From d6cb4930d3ac67dcc078e44f1ed8a63b8bd0fc1a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=A9bastien=20Blin?=
 <sebastien.blin@savoirfairelinux.com>
Date: Thu, 23 May 2024 14:56:03 -0400
Subject: [PATCH] conference: fix tests and conference hangup

API changed for ut_conference.
For ut_conversation_call, because the host is not a dummy call,
we must change the hangup in manager.cpp and fix sink creation
for host while attaching.

Change-Id: Icfc296949438e92f7b9b986ed6aa3b463ec2334e
---
 src/conference.cpp                  | 22 ++++++--
 src/manager.cpp                     | 73 +++++++++++++------------
 test/unitTest/call/conference.cpp   | 12 ++--
 test/unitTest/conversation/call.cpp | 85 +++++++++++++++--------------
 4 files changed, 103 insertions(+), 89 deletions(-)

diff --git a/src/conference.cpp b/src/conference.cpp
index f1aba56639..64734f4911 100644
--- a/src/conference.cpp
+++ b/src/conference.cpp
@@ -602,8 +602,13 @@ Conference::requestMediaChange(const std::vector<libjami::MediaMap>& mediaList)
     }
 
 #ifdef ENABLE_VIDEO
-    if (videoMixer_)
-        videoMixer_->switchInputs(newVideoInputs);
+    if (videoMixer_) {
+        if (newVideoInputs.empty()) {
+            videoMixer_->addAudioOnlySource("", sip_utils::streamId("", sip_utils::DEFAULT_AUDIO_STREAMID));
+        } else {
+            videoMixer_->switchInputs(newVideoInputs);
+        }
+    }
 #endif
     hostSources_ = mediaAttrList; // New medias
     if (!isMuted("host"sv) && !isMediaSourceMuted(MediaType::MEDIA_AUDIO))
@@ -918,7 +923,11 @@ Conference::attachHost(const std::vector<libjami::MediaMap>& mediaList)
                     if (source.type_ == MediaType::MEDIA_VIDEO)
                         videoInputs.emplace_back(source.sourceUri_);
                 }
