diff --git a/daemon/src/client/callmanager.cpp b/daemon/src/client/callmanager.cpp
index feea893e1a409fdc30e3ac5af8288d534b6127f2..435dc29e31136270d1415a50d4634ecaf87bfb21 100644
--- a/daemon/src/client/callmanager.cpp
+++ b/daemon/src/client/callmanager.cpp
@@ -259,7 +259,11 @@ CallManager::getCallList()
 void
 CallManager::playDTMF(const std::string& key)
 {
-    Manager::instance().sendDtmf(Manager::instance().getCurrentCallId(), key.data()[0]);
+    auto code = key.data()[0];
+    Manager::instance().playDtmf(code);
+
+    if (auto current_call = Manager::instance().getCurrentCall())
+        current_call->carryingDTMFdigits(code);
 }
 
 void
diff --git a/daemon/src/iax/iaxcall.cpp b/daemon/src/iax/iaxcall.cpp
index 2a4f56c67d3166d96a0cc446ccc8fe93c3477261..e72627838e88adf6d4bd79a33290b65f57b71648 100644
--- a/daemon/src/iax/iaxcall.cpp
+++ b/daemon/src/iax/iaxcall.cpp
@@ -140,7 +140,7 @@ int IAXCall::getAudioCodec() const
 void
 IAXCall::answer()
 {
-    Manager::instance().addStream(getCallId());
+    Manager::instance().addStream(*this);
 
     {
         std::lock_guard<std::mutex> lock(IAXVoIPLink::mutexIAX);
@@ -207,7 +207,7 @@ IAXCall::onhold()
 void
 IAXCall::offhold()
 {
-    Manager::instance().addStream(getCallId());
+    Manager::instance().addStream(*this);
 
     {
         std::lock_guard<std::mutex> lock(IAXVoIPLink::mutexIAX);
diff --git a/daemon/src/iax/iaxvoiplink.cpp b/daemon/src/iax/iaxvoiplink.cpp
index ba1eb9b7e711df90b7a833bcc27d992174a71c63..47ed7c7f3c6e5d96655b6f80bb4d89f495a09199 100644
--- a/daemon/src/iax/iaxvoiplink.cpp
+++ b/daemon/src/iax/iaxvoiplink.cpp
@@ -207,7 +207,7 @@ IAXVoIPLink::handleReject(IAXCall& call)
 {
     call.setConnectionState(Call::CONNECTED);
     call.setState(Call::MERROR);
-    Manager::instance().callFailure(call.getCallId());
+    Manager::instance().callFailure(call);
     call.removeCall();
 }
 
@@ -230,9 +230,8 @@ IAXVoIPLink::handleAnswerTransfer(iax_event* event, IAXCall& call)
     if (event->ies.format)
         call.format = event->ies.format;
 
-    const auto& id = call.getCallId();
-    Manager::instance().addStream(id);
-    Manager::instance().peerAnsweredCall(id);
+    Manager::instance().addStream(call);
+    Manager::instance().peerAnsweredCall(call);
     Manager::instance().startAudioDriverStream();
     Manager::instance().getRingBufferPool().flushAllBuffers();
 }
@@ -243,7 +242,7 @@ IAXVoIPLink::handleBusy(IAXCall& call)
     call.setConnectionState(Call::CONNECTED);
     call.setState(Call::BUSY);
 
-    Manager::instance().callBusy(call.getCallId());
+    Manager::instance().callBusy(call);
     call.removeCall();
 }
 
@@ -260,13 +259,13 @@ void
 IAXVoIPLink::handleRinging(IAXCall& call)
 {
     call.setConnectionState(Call::RINGING);
-    Manager::instance().peerRingingCall(call.getCallId());
+    Manager::instance().peerRingingCall(call);
 }
 
 void
 IAXVoIPLink::handleHangup(IAXCall& call)
 {
-    Manager::instance().peerHungupCall(call.getCallId());
+    Manager::instance().peerHungupCall(call);
     call.removeCall();
 }
 
@@ -426,8 +425,7 @@ void IAXVoIPLink::iaxHandlePrecallEvent(iax_event* event)
 
         case IAX_EVENT_HANGUP:
             if (auto raw_call_ptr = iaxGetCallFromSession(event->session)) {
-                id = raw_call_ptr->getCallId();
-                Manager::instance().peerHungupCall(id);
+                Manager::instance().peerHungupCall(*raw_call_ptr);
                 raw_call_ptr->removeCall();
             }
 
diff --git a/daemon/src/managerimpl.cpp b/daemon/src/managerimpl.cpp
index 0f3cd20cec164ffdd7fff5f6406ee617d7a5327b..760bcf170b108eebd4a4daf50f1dbd5b6a1e5fd6 100644
--- a/daemon/src/managerimpl.cpp
+++ b/daemon/src/managerimpl.cpp
@@ -379,32 +379,35 @@ ManagerImpl::outgoingCall(const std::string& preferred_account_id,
             detachParticipant(sfl::RingBufferPool::DEFAULT_ID);
     }
 
+    std::shared_ptr<Call> call;
+
     try {
         /* SFL_WARN: after this call the account_id is obsolete
          * as the factory may decide to use another account (like IP2IP).
          */
         SFL_DBG("New outgoing call to %s", to_cleaned.c_str());
-        auto call = newOutgoingCall(call_id, to_cleaned, preferred_account_id);
-
-        // try to reverse match the peer name using the cache
-        if (call->getDisplayName().empty()) {
-            const auto& name = history_.getNameFromHistory(call->getPeerNumber(),
-                                                           call->getAccountId());
-            const std::string pseudo_contact_name(name);
-            if (not pseudo_contact_name.empty())
-                call->setDisplayName(pseudo_contact_name);
-        }
-        switchCall(call);
-        call->setConfId(conf_id);
+        call = newOutgoingCall(call_id, to_cleaned, preferred_account_id);
     } catch (ost::Socket *) {
-        callFailure(call_id);
         SFL_ERR("Could not bind socket");
         return false;
     } catch (const std::exception &e) {
-        callFailure(call_id);
         SFL_ERR("%s", e.what());
         return false;
     }
+
+    if (not call)
+        return false;
+
+    // try to reverse match the peer name using the cache
+    if (call->getDisplayName().empty()) {
+        const auto& name = history_.getNameFromHistory(call->getPeerNumber(),
+                                                       call->getAccountId());
+        const std::string pseudo_contact_name(name);
+        if (not pseudo_contact_name.empty())
+            call->setDisplayName(pseudo_contact_name);
+    }
+    switchCall(call);
+    call->setConfId(conf_id);
     return true;
 }
 
@@ -458,7 +461,7 @@ ManagerImpl::answerCall(const std::string& call_id)
         switchCall(call);
 
     // Connect streams
-    addStream(call_id);
+    addStream(*call);
 
     // Start recording if set in preference
     if (audioPreference.getIsAlwaysRecording())
@@ -500,7 +503,7 @@ ManagerImpl::hangupCall(const std::string& callId)
     }
 
     // Disconnect streams
