diff --git a/bin/dbus/cx.ring.Ring.CallManager.xml b/bin/dbus/cx.ring.Ring.CallManager.xml index 5835a672aa2b86b161ff2da801eaa1571ef7f224..3a8de89028a2020a185656247e2c5bb74ef43a09 100644 --- a/bin/dbus/cx.ring.Ring.CallManager.xml +++ b/bin/dbus/cx.ring.Ring.CallManager.xml @@ -242,6 +242,16 @@ <arg type="b" name="addSucceeded" direction="out"/> </method> + <method name="detachLocalParticipant" tp:name-for-bindings="detachLocalParticipant"> + <tp:added version="3.0.0"/> + <tp:docstring> + Detach local participant from the conference. + Remote participants are placed in hold. + The signal <tp:member-ref>conferenceChanged</tp:member-ref> is emited. + </tp:docstring> + <arg type="b" name="detachSucceeded" direction="out"/> + </method> + <method name="detachParticipant" tp:name-for-bindings="detachParticipant"> <tp:added version="0.9.7"/> <tp:docstring> diff --git a/bin/dbus/dbuscallmanager.cpp b/bin/dbus/dbuscallmanager.cpp index 94bfd42d11e1d70b72b97532b35c3713e8939565..ba13e13fd99f55d3adf3250d6387ea3cab26e58c 100644 --- a/bin/dbus/dbuscallmanager.cpp +++ b/bin/dbus/dbuscallmanager.cpp @@ -128,6 +128,12 @@ DBusCallManager::addMainParticipant(const std::string& confID) -> decltype(DRing return DRing::addMainParticipant(confID); } +auto +DBusCallManager::detachLocalParticipant() -> decltype(DRing::detachLocalParticipant()) +{ + return DRing::detachLocalParticipant(); +} + auto DBusCallManager::detachParticipant(const std::string& callID) -> decltype(DRing::detachParticipant(callID)) { diff --git a/bin/dbus/dbuscallmanager.h b/bin/dbus/dbuscallmanager.h index 387e2a8df9cb4a9f274f0768912814ae48d9dafd..db70c044c65c665c6647187b93281d76055b6763 100644 --- a/bin/dbus/dbuscallmanager.h +++ b/bin/dbus/dbuscallmanager.h @@ -71,6 +71,7 @@ class DBusCallManager : bool isConferenceParticipant(const std::string& call_id); bool addParticipant(const std::string& callID, const std::string& confID); bool addMainParticipant(const std::string& confID); + bool detachLocalParticipant(); bool detachParticipant(const std::string& callID); bool joinConference(const std::string& sel_confID, const std::string& drag_confID); bool hangUpConference(const std::string& confID); diff --git a/src/client/callmanager.cpp b/src/client/callmanager.cpp index 9d807863da991ea0516c50c43a3e8dc816d9f4c6..b0d43b82a32c89e003ce7bb3781ce36dc1e806bb 100644 --- a/src/client/callmanager.cpp +++ b/src/client/callmanager.cpp @@ -168,6 +168,12 @@ addMainParticipant(const std::string& confID) return ring::Manager::instance().addMainParticipant(confID); } +bool +detachLocalParticipant() +{ + return ring::Manager::instance().detachLocalParticipant(); +} + bool detachParticipant(const std::string& callID) { diff --git a/src/dring/callmanager_interface.h b/src/dring/callmanager_interface.h index fa578a68c521ac47727cd59f0a3d819773acfd94..2b6a54999708d819ca6d26e819270d00ec3e31cc 100644 --- a/src/dring/callmanager_interface.h +++ b/src/dring/callmanager_interface.h @@ -56,6 +56,7 @@ void createConfFromParticipantList(const std::vector<std::string>& participants) bool isConferenceParticipant(const std::string& call_id); bool addParticipant(const std::string& callID, const std::string& confID); bool addMainParticipant(const std::string& confID); +bool detachLocalParticipant(); bool detachParticipant(const std::string& callID); bool joinConference(const std::string& sel_confID, const std::string& drag_confID); bool hangUpConference(const std::string& confID); diff --git a/src/manager.cpp b/src/manager.cpp index e3f91c25f43b9645bdb0ed0cff09d6b9587f4067..5fb44feb9898f7363cf23659ad79410e3b01e81e 100644 --- a/src/manager.cpp +++ b/src/manager.cpp @@ -509,7 +509,7 @@ Manager::outgoingCall(const std::string& preferred_account_id, if (not isConference(current_call_id) and not isConferenceParticipant(current_call_id)) onHoldCall(current_call_id); else if (isConference(current_call_id) and not isConferenceParticipant(call_id)) - detachParticipant(RingBufferPool::DEFAULT_ID); + detachLocalParticipant(); } switchCall(call); @@ -547,7 +547,7 @@ Manager::answerCall(const std::string& call_id) } else if (isConference(current_call_id) and not isConferenceParticipant(call_id)) { // if we are talking to a conference and we are answering an incoming call RING_DBG("Detach main participant from conference"); - detachParticipant(RingBufferPool::DEFAULT_ID); + detachLocalParticipant(); } } @@ -706,7 +706,7 @@ Manager::offHoldCall(const std::string& callId) onHoldCall(currentCallId); } else if (isConference(currentCallId) and not isConferenceParticipant(callId)) { holdConference(currentCallId); - detachParticipant(RingBufferPool::DEFAULT_ID); + detachLocalParticipant(); } } @@ -971,7 +971,7 @@ Manager::addParticipant(const std::string& callId, // detach from prior communication and switch to this conference if (current_call_id != callId) { if (isConference(current_call_id)) - detachParticipant(RingBufferPool::DEFAULT_ID); + detachLocalParticipant(); else onHoldCall(current_call_id); } @@ -1022,7 +1022,7 @@ Manager::addMainParticipant(const std::string& conference_id) std::string current_call_id(getCurrentCallId()); if (isConference(current_call_id)) - detachParticipant(RingBufferPool::DEFAULT_ID); + detachLocalParticipant(); else onHoldCall(current_call_id); } @@ -1127,7 +1127,7 @@ Manager::joinParticipant(const std::string& callId1, const std::string& callId2) auto current_call_id = getCurrentCallId(); if ((current_call_id != callId1) and (current_call_id != callId2)) { if (isConference(current_call_id)) - detachParticipant(RingBufferPool::DEFAULT_ID); + detachLocalParticipant(); else onHoldCall(current_call_id); // currently in a call } @@ -1191,67 +1191,63 @@ Manager::createConfFromParticipantList(const std::vector< std::string > &partici } bool -Manager::detachParticipant(const std::string& call_id) +Manager::detachLocalParticipant() { - const std::string current_call_id(getCurrentCallId()); - - if (call_id != RingBufferPool::DEFAULT_ID) { - auto call = getCallFromCallID(call_id); - if (!call) { - RING_ERR("Could not find call %s", call_id.c_str()); - return false; - } - - auto conf = getConferenceFromCallID(call_id); - - if (conf == nullptr) { - RING_ERR("Call is not conferencing, cannot detach"); - return false; - } - - std::map<std::string, std::string> call_details(getCallDetails(call_id)); - std::map<std::string, std::string>::iterator iter_details(call_details.find("CALL_STATE")); - - if (iter_details == call_details.end()) { - RING_ERR("Could not find CALL_STATE"); - return false; - } - - // Don't hold ringing calls when detaching them from conferences - if (iter_details->second != "RINGING") - onHoldCall(call_id); - - removeParticipant(call_id); - - } else { - RING_DBG("Unbind main participant from conference"); - getRingBufferPool().unBindAll(RingBufferPool::DEFAULT_ID); + RING_DBG("Unbind local participant from conference"); + const auto& current_call_id = getCurrentCallId(); - if (not isConference(current_call_id)) { - RING_ERR("Current call id (%s) is not a conference", current_call_id.c_str()); - return false; - } + if (not isConference(current_call_id)) { + RING_ERR("Current call id (%s) is not a conference", current_call_id.c_str()); + return false; + } - ConferenceMap::iterator iter = conferenceMap_.find(current_call_id); + auto iter = conferenceMap_.find(current_call_id); + if (iter == conferenceMap_.end() or iter->second == nullptr) { + RING_ERR("Conference is NULL"); + return false; + } - auto conf = iter->second; - if (iter == conferenceMap_.end() or conf == 0) { - RING_DBG("Conference is NULL"); - return false; - } + getRingBufferPool().unBindAll(RingBufferPool::DEFAULT_ID); - if (conf->getState() == Conference::ACTIVE_ATTACHED) + auto conf = iter->second; + switch (conf->getState()) { + case Conference::ACTIVE_ATTACHED: conf->setState(Conference::ACTIVE_DETACHED); - else if (conf->getState() == Conference::ACTIVE_ATTACHED_REC) + break; + case Conference::ACTIVE_ATTACHED_REC: conf->setState(Conference::ACTIVE_DETACHED_REC); - else + break; + default: RING_WARN("Undefined behavior, invalid conference state in detach participant"); + } - emitSignal<DRing::CallSignal::ConferenceChanged>(conf->getConfID(), conf->getStateStr()); + emitSignal<DRing::CallSignal::ConferenceChanged>(conf->getConfID(), conf->getStateStr()); - unsetCurrentCall(); + unsetCurrentCall(); +} + +bool +Manager::detachParticipant(const std::string& call_id) +{ + RING_DBG("Detach participant %s", call_id.c_str()); + + auto call = getCallFromCallID(call_id); + if (!call) { + RING_ERR("Could not find call %s", call_id.c_str()); + return false; + } + + auto conf = getConferenceFromCallID(call_id); + if (!conf) { + RING_ERR("Call is not conferencing, cannot detach"); + return false; } + // Don't hold ringing calls when detaching them from conferences + if (call->getStateStr() != "RINGING") + onHoldCall(call_id); + + removeParticipant(call_id); return true; } diff --git a/src/manager.h b/src/manager.h index ef4a36d2602047221d8625d52cc8c05e7e0d1dce..88f24910841c0ef5730985ee2057fcff8683f7c2 100644 --- a/src/manager.h +++ b/src/manager.h @@ -308,6 +308,12 @@ class Manager { */ bool detachParticipant(const std::string& call_id); + /** + * Detach the local participant from curent conference. + * Remote participants are placed in hold. + */ + bool detachLocalParticipant(); + /** * Remove the conference participant from a conference * @param call id