-                videoMixer_->switchInputs(videoInputs);
+                if (videoInputs.empty()) {
+                    videoMixer_->addAudioOnlySource("", sip_utils::streamId("", sip_utils::DEFAULT_AUDIO_STREAMID));
+                } else {
+                    videoMixer_->switchInputs(videoInputs);
+                }
             }
 #endif
         } else {
@@ -935,7 +944,8 @@ Conference::attachHost(const std::vector<libjami::MediaMap>& mediaList)
 void
 Conference::detachHost()
 {
-    JAMI_INFO("Detach local participant from conference %s", id_.c_str());
+    JAMI_LOG("Detach local participant from conference {}", id_);
+
     if (getState() == State::ACTIVE_ATTACHED) {
         unbindHostAudio();
 
@@ -944,8 +954,8 @@ Conference::detachHost()
             videoMixer_->stopInputs();
 #endif
     } else {
-        JAMI_WARN(
-            "Invalid conference state in detach participant: current \"%s\" - expected \"%s\"",
+        JAMI_WARNING(
+            "Invalid conference state in detach participant: current \"{}\" - expected \"{}\"",
             getStateStr(),
             "ACTIVE_ATTACHED");
         return;
diff --git a/src/manager.cpp b/src/manager.cpp
index ede97e9a07..cda27ada8d 100644
--- a/src/manager.cpp
+++ b/src/manager.cpp
@@ -535,7 +535,7 @@ Manager::ManagerPimpl::processRemainingParticipants(Conference& conf)
     const std::string current_callId(base_.getCurrentCallId());
     CallIdSet subcalls(conf.getSubCalls());
     const size_t n = subcalls.size();
-    JAMI_DBG("Process remaining %zu participant(s) from conference %s", n, conf.getConfId().c_str());
+    JAMI_DEBUG("Process remaining {} participant(s) from conference {}", n, conf.getConfId());
 
     if (n > 1) {
         // Reset ringbuffer's readpointers
@@ -550,43 +550,45 @@ Manager::ManagerPimpl::processRemainingParticipants(Conference& conf)
         }
 
         base_.getRingBufferPool().flush(RingBufferPool::DEFAULT_ID);
-    } else if (n == 1) {
-        // this call is the last participant, hence
-        // the conference is over
-        auto p = subcalls.begin();
-        if (auto call = base_.getCallFromCallID(*p)) {
-            // if we are not listening to this conference and not a rendez-vous
-            auto w = call->getAccount();
-            auto account = w.lock();
-            if (!account) {
-                JAMI_ERR("No account detected");
-                return;
-            }
-
+    } else {
+        if (auto acc = std::dynamic_pointer_cast<JamiAccount>(conf.getAccount())) {
             // Stay in a conference if 1 participants for swarm and rendezvous
-            if (account->isRendezVous())
-                return;
-
-            if (auto acc = std::dynamic_pointer_cast<JamiAccount>(account))
-                if (auto cm = acc->convModule(true))
-                    if (cm->isHosting("", conf.getConfId()))
+            if (auto cm = acc->convModule(true)) {
+                if (acc->isRendezVous() || cm->isHosting("", conf.getConfId())) {
+                    // Check if attached
+                    if (conf.getState() == Conference::State::ACTIVE_ATTACHED) {
                         return;
-
-            // Else go in 1:1
-            if (current_callId != conf.getConfId())
-                base_.onHoldCall(account->getAccountID(), call->getCallId());
-            else
-                switchCall(call->getCallId());
+                    }
+                }
+            }
         }
+        if (n == 1) {
+            // this call is the last participant (non swarm-call), hence
+            // the conference is over
+            auto p = subcalls.begin();
+            if (auto call = base_.getCallFromCallID(*p)) {
+                // if we are not listening to this conference and not a rendez-vous
+                auto w = call->getAccount();
+                auto account = w.lock();
+                if (!account) {
+                    JAMI_ERR("No account detected");
+                    return;
+                }
+                if (current_callId != conf.getConfId())
+                    base_.onHoldCall(account->getAccountID(), call->getCallId());
+                else
+                    switchCall(call->getCallId());
+            }
 
-        JAMI_DBG("No remaining participants, remove conference");
-        if (auto account = conf.getAccount())
-            account->removeConference(conf.getConfId());
-    } else {
-        JAMI_DBG("No remaining participants, remove conference");
-        if (auto account = conf.getAccount())
-            account->removeConference(conf.getConfId());
-        unsetCurrentCall();
+            JAMI_DBG("No remaining participants, remove conference");
+            if (auto account = conf.getAccount())
+                account->removeConference(conf.getConfId());
+        } else {
+            JAMI_DBG("No remaining participants, remove conference");
+            if (auto account = conf.getAccount())
+                account->removeConference(conf.getConfId());
+            unsetCurrentCall();
+        }
     }
 }
 
@@ -1221,7 +1223,7 @@ Manager::hangupConference(const std::string& accountId, const std::string& confI
         if (auto conference = account->getConference(confId)) {
             return pimpl_->hangupConference(*conference);
         } else {
-            JAMI_ERR("No such conference %s", confId.c_str());
+            JAMI_ERROR("No such conference {}", confId);
         }
     }
     return false;
@@ -1450,6 +1452,7 @@ Manager::ManagerPimpl::hangupConference(Conference& conference)
 {
     JAMI_DEBUG("Hangup conference {}", conference.getConfId());
     CallIdSet subcalls(conference.getSubCalls());
+    conference.detachHost();
     if (subcalls.empty()) {
         if (auto account = conference.getAccount())
             account->removeConference(conference.getConfId());
diff --git a/test/unitTest/call/conference.cpp b/test/unitTest/call/conference.cpp
index f81bb4fe53..6f25e37e0f 100644
--- a/test/unitTest/call/conference.cpp
+++ b/test/unitTest/call/conference.cpp
@@ -339,7 +339,7 @@ ConferenceTest::startConference(bool audioOnly, bool addDavi)
         CPPUNIT_ASSERT(cv.wait_for(lk, 20s, [&] { return !daviCall.callId.empty(); }));
         Manager::instance().answerCall(daviId, daviCall.callId);
         CPPUNIT_ASSERT(cv.wait_for(lk, 20s, [&] { return daviCall.hostState == "CURRENT"; }));
-        Manager::instance().addParticipant(aliceId, call1, aliceId, confId);
+        Manager::instance().addSubCall(aliceId, call1, aliceId, confId);
         CPPUNIT_ASSERT(cv.wait_for(lk, 20s, [&] { return !daviCall.device.empty(); }));
     }
 }
@@ -508,7 +508,7 @@ ConferenceTest::testMuteStatusAfterAdd()
     CPPUNIT_ASSERT(cv.wait_for(lk, 20s, [&] { return !daviCall.callId.empty(); }));
     Manager::instance().answerCall(daviId, daviCall.callId);
     CPPUNIT_ASSERT(cv.wait_for(lk, 20s, [&] { return daviCall.hostState == "CURRENT"; }));
-    Manager::instance().addParticipant(aliceId, call3, aliceId, confId);
+    Manager::instance().addSubCall(aliceId, call3, aliceId, confId);
     CPPUNIT_ASSERT(cv.wait_for(lk, 20s, [&] { return !daviCall.device.empty(); }));
 
     auto aliceConf = aliceAccount->getConference(confId);
@@ -600,7 +600,7 @@ ConferenceTest::testMuteStatusAfterRemove()
     CPPUNIT_ASSERT(cv.wait_for(lk, 20s, [&] { return !daviCall.callId.empty(); }));
     Manager::instance().answerCall(daviId, daviCall.callId);
     CPPUNIT_ASSERT(cv.wait_for(lk, 20s, [&] { return daviCall.hostState == "CURRENT"; }));
-    Manager::instance().addParticipant(aliceId, call2, aliceId, confId);
+    Manager::instance().addSubCall(aliceId, call2, aliceId, confId);
     CPPUNIT_ASSERT(cv.wait_for(lk, 20s, [&] { return !daviCall.device.empty(); }));
 
     CPPUNIT_ASSERT(cv.wait_for(lk, 5s, [&] { return !daviCall.moderatorMuted.load(); }));
@@ -643,7 +643,7 @@ ConferenceTest::testActiveStatusAfterRemove()
     CPPUNIT_ASSERT(cv.wait_for(lk, 20s, [&] { return !daviCall.callId.empty(); }));
     Manager::instance().answerCall(daviId, daviCall.callId);
     CPPUNIT_ASSERT(cv.wait_for(lk, 20s, [&] { return daviCall.hostState == "CURRENT"; }));
-    Manager::instance().addParticipant(aliceId, call2, aliceId, confId);
+    Manager::instance().addSubCall(aliceId, call2, aliceId, confId);
     CPPUNIT_ASSERT(cv.wait_for(lk, 20s, [&] { return !daviCall.device.empty(); }));
 
     CPPUNIT_ASSERT(cv.wait_for(lk, 5s, [&] { return !daviCall.active.load(); }));
@@ -707,7 +707,7 @@ ConferenceTest::testHandsUp()
     CPPUNIT_ASSERT(cv.wait_for(lk, 20s, [&] { return !daviCall.callId.empty(); }));
     Manager::instance().answerCall(daviId, daviCall.callId);
     CPPUNIT_ASSERT(cv.wait_for(lk, 20s, [&] { return daviCall.hostState == "CURRENT"; }));
-    Manager::instance().addParticipant(aliceId, call2, aliceId, confId);
+    Manager::instance().addSubCall(aliceId, call2, aliceId, confId);
     CPPUNIT_ASSERT(cv.wait_for(lk, 20s, [&] { return !daviCall.device.empty(); }));
 
     CPPUNIT_ASSERT(cv.wait_for(lk, 5s, [&] { return !daviCall.raisedHand.load(); }));
@@ -760,7 +760,7 @@ ConferenceTest::testJoinCallFromOtherAccount()
     CPPUNIT_ASSERT(cv.wait_for(lk, 20s, [&] { return !daviCall.callId.empty(); }));
     Manager::instance().answerCall(daviId, daviCall.callId);
     CPPUNIT_ASSERT(cv.wait_for(lk, 20s, [&] { return daviCall.hostState == "CURRENT"; }));
-    CPPUNIT_ASSERT(Manager::instance().addParticipant(daviId, daviCall.callId, aliceId, confId));
+    CPPUNIT_ASSERT(Manager::instance().addSubCall(daviId, daviCall.callId, aliceId, confId));
     hangupConference();
 
     libjami::unregisterSignalHandlers();
diff --git a/test/unitTest/conversation/call.cpp b/test/unitTest/conversation/call.cpp
index bf59bdbe4f..a3682391e5 100644
--- a/test/unitTest/conversation/call.cpp
+++ b/test/unitTest/conversation/call.cpp
@@ -41,6 +41,7 @@ struct ConvData
 {
     std::string id {};
     std::string callId {};
+    std::string confId {};
     bool requestReceived {false};
     bool needsHost {false};
     bool conferenceChanged {false};
@@ -211,6 +212,14 @@ ConversationCallTest::connectSignals()
                 aliceData_.conferenceChanged = true;
             cv.notify_one();
         }));
+    confHandlers.insert(libjami::exportable_callback<libjami::CallSignal::ConferenceCreated>(
+        [&](const std::string& accountId, const std::string&, const std::string& confId) {
+            if (accountId == aliceId)
+                aliceData_.confId = confId;
+            else if (accountId == bobId)
+                bobData_.confId = confId;
+            cv.notify_one();
+        }));
     confHandlers.insert(libjami::exportable_callback<libjami::CallSignal::ConferenceRemoved>(
         [&](const std::string& accountId, const std::string&) {
             if (accountId == aliceId)
@@ -236,21 +245,13 @@ ConversationCallTest::connectSignals()
                         carlaData_.hostState = state;
                 }
             } else if (accountId == bobId) {
+                bobData_.callId = callId;
                 bobData_.state = state;
             } else if (accountId == carlaId) {
                 carlaData_.state = state;
             }
             cv.notify_one();
         }));
