diff --git a/bin/dbus/cx.ring.Ring.CallManager.xml b/bin/dbus/cx.ring.Ring.CallManager.xml index f44b4978581fc49d775c7c404919be7690504823..6178ae67e6644627850a5a233e3cb533d1de7840 100644 --- a/bin/dbus/cx.ring.Ring.CallManager.xml +++ b/bin/dbus/cx.ring.Ring.CallManager.xml @@ -904,9 +904,10 @@ Emitted when a new conference is created. Client is responsible for storing the confID and call <tp:member-ref>getParticipantList</tp:member-ref> to update the display. </tp:docstring> <arg type="s" name="accountId" /> - <arg type="s" name="confID"> + <arg type="s" name="conversationId" /> + <arg type="s" name="confId"> <tp:docstring> - A new conference ID. + A new conference Id. </tp:docstring> </arg> </signal> diff --git a/bin/dbus/dbuscallmanager.hpp b/bin/dbus/dbuscallmanager.hpp index 6b5630afdc1701cae9e843d219aed01afc8b769f..1fe65b7f70bdfb1397b84d58a6c3286f2c6832b3 100644 --- a/bin/dbus/dbuscallmanager.hpp +++ b/bin/dbus/dbuscallmanager.hpp @@ -489,7 +489,7 @@ private: exportable_serialized_callback<CallSignal::RecordPlaybackFilepath>( std::bind(&DBusCallManager::emitRecordPlaybackFilepath, this, _1, _2)), exportable_serialized_callback<CallSignal::ConferenceCreated>( - std::bind(&DBusCallManager::emitConferenceCreated, this, _1, _2)), + std::bind(&DBusCallManager::emitConferenceCreated, this, _1, _2, _3)), exportable_serialized_callback<CallSignal::ConferenceChanged>( std::bind(&DBusCallManager::emitConferenceChanged, this, _1, _2, _3)), exportable_serialized_callback<CallSignal::UpdatePlaybackScale>( diff --git a/bin/jni/callmanager.i b/bin/jni/callmanager.i index b197107b7732f416858439170efd7ddc264f677e..96c52814f16ab9924ec325eeb20dcf7e4301c865 100644 --- a/bin/jni/callmanager.i +++ b/bin/jni/callmanager.i @@ -40,7 +40,7 @@ public: virtual void mediaChangeRequested(const std::string& accountId, const std::string& callId, const std::vector<std::map<std::string, std::string>>& mediaList){} virtual void recordPlaybackFilepath(const std::string& id, const std::string& filename){} - virtual void conferenceCreated(const std::string& accountId, const std::string& confId){} + virtual void conferenceCreated(const std::string& accountId, const std::string& conversationId, const std::string& confId){} virtual void conferenceChanged(const std::string& accountId, const std::string& confId, const std::string& state){} virtual void conferenceRemoved(const std::string& accountId, const std::string& confId){} virtual void updatePlaybackScale(const std::string& filepath, int position, int scale){} @@ -164,7 +164,7 @@ public: virtual void mediaChangeRequested(const std::string& accountId, const std::string& callId, const std::vector<std::map<std::string, std::string>>& mediaList){} virtual void recordPlaybackFilepath(const std::string& id, const std::string& filename){} - virtual void conferenceCreated(const std::string& accountId, const std::string& confId){} + virtual void conferenceCreated(const std::string& accountId, const std::string& conversationId, const std::string& confId){} virtual void conferenceChanged(const std::string& accountId, const std::string& confId, const std::string& state){} virtual void conferenceRemoved(const std::string& accountId, const std::string& confId){} virtual void updatePlaybackScale(const std::string& filepath, int position, int scale){} diff --git a/bin/jni/jni_interface.i b/bin/jni/jni_interface.i index d2b4e166fce874516b083140d0fb2f64f3850df3..90da5cdeb01808bc8f432fb1b2091e2e78355b33 100644 --- a/bin/jni/jni_interface.i +++ b/bin/jni/jni_interface.i @@ -248,7 +248,7 @@ void init(ConfigurationCallback* confM, Callback* callM, PresenceCallback* presM exportable_callback<CallSignal::IncomingCallWithMedia>(bind(&Callback::incomingCallWithMedia, callM, _1, _2, _3, _4)), exportable_callback<CallSignal::MediaChangeRequested>(bind(&Callback::mediaChangeRequested, callM, _1, _2, _3)), exportable_callback<CallSignal::RecordPlaybackFilepath>(bind(&Callback::recordPlaybackFilepath, callM, _1, _2)), - exportable_callback<CallSignal::ConferenceCreated>(bind(&Callback::conferenceCreated, callM, _1, _2)), + exportable_callback<CallSignal::ConferenceCreated>(bind(&Callback::conferenceCreated, callM, _1, _2, _3)), exportable_callback<CallSignal::ConferenceChanged>(bind(&Callback::conferenceChanged, callM, _1, _2, _3)), exportable_callback<CallSignal::ConferenceRemoved>(bind(&Callback::conferenceRemoved, callM, _1, _2)), exportable_callback<CallSignal::UpdatePlaybackScale>(bind(&Callback::updatePlaybackScale, callM, _1, _2, _3)), diff --git a/bin/nodejs/callback.h b/bin/nodejs/callback.h index e1299401a7d463fc9f3427d76c660e75144e66c2..4ec2e5923288606e1ddb1bd3a153798eecf50502 100644 --- a/bin/nodejs/callback.h +++ b/bin/nodejs/callback.h @@ -811,15 +811,16 @@ onConversationError(const std::string& accountId, } void -conferenceCreated(const std::string& accountId, const std::string& confId) +conferenceCreated(const std::string& accountId, const std::string& conversationId, const std::string& confId) { std::lock_guard lock(pendingSignalsLock); - pendingSignals.emplace([accountId, confId]() { + pendingSignals.emplace([accountId, confId, conversationId]() { Local<Function> func = Local<Function>::New(Isolate::GetCurrent(), conferenceCreatedCb); if (!func.IsEmpty()) { SWIGV8_VALUE callback_args[] = {V8_STRING_NEW_LOCAL(accountId), + V8_STRING_NEW_LOCAL(conversationId), V8_STRING_NEW_LOCAL(confId)}; - func->Call(SWIGV8_CURRENT_CONTEXT(), SWIGV8_NULL(), 2, callback_args); + func->Call(SWIGV8_CURRENT_CONTEXT(), SWIGV8_NULL(), 3, callback_args); } }); uv_async_send(&signalAsync); diff --git a/bin/nodejs/callmanager.i b/bin/nodejs/callmanager.i index b197107b7732f416858439170efd7ddc264f677e..96c52814f16ab9924ec325eeb20dcf7e4301c865 100644 --- a/bin/nodejs/callmanager.i +++ b/bin/nodejs/callmanager.i @@ -40,7 +40,7 @@ public: virtual void mediaChangeRequested(const std::string& accountId, const std::string& callId, const std::vector<std::map<std::string, std::string>>& mediaList){} virtual void recordPlaybackFilepath(const std::string& id, const std::string& filename){} - virtual void conferenceCreated(const std::string& accountId, const std::string& confId){} + virtual void conferenceCreated(const std::string& accountId, const std::string& conversationId, const std::string& confId){} virtual void conferenceChanged(const std::string& accountId, const std::string& confId, const std::string& state){} virtual void conferenceRemoved(const std::string& accountId, const std::string& confId){} virtual void updatePlaybackScale(const std::string& filepath, int position, int scale){} @@ -164,7 +164,7 @@ public: virtual void mediaChangeRequested(const std::string& accountId, const std::string& callId, const std::vector<std::map<std::string, std::string>>& mediaList){} virtual void recordPlaybackFilepath(const std::string& id, const std::string& filename){} - virtual void conferenceCreated(const std::string& accountId, const std::string& confId){} + virtual void conferenceCreated(const std::string& accountId, const std::string& conversationId, const std::string& confId){} virtual void conferenceChanged(const std::string& accountId, const std::string& confId, const std::string& state){} virtual void conferenceRemoved(const std::string& accountId, const std::string& confId){} virtual void updatePlaybackScale(const std::string& filepath, int position, int scale){} diff --git a/src/jami/callmanager_interface.h b/src/jami/callmanager_interface.h index f04ec7d9ccaa93fa465bdee3a1c6798664bab3ca..a3bcca9fedede6bf5ca92e3d4832e098fa4adc83 100644 --- a/src/jami/callmanager_interface.h +++ b/src/jami/callmanager_interface.h @@ -258,7 +258,7 @@ struct LIBJAMI_PUBLIC CallSignal struct LIBJAMI_PUBLIC ConferenceCreated { constexpr static const char* name = "ConferenceCreated"; - using cb_type = void(const std::string&, const std::string&); + using cb_type = void(const std::string&, const std::string&, const std::string&); }; struct LIBJAMI_PUBLIC ConferenceChanged { diff --git a/src/jamidht/conversation_module.cpp b/src/jamidht/conversation_module.cpp index 725848d3ed14ea5ceb9206c2b7086bbc9ce9e03e..fced6f2bf3bbff7d4638e8f8472d1e11da14508a 100644 --- a/src/jamidht/conversation_module.cpp +++ b/src/jamidht/conversation_module.cpp @@ -2858,10 +2858,10 @@ ConversationModule::getActiveCalls(const std::string& conversationId) const }); } -void +std::shared_ptr<SIPCall> ConversationModule::call(const std::string& url, - const std::shared_ptr<SIPCall>& call, - std::function<void(const std::string&, const DeviceId&)>&& cb) + const std::vector<libjami::MediaMap>& mediaList, + std::function<void(const std::string&, const DeviceId&, const std::shared_ptr<SIPCall>&)>&& cb) { std::string conversationId = "", confId = "", uri = "", deviceId = ""; if (url.find('/') == std::string::npos) { @@ -2870,7 +2870,7 @@ ConversationModule::call(const std::string& url, auto parameters = jami::split_string(url, '/'); if (parameters.size() != 4) { JAMI_ERROR("Incorrect url {:s}", url); - return; + return {}; } conversationId = parameters[0]; uri = parameters[1]; @@ -2878,36 +2878,14 @@ ConversationModule::call(const std::string& url, confId = parameters[3]; } - std::string callUri; - auto sendCall = [&]() { - call->setState(Call::ConnectionState::TRYING); - call->setPeerNumber(callUri); - call->setPeerUri("rdv:" + callUri); - call->addStateListener([w = pimpl_->weak(), conversationId](Call::CallState call_state, - Call::ConnectionState cnx_state, - int) { - if (cnx_state == Call::ConnectionState::DISCONNECTED - && call_state == Call::CallState::MERROR) { - auto shared = w.lock(); - if (!shared) - return false; - if (auto acc = shared->account_.lock()) - emitSignal<libjami::ConfigurationSignal::NeedsHost>(acc->getAccountID(), - conversationId); - return true; - } - return true; - }); - cb(callUri, DeviceId(deviceId)); - }; auto conv = pimpl_->getConversation(conversationId); if (!conv) - return; + return {}; std::unique_lock lk(conv->mtx); if (!conv->conversation) { JAMI_ERROR("Conversation {:s} not found", conversationId); - return; + return {}; } // Check if we want to join a specific conference @@ -2920,7 +2898,6 @@ ConversationModule::call(const std::string& url, auto sendCallRequest = false; if (confId != "") { sendCallRequest = true; - confId = confId == "0" ? Manager::instance().callFactory.getNewCallID() : confId; JAMI_DEBUG("Calling self, join conference"); } else if (!activeCalls.empty()) { // Else, we try to join active calls @@ -2929,7 +2906,6 @@ ConversationModule::call(const std::string& url, confId = ac.at("id"); uri = ac.at("uri"); deviceId = ac.at("device"); - JAMI_DEBUG("Calling last active call: {:s}", callUri); } else if (itRdvAccount != infos.end() && itRdvDevice != infos.end()) { // Else, creates "to" (accountId/deviceId/conversationId/confId) and ask remote host sendCallRequest = true; @@ -2938,65 +2914,100 @@ ConversationModule::call(const std::string& url, confId = "0"; JAMI_DEBUG("Remote host detected. Calling {:s} on device {:s}", uri, deviceId); } + lk.unlock(); - if (sendCallRequest) { - callUri = fmt::format("{}/{}/{}/{}", conversationId, uri, deviceId, confId); - if (uri == pimpl_->username_ && deviceId == pimpl_->deviceId_) { - // In this case, we're probably hosting the conference. - call->setState(Call::ConnectionState::CONNECTED); - // In this case, the call is the only one in the conference - // and there is no peer, so media succeeded and are shown to - // the client. - call->reportMediaNegotiationStatus(); - lk.unlock(); - if (confId == "0") - confId = call->getCallId(); - hostConference(conversationId, confId, call->getCallId(), true); - return; + if (!sendCallRequest + || (uri == pimpl_->username_ && deviceId == pimpl_->deviceId_)) { + confId = confId == "0" ? Manager::instance().callFactory.getNewCallID() : confId; + // TODO attach host with media list + hostConference(conversationId, confId, ""); + return {}; + } + + // Else we need to create a call + auto account = pimpl_->account_.lock(); + auto& manager = Manager::instance(); + std::shared_ptr<SIPCall> call; + + // SIP allows sending empty invites, this use case is not used with Jami accounts. + if (not mediaList.empty()) { + call = manager.callFactory.newSipCall(account, Call::CallType::OUTGOING, mediaList); + } else { + JAMI_WARN("Media list is empty, setting a default list"); + call = manager.callFactory.newSipCall(account, + Call::CallType::OUTGOING, + MediaAttribute::mediaAttributesToMediaMaps( + account->createDefaultMediaList(account->isVideoEnabled()))); + } + + if (not call) + return {}; + + auto callUri = fmt::format("{}/{}/{}/{}", conversationId, uri, deviceId, confId); + account->getIceOptions([call, accountId = account->getAccountID(), callUri, uri = std::move(uri), conversationId, deviceId, cb=std::move(cb)](auto&& opts) { + if (call->isIceEnabled()) { + if (not call->createIceMediaTransport(false) + or not call->initIceMediaTransport(true, + std::forward<dhtnet::IceTransportOptions>(opts))) { + return; + } } + JAMI_DEBUG("New outgoing call with {}", uri); + call->setPeerNumber(uri); + call->setPeerUri("swarm:" + uri); + JAMI_DEBUG("Calling: {:s}", callUri); - sendCall(); - return; - } + call->setState(Call::ConnectionState::TRYING); + call->setPeerNumber(callUri); + call->setPeerUri("rdv:" + callUri); + call->addStateListener([accountId, conversationId](Call::CallState call_state, + Call::ConnectionState cnx_state, + int) { + if (cnx_state == Call::ConnectionState::DISCONNECTED + && call_state == Call::CallState::MERROR) { + emitSignal<libjami::ConfigurationSignal::NeedsHost>(accountId, conversationId); + return true; + } + return true; + }); + cb(callUri, DeviceId(deviceId), call); + }); - // Else, we are the host. - confId = Manager::instance().callFactory.getNewCallID(); - call->setState(Call::ConnectionState::CONNECTED); - // In this case, the call is the only one in the conference - // and there is no peer, so media succeeded and are shown to - // the client. - call->reportMediaNegotiationStatus(); - lk.unlock(); - hostConference(conversationId, confId, call->getCallId(), true); + return call; } void ConversationModule::hostConference(const std::string& conversationId, const std::string& confId, - const std::string& callId, - bool local) + const std::string& callId) { auto acc = pimpl_->account_.lock(); if (!acc) return; - std::shared_ptr<Call> call; - call = acc->getCall(callId); - if (!call) { - JAMI_WARNING("No call with id {} found", callId); - return; - } auto conf = acc->getConference(confId); auto createConf = !conf; + std::shared_ptr<SIPCall> call; + if (!callId.empty()) { + call = std::dynamic_pointer_cast<SIPCall>(acc->getCall(callId)); + if (!call) { + JAMI_WARNING("No call with id {} found", callId); + return; + } + } if (createConf) { - conf = std::make_shared<Conference>(acc, confId, local, call->getMediaAttributeList()); + conf = std::make_shared<Conference>(acc, confId, callId.empty(), callId.empty()? std::vector<MediaAttribute> {} : call->getMediaAttributeList()); acc->attach(conf); } - conf->addParticipant(callId); + + if (!callId.empty()) + conf->addParticipant(callId); + + if (!createConf && callId.empty()) // TODO use mediaList + conf->attachLocalParticipant(); if (createConf) { - emitSignal<libjami::CallSignal::ConferenceCreated>(acc->getAccountID(), confId); + emitSignal<libjami::CallSignal::ConferenceCreated>(acc->getAccountID(), conversationId, confId); } else { - conf->attachLocalParticipant(); conf->reportMediaNegotiationStatus(); emitSignal<libjami::CallSignal::ConferenceChanged>(acc->getAccountID(), conf->getConfId(), @@ -3036,7 +3047,7 @@ ConversationModule::hostConference(const std::string& conversationId, // Master call, so when it's stopped, the conference will be stopped (as we use the hold // state for detaching the call) conf->onShutdown( - [w = pimpl_->weak(), accountUri = pimpl_->username_, confId, conversationId, call, conv]( + [w = pimpl_->weak(), accountUri = pimpl_->username_, confId, conversationId, conv]( int duration) { auto shared = w.lock(); if (shared) { diff --git a/src/jamidht/conversation_module.h b/src/jamidht/conversation_module.h index d01f9ccf16c7718bbcef39a97793c72ceb056fff..571808eeef994843eba1ebf37ef9f38e5878bf5a 100644 --- a/src/jamidht/conversation_module.h +++ b/src/jamidht/conversation_module.h @@ -450,16 +450,16 @@ public: /** * Call the conversation * @param url Url to call (swarm:conversation or swarm:conv/account/device/conf to join) - * @param call Call to use + * @param mediaList The media list * @param cb Callback to pass which device to call (called in the same thread) + * @return call if a call is started, else nullptr */ - void call(const std::string& url, - const std::shared_ptr<SIPCall>& call, - std::function<void(const std::string&, const DeviceId&)>&& cb); + std::shared_ptr<SIPCall> call(const std::string& url, + const std::vector<libjami::MediaMap>& mediaList, + std::function<void(const std::string&, const DeviceId&, const std::shared_ptr<SIPCall>&)>&& cb); void hostConference(const std::string& conversationId, const std::string& confId, - const std::string& callId, - bool local); + const std::string& callId); // The following methods modify what is stored on the disk static void saveConvInfos(const std::string& accountId, diff --git a/src/jamidht/jamiaccount.cpp b/src/jamidht/jamiaccount.cpp index 8e63f016fbec9f94afa254840ad9ecc7b4237475..0ee7fa9bd62ebe04dfe0232d73093422cf97bcfc 100644 --- a/src/jamidht/jamiaccount.cpp +++ b/src/jamidht/jamiaccount.cpp @@ -340,6 +340,13 @@ JamiAccount::newIncomingCall(const std::string& from, std::shared_ptr<Call> JamiAccount::newOutgoingCall(std::string_view toUrl, const std::vector<libjami::MediaMap>& mediaList) { + auto uri = Uri(toUrl); + if (uri.scheme() == Uri::Scheme::SWARM || uri.scheme() == Uri::Scheme::RENDEZVOUS) { + // NOTE: In this case newOutgoingCall can act as "unholdConference" and just attach the + // host to the current hosted conference. So, no call will be returned in that case. + return newSwarmOutgoingCallHelper(uri, mediaList); + } + auto& manager = Manager::instance(); std::shared_ptr<SIPCall> call; @@ -357,7 +364,6 @@ JamiAccount::newOutgoingCall(std::string_view toUrl, const std::vector<libjami:: if (not call) return {}; - auto uri = Uri(toUrl); connectionManager_->getIceOptions([call, w = weak(), uri = std::move(uri)](auto&& opts) { if (call->isIceEnabled()) { if (not call->createIceMediaTransport(false) @@ -373,10 +379,7 @@ JamiAccount::newOutgoingCall(std::string_view toUrl, const std::vector<libjami:: call->setPeerNumber(uri.authority()); call->setPeerUri(uri.toString()); - if (uri.scheme() == Uri::Scheme::SWARM || uri.scheme() == Uri::Scheme::RENDEZVOUS) - shared->newSwarmOutgoingCallHelper(call, uri); - else - shared->newOutgoingCallHelper(call, uri); + shared->newOutgoingCallHelper(call, uri); }); return call; @@ -419,16 +422,17 @@ JamiAccount::newOutgoingCallHelper(const std::shared_ptr<SIPCall>& call, const U } } -void -JamiAccount::newSwarmOutgoingCallHelper(const std::shared_ptr<SIPCall>& call, const Uri& uri) -{ - JAMI_DBG("[Account %s] Calling conversation %s", - getAccountID().c_str(), - uri.authority().c_str()); - convModule()->call( - uri.authority(), - call, - [this, uri, call](const std::string& accountUri, const DeviceId& deviceId) { +std::shared_ptr<SIPCall> +JamiAccount::newSwarmOutgoingCallHelper(const Uri& uri, const std::vector<libjami::MediaMap>& mediaList) +{ + JAMI_DEBUG("[Account {}] Calling conversation {}", + getAccountID(), + uri.authority()); + return convModule()->call( + uri.authority(), mediaList, + [this, uri](const auto& accountUri, const auto& deviceId, const auto& call) { + if (!call) + return; std::unique_lock lkSipConn(sipConnsMtx_); for (auto& [key, value] : sipConns_) { if (key.first != accountUri || key.second != deviceId) @@ -469,8 +473,8 @@ JamiAccount::newSwarmOutgoingCallHelper(const std::shared_ptr<SIPCall>& call, co // Else, ask for a channel (for future calls/text messages) auto type = call->hasVideo() ? "videoCall" : "audioCall"; - JAMI_WARN("[call %s] No channeled socket with this peer. Send request", - call->getCallId().c_str()); + JAMI_WARNING("[call {}] No channeled socket with this peer. Send request", + call->getCallId()); requestSIPConnection(accountUri, deviceId, type, true, call); }); } @@ -552,7 +556,7 @@ JamiAccount::handleIncomingConversationCall(const std::string& callId, if (isNotHosting) { JAMI_DEBUG("Creating conference for swarm {} with id {}", conversationId, confId); // Create conference and host it. - convModule()->hostConference(conversationId, confId, callId, false); + convModule()->hostConference(conversationId, confId, callId); } else { JAMI_DEBUG("Adding participant {} for swarm {} with id {}", callId, conversationId, confId); Manager::instance().addAudio(*call); @@ -3152,6 +3156,12 @@ JamiAccount::getIceOptions() const noexcept return connectionManager_->getIceOptions(); } +void +JamiAccount::getIceOptions(std::function<void(dhtnet::IceTransportOptions&&)> cb) const noexcept +{ + return connectionManager_->getIceOptions(std::move(cb)); +} + dhtnet::IpAddr JamiAccount::getPublishedIpAddress(uint16_t family) const { diff --git a/src/jamidht/jamiaccount.h b/src/jamidht/jamiaccount.h index 1502556e3c446bec8343e1d950cfcc9a33b9cc06..fb7e2535166baa85836bb5b4e35f014b9ef76747 100644 --- a/src/jamidht/jamiaccount.h +++ b/src/jamidht/jamiaccount.h @@ -338,6 +338,7 @@ public: * Create and return ICE options. */ dhtnet::IceTransportOptions getIceOptions() const noexcept override; + void getIceOptions(std::function<void(dhtnet::IceTransportOptions&&)> cb) const noexcept; dhtnet::IpAddr getPublishedIpAddress(uint16_t family = PF_UNSPEC) const override; /* Devices */ @@ -695,7 +696,7 @@ private: void generateDhParams(); void newOutgoingCallHelper(const std::shared_ptr<SIPCall>& call, const Uri& uri); - void newSwarmOutgoingCallHelper(const std::shared_ptr<SIPCall>& call, const Uri& uri); + std::shared_ptr<SIPCall> newSwarmOutgoingCallHelper(const Uri& uri, const std::vector<libjami::MediaMap>& mediaList); std::shared_ptr<SIPCall> createSubCall(const std::shared_ptr<SIPCall>& mainCall); std::filesystem::path idPath_ {}; diff --git a/src/manager.cpp b/src/manager.cpp index 947c19b4b38ab7c379e7d8bdd1589fac96dafeeb..078aa7b1638b0ae251f8dccb61a68a8d685fb625 100644 --- a/src/manager.cpp +++ b/src/manager.cpp @@ -1113,7 +1113,7 @@ Manager::outgoingCall(const std::string& account_id, try { call = newOutgoingCall(trim(to), account_id, mediaList); } catch (const std::exception& e) { - JAMI_ERR("%s", e.what()); + JAMI_ERROR("{}", e.what()); return {}; } @@ -1452,8 +1452,12 @@ Manager::ManagerPimpl::addMainParticipant(Conference& conf) bool Manager::ManagerPimpl::hangupConference(Conference& conference) { - JAMI_DBG("Hangup conference %s", conference.getConfId().c_str()); + JAMI_DEBUG("Hangup conference {}", conference.getConfId()); ParticipantSet participants(conference.getParticipantList()); + if (participants.empty()) { + if (auto account = conference.getAccount()) + account->removeConference(conference.getConfId()); + } for (const auto& callId : participants) { if (auto call = base_.getCallFromCallID(callId)) base_.hangupCall(call->getAccountId(), callId); @@ -1527,7 +1531,7 @@ Manager::joinParticipant(const std::string& accountId, mediaAttr = call2->getMediaAttributeList(); auto conf = std::make_shared<Conference>(account, "", true, mediaAttr); account->attach(conf); - emitSignal<libjami::CallSignal::ConferenceCreated>(account->getAccountID(), conf->getConfId()); + emitSignal<libjami::CallSignal::ConferenceCreated>(account->getAccountID(), "", conf->getConfId()); // Bind calls according to their state pimpl_->bindCallToConference(*call1, *conf); @@ -1585,7 +1589,7 @@ Manager::createConfFromParticipantList(const std::string& accountId, // Create the conference if and only if at least 2 calls have been successfully created if (successCounter >= 2) { account->attach(conf); - emitSignal<libjami::CallSignal::ConferenceCreated>(accountId, conf->getConfId()); + emitSignal<libjami::CallSignal::ConferenceCreated>(accountId, "", conf->getConfId()); } } @@ -2619,7 +2623,7 @@ Manager::ManagerPimpl::processIncomingCall(const std::string& accountId, Call& i // First call auto conf = std::make_shared<Conference>(account, "", false); account->attach(conf); - emitSignal<libjami::CallSignal::ConferenceCreated>(account->getAccountID(), + emitSignal<libjami::CallSignal::ConferenceCreated>(account->getAccountID(), "", conf->getConfId()); // Bind calls according to their state diff --git a/test/agent/src/bindings/signal.cpp b/test/agent/src/bindings/signal.cpp index e40443e1412e18644bba46a2859a9e128b914893..3bfdf0596981247b7f9bae918383ea9f5d3e3c5c 100644 --- a/test/agent/src/bindings/signal.cpp +++ b/test/agent/src/bindings/signal.cpp @@ -211,7 +211,7 @@ install_signal_primitives(void*) add_handler<libjami::CallSignal::RecordPlaybackFilepath, const std::string&, const std::string&>( handlers, "record-playback-filepath"); - add_handler<libjami::CallSignal::ConferenceCreated, const std::string&, const std::string&>( + add_handler<libjami::CallSignal::ConferenceCreated, const std::string&, const std::string&, const std::string&>( handlers, "conference-created"); add_handler<libjami::CallSignal::ConferenceChanged, diff --git a/test/unitTest/call/conference.cpp b/test/unitTest/call/conference.cpp index 19d7bd2d64495c4ce455ad34b6a8ec705b0bef71..d864703e2329c01565f492e6aa93a5ec36640273 100644 --- a/test/unitTest/call/conference.cpp +++ b/test/unitTest/call/conference.cpp @@ -235,7 +235,7 @@ ConferenceTest::registerSignalHandlers() cv.notify_one(); })); confHandlers.insert(libjami::exportable_callback<libjami::CallSignal::ConferenceCreated>( - [=](const std::string&, const std::string& conferenceId) { + [=](const std::string&, const std::string&, const std::string& conferenceId) { confId = conferenceId; cv.notify_one(); })); diff --git a/tools/jamictrl/controller.py b/tools/jamictrl/controller.py index 760c86afe93ca2f3f53f7eae7ccffd87f551b9c9..cff1ac9ef6afbc0f7662075a246e7383d239c40e 100644 --- a/tools/jamictrl/controller.py +++ b/tools/jamictrl/controller.py @@ -298,10 +298,10 @@ class libjamiCtrl(Thread): def onConferenceCreated_cb(self): pass - def onConferenceCreated_callback(self, confId): + def onConferenceCreated_callback(self, convId, confId): pass - def onConferenceCreated(self, confId): + def onConferenceCreated(self, convId, confId): self.currentConfId = confId self.onConferenceCreated_cb() self.onConferenceCreated_callback(confId)