-    removeStream(callId);
+    removeStream(*call);
 
     if (isConferenceParticipant(callId)) {
         removeParticipant(callId);
@@ -559,21 +562,19 @@ ManagerImpl::onHoldCall(const std::string& callId)
 
     std::string current_call_id(getCurrentCallId());
 
-    try {
-        if (auto call = getCallFromCallID(callId)) {
+    if (auto call = getCallFromCallID(callId)) {
+        try {
             call->onhold();
-        } else {
-            SFL_DBG("CallID %s doesn't exist in call onHold", callId.c_str());
-            return false;
+            removeStream(*call); // Unbind calls in main buffer
+        } catch (const VoipLinkException &e) {
+            SFL_ERR("%s", e.what());
+            result = false;
         }
-    } catch (const VoipLinkException &e) {
-        SFL_ERR("%s", e.what());
-        result = false;
+    } else {
+        SFL_DBG("CallID %s doesn't exist in call onHold", callId.c_str());
+        return false;
     }
 
-    // Unbind calls in main buffer
-    removeStream(callId);
-
     // Remove call from teh queue if it was still there
     removeWaitingCall(callId);
 
@@ -627,7 +628,7 @@ ManagerImpl::offHoldCall(const std::string& callId)
     else
         switchCall(call);
 
-    addStream(callId);
+    addStream(*call);
 
     return result;
 }
@@ -698,7 +699,7 @@ ManagerImpl::refuseCall(const std::string& id)
     client_.getCallManager()->callStateChanged(id, "HUNGUP");
 
     // Disconnect streams
-    removeStream(id);
+    removeStream(*call);
 
     return true;
 }
@@ -918,7 +919,7 @@ ManagerImpl::addParticipant(const std::string& callId,
         SFL_ERR("Participant list is empty for this conference");
 
     // Connect stream
-    addStream(callId);
+    addStream(*call);
     return true;
 }
 
@@ -1207,7 +1208,7 @@ ManagerImpl::removeParticipant(const std::string& call_id)
     conf->remove(call_id);
     call->setConfId("");
 
-    removeStream(call_id);
+    removeStream(*call);
 
     client_.getCallManager()->conferenceChanged(conf->getConfID(), conf->getStateStr());
 
@@ -1276,22 +1277,20 @@ ManagerImpl::joinConference(const std::string& conf_id1,
 }
 
 void
-ManagerImpl::addStream(const std::string& call_id)
+ManagerImpl::addStream(Call& call)
 {
+    const auto call_id = call.getCallId();
     SFL_DBG("Add audio stream %s", call_id.c_str());
-    auto call = getCallFromCallID(call_id);
-    if (call and isConferenceParticipant(call_id)) {
+
+    if (isConferenceParticipant(call_id)) {
         SFL_DBG("Add stream to conference");
 
         // bind to conference participant
-        ConferenceMap::iterator iter = conferenceMap_.find(call->getConfId());
-
+        ConferenceMap::iterator iter = conferenceMap_.find(call_id);
         if (iter != conferenceMap_.end() and iter->second) {
             auto conf = iter->second;
-
             conf->bindParticipant(call_id);
         }
-
     } else {
         SFL_DBG("Add stream to call");
 
@@ -1309,8 +1308,9 @@ ManagerImpl::addStream(const std::string& call_id)
 }
 
 void
-ManagerImpl::removeStream(const std::string& call_id)
+ManagerImpl::removeStream(Call& call)
 {
+    const auto call_id = call.getCallId();
     SFL_DBG("Remove audio stream %s", call_id.c_str());
     getRingBufferPool().unBindAll(call_id);
 }
@@ -1384,20 +1384,6 @@ ManagerImpl::saveConfig()
     }
 }
 
-//THREAD=Main
-void
-ManagerImpl::sendDtmf(const std::string& id, char code)
-{
-    playDtmf(code);
-
-    // return if we're not "in" a call
-    if (id.empty())
-        return;
-
-    if (auto call = getCallFromCallID(id))
-        call->carryingDTMFdigits(code);
-}
-
 //THREAD=Main | VoIPLink
 void
 ManagerImpl::playDtmf(char code)
@@ -1617,18 +1603,17 @@ ManagerImpl::sendTextMessage(const std::string& callID,
 
 //THREAD=VoIP CALL=Outgoing
 void
-ManagerImpl::peerAnsweredCall(const std::string& id)
+ManagerImpl::peerAnsweredCall(Call& call)
 {
-    auto call = getCallFromCallID(id);
-    if (!call) return;
-    SFL_DBG("Peer answered call %s", id.c_str());
+    const auto call_id = call.getCallId();
+    SFL_DBG("Peer answered call %s", call_id.c_str());
 
     // The if statement is usefull only if we sent two calls at the same time.
-    if (isCurrentCall(*call))
+    if (isCurrentCall(call))
         stopTone();
 
     // Connect audio streams
-    addStream(id);
+    addStream(call);
 
     if (audiodriver_) {
         std::lock_guard<std::mutex> lock(audioLayerMutex_);
@@ -1637,43 +1622,40 @@ ManagerImpl::peerAnsweredCall(const std::string& id)
     }
 
     if (audioPreference.getIsAlwaysRecording())
-        toggleRecordingCall(id);
+        toggleRecordingCall(call_id);
 
-    client_.getCallManager()->callStateChanged(id, "CURRENT");
+    client_.getCallManager()->callStateChanged(call_id, "CURRENT");
 }
 
 //THREAD=VoIP Call=Outgoing
 void
-ManagerImpl::peerRingingCall(const std::string& id)
+ManagerImpl::peerRingingCall(Call& call)
 {
-    auto call = getCallFromCallID(id);
-    if (!call) return;
-    SFL_DBG("Peer call %s ringing", id.c_str());
+    const auto call_id = call.getCallId();
+    SFL_DBG("Peer call %s ringing", call_id.c_str());
 
-    if (isCurrentCall(*call))
+    if (isCurrentCall(call))
         ringback();
 
-    client_.getCallManager()->callStateChanged(id, "RINGING");
+    client_.getCallManager()->callStateChanged(call_id, "RINGING");
 }
 
 //THREAD=VoIP Call=Outgoing/Ingoing
 void
-ManagerImpl::peerHungupCall(const std::string& call_id)
+ManagerImpl::peerHungupCall(Call& call)
 {
-    auto call = getCallFromCallID(call_id);
-    if (!call) return;
-
+    const auto call_id = call.getCallId();
     SFL_DBG("Peer hungup call %s", call_id.c_str());
 
     if (isConferenceParticipant(call_id)) {
         removeParticipant(call_id);
-    } else if (isCurrentCall(*call)) {
+    } else if (isCurrentCall(call)) {
         stopTone();
         unsetCurrentCall();
     }
 
-    history_.addCall(call.get(), preferences.getHistoryLimit());
-    call->peerHungup();
+    history_.addCall(&call, preferences.getHistoryLimit());
+    call.peerHungup();
     saveHistory();
 
     client_.getCallManager()->callStateChanged(call_id, "HUNGUP");
@@ -1683,37 +1665,35 @@ ManagerImpl::peerHungupCall(const std::string& call_id)
     if (not incomingCallsWaiting())
         stopTone();
 
-    removeStream(call_id);
+    removeStream(call);
 }
 
 //THREAD=VoIP
 void
-ManagerImpl::callBusy(const std::string& id)
+ManagerImpl::callBusy(Call& call)
 {
-    auto call = getCallFromCallID(id);
-    if (!call) return;
+    const auto call_id = call.getCallId();
 
-    client_.getCallManager()->callStateChanged(id, "BUSY");
+    client_.getCallManager()->callStateChanged(call_id, "BUSY");
 
-    if (isCurrentCall(*call)) {
+    if (isCurrentCall(call)) {
         playATone(sfl::Tone::TONE_BUSY);
         unsetCurrentCall();
     }
 
     checkAudio();
-    removeWaitingCall(id);
+    removeWaitingCall(call_id);
 }
 
 //THREAD=VoIP
 void
-ManagerImpl::callFailure(const std::string& call_id)
+ManagerImpl::callFailure(Call& call)
 {
-    client_.getCallManager()->callStateChanged(call_id, "FAILURE");
+    const auto call_id = call.getCallId();
 
-    auto call = getCallFromCallID(call_id);
-    if (!call) return;
+    client_.getCallManager()->callStateChanged(call_id, "FAILURE");
 
-    if (isCurrentCall(*call)) {
+    if (isCurrentCall(call)) {
         playATone(Tone::TONE_BUSY);
         unsetCurrentCall();
     }
diff --git a/daemon/src/managerimpl.h b/daemon/src/managerimpl.h
index d665bb31f229bd0df58b3d2b9c1819699296e6ce..5dfa2cb4d095facda2bf2939bc35ae1ff4325d52 100644
--- a/daemon/src/managerimpl.h
+++ b/daemon/src/managerimpl.h
@@ -322,9 +322,9 @@ class ManagerImpl {
          */
         bool joinConference(const std::string& conf_id1, const std::string& conf_id2);
 
-        void addStream(const std::string& call_id);
+        void addStream(Call& call);
 
-        void removeStream(const std::string& call_id);
+        void removeStream(Call& call);
 
         /**
          * Save config to file
@@ -336,13 +336,6 @@ class ManagerImpl {
          */
         bool hasTriedToRegister_;
 
-        /**
-         * Handle choice of the DTMF-send-way
-         * @param   id: callid of the line.
-         * @param   code: pressed key.
-         */
-        void sendDtmf(const std::string& id, char code);
-
         /**
          * Play a ringtone
          */
@@ -370,20 +363,20 @@ class ManagerImpl {
          * call in Current state
          * @param id  The call identifier
          */
-        void peerAnsweredCall(const std::string& id);
+        void peerAnsweredCall(Call& call);
 
         /**
          * Rings back because the outgoing call is ringing and the put the
          * call in Ringing state
          * @param id  The call identifier
          */
-        void peerRingingCall(const std::string& id);
+        void peerRingingCall(Call& call);
 
         /**
          * Put the call in Hungup state, remove the call from the list
          * @param id  The call identifier
          */
-        void peerHungupCall(const std::string& id);
+        void peerHungupCall(Call& call);
 
 #if HAVE_INSTANT_MESSAGING
         /**
@@ -689,15 +682,21 @@ class ManagerImpl {
          */
         void congestion();
 
+        /**
+         * Play the dtmf-associated sound
+         * @param code  The pressed key
+         */
+        void playDtmf(char code);
+
         /**
          * Handle played sound when a call can not be conpleted because of a busy recipient
          */
-        void callBusy(const std::string& id);
+        void callBusy(Call& call);
 
         /**
          * Handle played sound when a failure occurs
          */
-        void callFailure(const std::string& id);
+        void callFailure(Call& call);
 
         /**
          * Retrieve the current telephone tone
@@ -754,12 +753,6 @@ class ManagerImpl {
         const AudioCodecFactory audioCodecFactory;
 
     private:
-        /**
-         * Play the dtmf-associated sound
-         * @param code  The pressed key
-         */
-        void playDtmf(char code);
-
         void removeAccounts();
 
         bool parseConfiguration();
diff --git a/daemon/src/ringdht/ringaccount.cpp b/daemon/src/ringdht/ringaccount.cpp
index c1c06217bfa0314466f2ca70bf67c0811a5dfe34..fcb01f2fa049166d945c63d5ef583a5fdbcd74b0 100644
--- a/daemon/src/ringdht/ringaccount.cpp
+++ b/daemon/src/ringdht/ringaccount.cpp
@@ -169,7 +169,7 @@ RingAccount::newOutgoingCall(const std::string& id, const std::string& toUrl)
             auto& this_ = *std::static_pointer_cast<RingAccount>(shared).get();
             if (!ok) {
                 call->setConnectionState(Call::DISCONNECTED);
-                Manager::instance().callFailure(call->getCallId());
+                Manager::instance().callFailure(*call);
             }
             this_.dht_.cancelPut(callkey, callvid);
         }
@@ -193,7 +193,7 @@ RingAccount::newOutgoingCall(const std::string& id, const std::string& toUrl)
                 ice->start(v->data);
                 if (call->waitForIceNegotiation(ICE_NEGOTIATION_TIMEOUT) <= 0) {
                     call->setConnectionState(Call::DISCONNECTED);
-                    Manager::instance().callFailure(call->getCallId());
+                    Manager::instance().callFailure(*call);
                     return false;
                 }
                 call->setConnectionState(Call::PROGRESSING);
@@ -650,7 +650,7 @@ void RingAccount::doRegister()
                                 if (!ok || call->waitForIceNegotiation(ICE_NEGOTIATION_TIMEOUT) <= 0) {
                                     SFL_WARN("nego failed");
                                     call->setConnectionState(Call::DISCONNECTED);
-                                    Manager::instance().callFailure(call->getCallId());
+                                    Manager::instance().callFailure(*call);
                                 } else {
                                     SFL_WARN("nego succeeded");
                                     call->setConnectionState(Call::PROGRESSING);
diff --git a/daemon/src/sip/sipcall.cpp b/daemon/src/sip/sipcall.cpp
index 58573aa18db71ca90b5a8ad243d6f6598a70bb9b..61fe782fd430bab40721fb8468546d9096e83509 100644
--- a/daemon/src/sip/sipcall.cpp
+++ b/daemon/src/sip/sipcall.cpp
@@ -754,16 +754,14 @@ SIPCall::sendTextMessage(const std::string &message, const std::string &from)
 void
 SIPCall::onServerFailure()
 {
-    const std::string id(getCallId());
-    Manager::instance().callFailure(id);
+    Manager::instance().callFailure(*this);
     removeCall();
 }
 
 void
 SIPCall::onClosed()
 {
-    const std::string id(getCallId());
-    Manager::instance().peerHungupCall(id);
+    Manager::instance().peerHungupCall(*this);
     removeCall();
     Manager::instance().checkAudio();
 }
@@ -777,7 +775,7 @@ SIPCall::onAnswered()
         startAllMedia();
         setConnectionState(Call::CONNECTED);
         setState(Call::ACTIVE);
-        Manager::instance().peerAnsweredCall(getCallId());
+        Manager::instance().peerAnsweredCall(*this);
     }
 }
 
diff --git a/daemon/src/sip/sipvoiplink.cpp b/daemon/src/sip/sipvoiplink.cpp
index 1be1ea63d22e4c9944ff4b79835834fe64a54c84..bfb43b57e5a41111cdc489dea122d7fad42185b6 100644
--- a/daemon/src/sip/sipvoiplink.cpp
+++ b/daemon/src/sip/sipvoiplink.cpp
@@ -829,7 +829,7 @@ static void
 makeCallRing(SIPCall &call)
 {
     call.setConnectionState(Call::RINGING);
-    Manager::instance().peerRingingCall(call.getCallId());
+    Manager::instance().peerRingingCall(call);
 }
 
 static void
@@ -1017,9 +1017,8 @@ sdp_media_update_cb(pjsip_inv_session *inv, pj_status_t status)
                            PJSIP_SC_UNSUPPORTED_MEDIA_TYPE : 0;
 
         SFL_WARN("Could not negotiate offer");
-        const std::string callID(call->getCallId());
         call->hangup(reason);
-        Manager::instance().callFailure(callID);
+        Manager::instance().callFailure(*call);
         return;
     }