-    confHandlers.insert(libjami::exportable_callback<libjami::CallSignal::IncomingCallWithMedia>(
-        [&](const std::string& accountId,
-            const std::string& callId,
-            const std::string&,
-            const std::vector<std::map<std::string, std::string>>&) {
-            if (accountId == bobId)
-                bobData_.callId = callId;
-            cv.notify_one();
-        }));
     confHandlers.insert(libjami::exportable_callback<libjami::CallSignal::OnConferenceInfosUpdated>(
         [=](const std::string&,
             const std::vector<std::map<std::string, std::string>> participantsInfos) {
@@ -305,7 +306,7 @@ ConversationCallTest::testActiveCalls()
 
     // start call
     aliceData_.messages.clear();
-    auto callId = libjami::placeCallWithMedia(aliceId, "swarm:" + aliceData_.id, {});
+    libjami::placeCallWithMedia(aliceId, "swarm:" + aliceData_.id, {});
     // should get message
     cv.wait_for(lk, 30s, [&]() { return !aliceData_.conferenceChanged && !aliceData_.messages.empty(); });
     CPPUNIT_ASSERT(aliceData_.messages.rbegin()->type == "application/call-history+json");
@@ -315,10 +316,10 @@ ConversationCallTest::testActiveCalls()
 
     // hangup
     aliceData_.messages.clear();
-    Manager::instance().hangupCall(aliceId, callId);
+    Manager::instance().hangupConference(aliceId, aliceData_.confId);
 
     // should get message
-    cv.wait_for(lk, 30s, [&]() { return !aliceData_.messages.empty(); });
+    CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&]() { return !aliceData_.messages.empty(); }));
     CPPUNIT_ASSERT(aliceData_.messages.rbegin()->body.find("duration") != aliceData_.messages.rbegin()->body.end());
 
     // get active calls = 0
@@ -362,7 +363,7 @@ ConversationCallTest::testActiveCalls3Peers()
     aliceData_.messages.clear();
     bobData_.messages.clear();
     carlaData_.messages.clear();
-    auto callId = libjami::placeCallWithMedia(aliceId, "swarm:" + aliceData_.id, {});
+    libjami::placeCallWithMedia(aliceId, "swarm:" + aliceData_.id, {});
     auto lastCommitIsCall = [&](const auto& data) {
         return !data.messages.empty()
                && data.messages.rbegin()->body.at("type") == "application/call-history+json";
@@ -385,10 +386,10 @@ ConversationCallTest::testActiveCalls3Peers()
         return aliceData_.conferenceChanged && bobData_.hostState == "CURRENT";
     }));
     aliceData_.conferenceChanged = false;
-    // get 3 participants
+    // get 2 other participants
     libjami::placeCallWithMedia(carlaId, destination, {});
     CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&]() {
-        return aliceData_.conferenceChanged && carlaData_.hostState == "CURRENT" && libjami::getParticipantList(aliceId, confId).size() == 3;
+        return aliceData_.conferenceChanged && carlaData_.hostState == "CURRENT" && libjami::getParticipantList(aliceId, confId).size() == 2;
     }));
 
     // get active calls = 1
@@ -450,7 +451,7 @@ ConversationCallTest::testRejoinCall()
     aliceData_.messages.clear();
     bobData_.messages.clear();
     carlaData_.messages.clear();
-    auto callId = libjami::placeCallWithMedia(aliceId, "swarm:" + aliceData_.id, {});
+    libjami::placeCallWithMedia(aliceId, "swarm:" + aliceData_.id, {});
     auto lastCommitIsCall = [&](const auto& data) {
         return !data.messages.empty()
                && data.messages.rbegin()->body.at("type") == "application/call-history+json";
@@ -469,7 +470,7 @@ ConversationCallTest::testRejoinCall()
                                    confId);
 
     aliceData_.conferenceChanged = false;
-    auto bobCall = libjami::placeCallWithMedia(bobId, destination, {});
+    libjami::placeCallWithMedia(bobId, destination, {});
     cv.wait_for(lk, 30s, [&]() {
         return aliceData_.conferenceChanged && bobData_.hostState == "CURRENT"  && bobData_.state == "CURRENT";
     });
@@ -479,18 +480,18 @@ ConversationCallTest::testRejoinCall()
         return aliceData_.conferenceChanged && carlaData_.hostState == "CURRENT" && carlaData_.state == "CURRENT";
     });
 
-    CPPUNIT_ASSERT(libjami::getParticipantList(aliceId, confId).size() == 3);
+    CPPUNIT_ASSERT(libjami::getParticipantList(aliceId, confId).size() == 2);
 
     // hangup 1 participant and rejoin
     aliceData_.messages.clear();
     bobData_.messages.clear();
     aliceData_.conferenceChanged = false;
-    Manager::instance().hangupCall(bobId, bobCall);
+    Manager::instance().hangupCall(bobId, bobData_.callId);
     cv.wait_for(lk, 30s, [&]() {
         return aliceData_.conferenceChanged && bobData_.hostState == "OVER";
     });
 
-    CPPUNIT_ASSERT(libjami::getParticipantList(aliceId, confId).size() == 2);
+    CPPUNIT_ASSERT(libjami::getParticipantList(aliceId, confId).size() == 1);
 
     aliceData_.conferenceChanged = false;
     libjami::placeCallWithMedia(bobId, destination, {});
@@ -498,7 +499,7 @@ ConversationCallTest::testRejoinCall()
         return aliceData_.conferenceChanged && bobData_.hostState == "CURRENT";
     });
 
-    CPPUNIT_ASSERT(libjami::getParticipantList(aliceId, confId).size() == 3);
+    CPPUNIT_ASSERT(libjami::getParticipantList(aliceId, confId).size() == 2);
     CPPUNIT_ASSERT(aliceData_.messages.empty());
     CPPUNIT_ASSERT(bobData_.messages.empty());
 
@@ -509,10 +510,10 @@ ConversationCallTest::testRejoinCall()
     Manager::instance().hangupConference(aliceId, confId);
 
     // should get message
-    cv.wait_for(lk, 30s, [&]() {
+    CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&]() {
         return !aliceData_.messages.empty() && !bobData_.messages.empty()
                && !carlaData_.messages.empty();
-    });
+    }));
     CPPUNIT_ASSERT(aliceData_.messages[0].body.find("duration") != aliceData_.messages[0].body.end());
     CPPUNIT_ASSERT(bobData_.messages[0].body.find("duration") != bobData_.messages[0].body.end());
     CPPUNIT_ASSERT(carlaData_.messages[0].body.find("duration") != carlaData_.messages[0].body.end());
@@ -546,7 +547,7 @@ ConversationCallTest::testParticipantHangupConfNotRemoved()
     // start call
     aliceData_.messages.clear();
     bobData_.messages.clear();
-    auto callId = libjami::placeCallWithMedia(aliceId, "swarm:" + aliceData_.id, {});
+    libjami::placeCallWithMedia(aliceId, "swarm:" + aliceData_.id, {});
     auto lastCommitIsCall = [&](const auto& data) {
         return !data.messages.empty()
                && data.messages.rbegin()->body.at("type") == "application/call-history+json";
@@ -610,7 +611,7 @@ ConversationCallTest::testJoinFinishedCall()
     aliceData_.messages.clear();
     bobData_.messages.clear();
     carlaData_.messages.clear();
-    auto callId = libjami::placeCallWithMedia(aliceId, "swarm:" + aliceData_.id, {});
+    libjami::placeCallWithMedia(aliceId, "swarm:" + aliceData_.id, {});
     auto lastCommitIsCall = [&](const auto& data) {
         return !data.messages.empty()
                && data.messages.rbegin()->body.at("type") == "application/call-history+json";
@@ -630,7 +631,7 @@ ConversationCallTest::testJoinFinishedCall()
     aliceData_.messages.clear();
     bobData_.messages.clear();
     carlaData_.messages.clear();
-    Manager::instance().hangupCall(aliceId, callId);
+    Manager::instance().hangupConference(aliceId, aliceData_.confId);
     // should get message
     cv.wait_for(lk, 30s, [&]() {
         return !aliceData_.messages.empty() && !bobData_.messages.empty()
@@ -707,7 +708,7 @@ ConversationCallTest::testJoinFinishedCallForbidden()
     aliceData_.messages.clear();
     bobData_.messages.clear();
     carlaData_.messages.clear();
-    auto callId = libjami::placeCallWithMedia(aliceId, "swarm:" + aliceData_.id, {});
+    libjami::placeCallWithMedia(aliceId, "swarm:" + aliceData_.id, {});
     auto lastCommitIsCall = [&](const auto& data) {
         return !data.messages.empty()
                && data.messages.rbegin()->body.at("type") == "application/call-history+json";
@@ -729,7 +730,7 @@ ConversationCallTest::testJoinFinishedCallForbidden()
     aliceData_.messages.clear();
     bobData_.messages.clear();
     carlaData_.messages.clear();
-    Manager::instance().hangupCall(aliceId, callId);
+    Manager::instance().hangupConference(aliceId, aliceData_.confId);
 
     // should get message
     cv.wait_for(lk, 30s, [&]() {
@@ -816,7 +817,7 @@ ConversationCallTest::testUsePreference()
     // start call
     aliceData_.messages.clear();
     bobData_.messages.clear();
-    auto callId = libjami::placeCallWithMedia(bobId, "swarm:" + aliceData_.id, {});
+    libjami::placeCallWithMedia(bobId, "swarm:" + aliceData_.id, {});
     auto lastCommitIsCall = [&](const auto& data) {
         return !data.messages.empty()
                && data.messages.rbegin()->body.at("type") == "application/call-history+json";
@@ -833,7 +834,7 @@ ConversationCallTest::testUsePreference()
     CPPUNIT_ASSERT(cv.wait_for(lk, 5s, [&]() { return pInfos_.size() == 1; }));
     auto uri = string_remove_suffix(pInfos_[0]["uri"], '@');
     CPPUNIT_ASSERT(uri == bobUri);
-    Manager::instance().hangupCall(bobId, callId);
+    Manager::instance().hangupConference(bobId, bobData_.confId);
 }
 
 void
@@ -851,7 +852,7 @@ ConversationCallTest::testJoinWhileActiveCall()
 
     // start call
     aliceData_.messages.clear();
-    auto callId = libjami::placeCallWithMedia(aliceId, "swarm:" + aliceData_.id, {});
+    libjami::placeCallWithMedia(aliceId, "swarm:" + aliceData_.id, {});
     auto lastCommitIsCall = [&](const auto& data) {
         return !data.messages.empty()
                && data.messages.rbegin()->body.at("type") == "application/call-history+json";
@@ -920,7 +921,7 @@ ConversationCallTest::testCallSelfIfDefaultHost()
     aliceData_.messages.clear();
     bobData_.messages.clear();
     pInfos_.clear();
-    auto callId = libjami::placeCallWithMedia(aliceId, "swarm:" + aliceData_.id, {});
+    libjami::placeCallWithMedia(aliceId, "swarm:" + aliceData_.id, {});
     auto lastCommitIsCall = [&](const auto& data) {
         return !data.messages.empty()
                && data.messages.rbegin()->body.at("type") == "application/call-history+json";
@@ -977,7 +978,7 @@ ConversationCallTest::testNeedsHost()
     // Disable Host
     Manager::instance().sendRegister(aliceId, false);
     // start call
-    auto callId = libjami::placeCallWithMedia(bobId, "swarm:" + aliceData_.id, {});
+    libjami::placeCallWithMedia(bobId, "swarm:" + aliceData_.id, {});
     // Can fail after 30 seconds if it triggers a new ICE request (before No response from DHT)
     CPPUNIT_ASSERT(cv.wait_for(lk, 40s, [&]() { return bobData_.needsHost; }));
 }
@@ -1010,7 +1011,7 @@ ConversationCallTest::testAudioOnly()
             {libjami::Media::MediaAttributeKey::LABEL, "audio_0"}};
     mediaList.emplace_back(mediaAttribute);
     pInfos_.clear();
-    auto callId = libjami::placeCallWithMedia(aliceId, "swarm:" + aliceData_.id, mediaList);
+    libjami::placeCallWithMedia(aliceId, "swarm:" + aliceData_.id, mediaList);
     // should get message
     cv.wait_for(lk, 30s, [&]() { return !aliceData_.messages.empty() && !pInfos_.empty(); });
     CPPUNIT_ASSERT(aliceData_.messages[0].type == "application/call-history+json");
@@ -1019,7 +1020,7 @@ ConversationCallTest::testAudioOnly()
 
     // hangup
     aliceData_.messages.clear();
-    Manager::instance().hangupCall(aliceId, callId);
+    Manager::instance().hangupConference(aliceId, aliceData_.confId);
 
     // should get message
     cv.wait_for(lk, 30s, [&]() { return !aliceData_.messages.empty(); });
@@ -1066,7 +1067,7 @@ ConversationCallTest::testJoinAfterMuteHost()
             {libjami::Media::MediaAttributeKey::SOURCE, ""},
             {libjami::Media::MediaAttributeKey::LABEL, "audio_0"}};
     mediaList.emplace_back(mediaAttribute);
-    auto callId = libjami::placeCallWithMedia(aliceId, "swarm:" + aliceData_.id, mediaList);
+    libjami::placeCallWithMedia(aliceId, "swarm:" + aliceData_.id, mediaList);
     auto lastCommitIsCall = [&](const auto& data) {
         return !data.messages.empty()
                && data.messages.rbegin()->type == "application/call-history+json";
@@ -1078,8 +1079,8 @@ ConversationCallTest::testJoinAfterMuteHost()
     auto confId = bobData_.messages.rbegin()->body.at("confId");
 
     // Mute host
-    auto call = std::dynamic_pointer_cast<SIPCall>(aliceAccount->getCall(callId));
-    auto proposedList = call->currentMediaList();
+    auto conference = aliceAccount->getConference(aliceData_.confId);
+    auto proposedList = conference->currentMediaList();
     for (auto& media : proposedList)
         if (media["LABEL"] == "audio_0")
             media["MUTED"] = "true";
@@ -1134,7 +1135,7 @@ ConversationCallTest::testBusy()
             {libjami::Media::MediaAttributeKey::SOURCE, ""},
             {libjami::Media::MediaAttributeKey::LABEL, "audio_0"}};
     mediaList.emplace_back(mediaAttribute);
-    auto callId = libjami::placeCallWithMedia(aliceId, bobUri, mediaList);
+    libjami::placeCallWithMedia(aliceId, bobUri, mediaList);
     auto lastCommitIsCall = [&](const auto& data) {
         return !data.messages.empty()
                && data.messages.rbegin()->type == "application/call-history+json";
@@ -1176,8 +1177,8 @@ ConversationCallTest::testDecline()
             {libjami::Media::MediaAttributeKey::SOURCE, ""},
             {libjami::Media::MediaAttributeKey::LABEL, "audio_0"}};
     mediaList.emplace_back(mediaAttribute);
-    auto callId = libjami::placeCallWithMedia(aliceId, bobUri, mediaList);
-    CPPUNIT_ASSERT(cv.wait_for(lk, 10s, [&]() { return !bobData_.callId.empty(); }));
+    libjami::placeCallWithMedia(aliceId, bobUri, mediaList);
+    CPPUNIT_ASSERT(cv.wait_for(lk, 10s, [&]() { return !bobData_.callId.empty() && bobData_.state == "INCOMING"; }));
 
     libjami::refuse(bobId, bobData_.callId);
 
@@ -1217,7 +1218,7 @@ ConversationCallTest::testNoDevice()
             {libjami::Media::MediaAttributeKey::SOURCE, ""},
             {libjami::Media::MediaAttributeKey::LABEL, "audio_0"}};
     mediaList.emplace_back(mediaAttribute);
-    auto callId = libjami::placeCallWithMedia(aliceId, "e2eb225c76be68713d4874d290200849436c6355", mediaList);
+    libjami::placeCallWithMedia(aliceId, "e2eb225c76be68713d4874d290200849436c6355", mediaList);
 
     auto lastCommitIsCall = [&](const auto& data) {
         return !data.messages.empty()
-- 
GitLab