Skip to content
Snippets Groups Projects
Commit 01594813 authored by Aline Gondim Santos's avatar Aline Gondim Santos Committed by Sébastien Blin
Browse files

conference: add handsUp feature

GitLab: jami-project#855
Change-Id: I425a4b0049f1ade8c8eeeb93fc79f8d36bd25585
parent 9d0c33b2
No related branches found
No related tags found
No related merge requests found
...@@ -352,6 +352,14 @@ ...@@ -352,6 +352,14 @@
<arg type="b" name="isParticipant" direction="out"/> <arg type="b" name="isParticipant" direction="out"/>
</method> </method>
<method name="raiseParticipantHand" tp:name-for-bindings="raiseParticipantHand">
<tp:added version="11.0.0"/>
<arg type="s" name="accountId" direction="in"/>
<arg type="s" name="confId" direction="in"/>
<arg type="s" name="peerId" direction="in"/>
<arg type="b" name="state" direction="in"/>
</method>
<method name="hangupParticipant" tp:name-for-bindings="hangupParticipant"> <method name="hangupParticipant" tp:name-for-bindings="hangupParticipant">
<tp:added version="9.8.0"/> <tp:added version="9.8.0"/>
<arg type="s" name="confId" direction="in"/> <arg type="s" name="confId" direction="in"/>
......
...@@ -377,3 +377,12 @@ DBusCallManager::hangupParticipant(const std::string& confId, const std::string& ...@@ -377,3 +377,12 @@ DBusCallManager::hangupParticipant(const std::string& confId, const std::string&
{ {
DRing::hangupParticipant(confId, peerId); DRing::hangupParticipant(confId, peerId);
} }
void
DBusCallManager::raiseParticipantHand(const std::string& accountId,
const std::string& confId,
const std::string& peerId,
const bool& state)
{
DRing::raiseParticipantHand(accountId, confId, peerId, state);
}
\ No newline at end of file
...@@ -118,6 +118,10 @@ public: ...@@ -118,6 +118,10 @@ public:
void setModerator(const std::string& confId, const std::string& peerId, const bool& state); void setModerator(const std::string& confId, const std::string& peerId, const bool& state);
void muteParticipant(const std::string& confId, const std::string& peerId, const bool& state); void muteParticipant(const std::string& confId, const std::string& peerId, const bool& state);
void hangupParticipant(const std::string& confId, const std::string& peerId); void hangupParticipant(const std::string& confId, const std::string& peerId);
void raiseParticipantHand(const std::string& accountId,
const std::string& confId,
const std::string& peerId,
const bool& state);
}; };
#endif // __RING_CALLMANAGER_H__ #endif // __RING_CALLMANAGER_H__
...@@ -107,6 +107,7 @@ std::vector<std::map<std::string, std::string>> getConferenceInfos(const std::st ...@@ -107,6 +107,7 @@ std::vector<std::map<std::string, std::string>> getConferenceInfos(const std::st
void setModerator(const std::string& confId, const std::string& peerId, const bool& state); void setModerator(const std::string& confId, const std::string& peerId, const bool& state);
void muteParticipant(const std::string& confId, const std::string& peerId, const bool& state); void muteParticipant(const std::string& confId, const std::string& peerId, const bool& state);
void hangupParticipant(const std::string& confId, const std::string& peerId); void hangupParticipant(const std::string& confId, const std::string& peerId);
void raiseParticipantHand(const std::string& accountId, const std::string& confId, const std::string& peerId, const bool& state);
/* File Playback methods */ /* File Playback methods */
bool startRecordedFilePlayback(const std::string& filepath); bool startRecordedFilePlayback(const std::string& filepath);
......
...@@ -96,6 +96,7 @@ std::vector<std::map<std::string, std::string>> getConferenceInfos(const std::st ...@@ -96,6 +96,7 @@ std::vector<std::map<std::string, std::string>> getConferenceInfos(const std::st
void setModerator(const std::string& confId, const std::string& peerId, const bool& state); void setModerator(const std::string& confId, const std::string& peerId, const bool& state);
void muteParticipant(const std::string& confId, const std::string& peerId, const bool& state); void muteParticipant(const std::string& confId, const std::string& peerId, const bool& state);
void hangupParticipant(const std::string& confId, const std::string& peerId); void hangupParticipant(const std::string& confId, const std::string& peerId);
void raiseParticipantHand(const std::string& accountId, const std::string& confId, const std::string& peerId, const bool& state);
/* File Playback methods */ /* File Playback methods */
bool startRecordedFilePlayback(const std::string& filepath); bool startRecordedFilePlayback(const std::string& filepath);
......
...@@ -390,6 +390,15 @@ muteParticipant(const std::string& confId, const std::string& peerId, const bool ...@@ -390,6 +390,15 @@ muteParticipant(const std::string& confId, const std::string& peerId, const bool
jami::Manager::instance().muteParticipant(confId, peerId, state); jami::Manager::instance().muteParticipant(confId, peerId, state);
} }
void
raiseParticipantHand(const std::string& accountId,
const std::string& confId,
const std::string& peerId,
const bool& state)
{
jami::Manager::instance().raiseParticipantHand(confId, peerId, state);
}
void void
hangupParticipant(const std::string& confId, const std::string& participant) hangupParticipant(const std::string& confId, const std::string& participant)
{ {
......
...@@ -105,6 +105,7 @@ Conference::Conference(bool enableVideo) ...@@ -105,6 +105,7 @@ Conference::Conference(bool enableVideo)
peerId = "host"sv; peerId = "host"sv;
isLocalMuted = shared->isMediaSourceMuted(MediaType::MEDIA_AUDIO); isLocalMuted = shared->isMediaSourceMuted(MediaType::MEDIA_AUDIO);
} }
auto isHandRaised = shared->isHandRaised(peerId);
auto isModeratorMuted = shared->isMuted(peerId); auto isModeratorMuted = shared->isMuted(peerId);
auto sinkId = shared->getConfID() + peerId; auto sinkId = shared->getConfID() + peerId;
newInfo.emplace_back(ParticipantInfo {std::move(uri), newInfo.emplace_back(ParticipantInfo {std::move(uri),
...@@ -118,7 +119,8 @@ Conference::Conference(bool enableVideo) ...@@ -118,7 +119,8 @@ Conference::Conference(bool enableVideo)
!info.hasVideo, !info.hasVideo,
isLocalMuted, isLocalMuted,
isModeratorMuted, isModeratorMuted,
isModerator}); isModerator,
isHandRaised});
} }
if (auto videoMixer = shared->getVideoMixer()) { if (auto videoMixer = shared->getVideoMixer()) {
newInfo.h = videoMixer->getHeight(); newInfo.h = videoMixer->getHeight();
...@@ -127,8 +129,11 @@ Conference::Conference(bool enableVideo) ...@@ -127,8 +129,11 @@ Conference::Conference(bool enableVideo)
lk.unlock(); lk.unlock();
if (!hostAdded) { if (!hostAdded) {
auto audioLocalMuted = shared->isMediaSourceMuted(MediaType::MEDIA_AUDIO); auto audioLocalMuted = shared->isMediaSourceMuted(MediaType::MEDIA_AUDIO);
newInfo.emplace_back(ParticipantInfo { ParticipantInfo pi;
"", "", "", false, 0, 0, 0, 0, true, audioLocalMuted, false, true}); pi.videoMuted = true;
pi.audioLocalMuted = shared->isMediaSourceMuted(MediaType::MEDIA_AUDIO);
pi.isModerator = true;
newInfo.emplace_back(pi);
} }
shared->updateConferenceInfo(std::move(newInfo)); shared->updateConferenceInfo(std::move(newInfo));
...@@ -433,7 +438,6 @@ Conference::addParticipant(const std::string& participant_id) ...@@ -433,7 +438,6 @@ Conference::addParticipant(const std::string& participant_id)
void void
Conference::setActiveParticipant(const std::string& participant_id) Conference::setActiveParticipant(const std::string& participant_id)
{ {
// TODO. Shouldn't be protected by ENABLE_VIDEO define ?
if (!videoMixer_) if (!videoMixer_)
return; return;
if (isHost(participant_id)) { if (isHost(participant_id)) {
...@@ -570,6 +574,7 @@ Conference::removeParticipant(const std::string& participant_id) ...@@ -570,6 +574,7 @@ Conference::removeParticipant(const std::string& participant_id)
if (participants_.erase(participant_id)) { if (participants_.erase(participant_id)) {
if (auto call = getCall(participant_id)) { if (auto call = getCall(participant_id)) {
participantsMuted_.erase(std::string(string_remove_suffix(call->getPeerNumber(), '@'))); participantsMuted_.erase(std::string(string_remove_suffix(call->getPeerNumber(), '@')));
handsRaised_.erase(std::string(string_remove_suffix(call->getPeerNumber(), '@')));
#ifdef ENABLE_VIDEO #ifdef ENABLE_VIDEO
call->exitConference(); call->exitConference();
if (call->isPeerRecording()) if (call->isPeerRecording())
...@@ -871,6 +876,10 @@ Conference::onConfOrder(const std::string& callId, const std::string& confOrder) ...@@ -871,6 +876,10 @@ Conference::onConfOrder(const std::string& callId, const std::string& confOrder)
if (root.isMember("hangupParticipant")) { if (root.isMember("hangupParticipant")) {
hangupParticipant(root["hangupParticipant"].asString()); hangupParticipant(root["hangupParticipant"].asString());
} }
if (root.isMember("handRaised")) {
setHandRaised(root["handRaised"].asString(),
root["handState"].asString() == "true");
}
} }
} }
...@@ -886,6 +895,50 @@ Conference::isModerator(std::string_view uri) const ...@@ -886,6 +895,50 @@ Conference::isModerator(std::string_view uri) const
return moderators_.find(uri) != moderators_.end() or isHost(uri); return moderators_.find(uri) != moderators_.end() or isHost(uri);
} }
bool
Conference::isHandRaised(std::string_view uri) const
{
return isHost(uri) ? handsRaised_.find("host"sv) != handsRaised_.end()
: handsRaised_.find(uri) != handsRaised_.end();
}
void
Conference::setHandRaised(const std::string& participant_id, const bool& state)
{
if (isHost(participant_id)) {
auto isPeerRequiringAttention = isHandRaised("host"sv);
if (state and not isPeerRequiringAttention) {
JAMI_DBG("Raise host hand");
handsRaised_.emplace("host"sv);
updateHandsRaised();
} else if (not state and isPeerRequiringAttention) {
JAMI_DBG("Lower host hand");
handsRaised_.erase("host");
updateHandsRaised();
}
return;
} else {
for (const auto& p : participants_) {
if (auto call = getCall(p)) {
auto isPeerRequiringAttention = isHandRaised(participant_id);
if (participant_id == string_remove_suffix(call->getPeerNumber(), '@')) {
if (state and not isPeerRequiringAttention) {
JAMI_DBG("Raise %s hand", participant_id.c_str());
handsRaised_.emplace(participant_id);
updateHandsRaised();
} else if (not state and isPeerRequiringAttention) {
JAMI_DBG("Remove %s raised hand", participant_id.c_str());
handsRaised_.erase(participant_id);
updateHandsRaised();
}
return;
}
}
}
}
JAMI_WARN("Fail to raise %s hand (participant not found)", participant_id.c_str());
}
void void
Conference::setModerator(const std::string& participant_id, const bool& state) Conference::setModerator(const std::string& participant_id, const bool& state)
{ {
...@@ -919,6 +972,16 @@ Conference::updateModerators() ...@@ -919,6 +972,16 @@ Conference::updateModerators()
sendConferenceInfos(); sendConferenceInfos();
} }
void
Conference::updateHandsRaised()
{
std::lock_guard<std::mutex> lk(confInfoMutex_);
for (auto& info : confInfo_) {
info.handRaised = isHandRaised(string_remove_suffix(info.uri, '@'));
}
sendConferenceInfos();
}
bool bool
Conference::isMuted(std::string_view uri) const Conference::isMuted(std::string_view uri) const
{ {
......
...@@ -70,6 +70,7 @@ struct ParticipantInfo ...@@ -70,6 +70,7 @@ struct ParticipantInfo
bool audioLocalMuted {false}; bool audioLocalMuted {false};
bool audioModeratorMuted {false}; bool audioModeratorMuted {false};
bool isModerator {false}; bool isModerator {false};
bool handRaised {false};
void fromJson(const Json::Value& v) void fromJson(const Json::Value& v)
{ {
...@@ -85,6 +86,7 @@ struct ParticipantInfo ...@@ -85,6 +86,7 @@ struct ParticipantInfo
audioLocalMuted = v["audioLocalMuted"].asBool(); audioLocalMuted = v["audioLocalMuted"].asBool();
audioModeratorMuted = v["audioModeratorMuted"].asBool(); audioModeratorMuted = v["audioModeratorMuted"].asBool();
isModerator = v["isModerator"].asBool(); isModerator = v["isModerator"].asBool();
handRaised = v["handRaised"].asBool();
} }
Json::Value toJson() const Json::Value toJson() const
...@@ -102,6 +104,7 @@ struct ParticipantInfo ...@@ -102,6 +104,7 @@ struct ParticipantInfo
val["audioLocalMuted"] = audioLocalMuted; val["audioLocalMuted"] = audioLocalMuted;
val["audioModeratorMuted"] = audioModeratorMuted; val["audioModeratorMuted"] = audioModeratorMuted;
val["isModerator"] = isModerator; val["isModerator"] = isModerator;
val["handRaised"] = handRaised;
return val; return val;
} }
...@@ -118,7 +121,8 @@ struct ParticipantInfo ...@@ -118,7 +121,8 @@ struct ParticipantInfo
{"videoMuted", videoMuted ? "true" : "false"}, {"videoMuted", videoMuted ? "true" : "false"},
{"audioLocalMuted", audioLocalMuted ? "true" : "false"}, {"audioLocalMuted", audioLocalMuted ? "true" : "false"},
{"audioModeratorMuted", audioModeratorMuted ? "true" : "false"}, {"audioModeratorMuted", audioModeratorMuted ? "true" : "false"},
{"isModerator", isModerator ? "true" : "false"}}; {"isModerator", isModerator ? "true" : "false"},
{"handRaised", handRaised ? "true" : "false"}};
} }
friend bool operator==(const ParticipantInfo& p1, const ParticipantInfo& p2) friend bool operator==(const ParticipantInfo& p1, const ParticipantInfo& p2)
...@@ -128,7 +132,7 @@ struct ParticipantInfo ...@@ -128,7 +132,7 @@ struct ParticipantInfo
and p1.h == p2.h and p1.videoMuted == p2.videoMuted and p1.h == p2.h and p1.videoMuted == p2.videoMuted
and p1.audioLocalMuted == p2.audioLocalMuted and p1.audioLocalMuted == p2.audioLocalMuted
and p1.audioModeratorMuted == p2.audioModeratorMuted and p1.audioModeratorMuted == p2.audioModeratorMuted
and p1.isModerator == p2.isModerator; and p1.isModerator == p2.isModerator and p1.handRaised == p2.handRaised;
} }
friend bool operator!=(const ParticipantInfo& p1, const ParticipantInfo& p2) friend bool operator!=(const ParticipantInfo& p1, const ParticipantInfo& p2)
...@@ -320,6 +324,7 @@ public: ...@@ -320,6 +324,7 @@ public:
void updateConferenceInfo(ConfInfo confInfo); void updateConferenceInfo(ConfInfo confInfo);
void createSinks(const ConfInfo& infos); void createSinks(const ConfInfo& infos);
void setModerator(const std::string& uri, const bool& state); void setModerator(const std::string& uri, const bool& state);
void setHandRaised(const std::string& uri, const bool& state);
void muteParticipant(const std::string& uri, const bool& state); void muteParticipant(const std::string& uri, const bool& state);
void hangupParticipant(const std::string& participant_id); void hangupParticipant(const std::string& participant_id);
void updateMuted(); void updateMuted();
...@@ -335,7 +340,9 @@ private: ...@@ -335,7 +340,9 @@ private:
static std::shared_ptr<Call> getCall(const std::string& callId); static std::shared_ptr<Call> getCall(const std::string& callId);
bool isModerator(std::string_view uri) const; bool isModerator(std::string_view uri) const;
bool isHandRaised(std::string_view uri) const;
void updateModerators(); void updateModerators();
void updateHandsRaised();
std::string id_; std::string id_;
State confState_ {State::ACTIVE_ATTACHED}; State confState_ {State::ACTIVE_ATTACHED};
...@@ -361,6 +368,7 @@ private: ...@@ -361,6 +368,7 @@ private:
std::shared_ptr<jami::AudioInput> audioMixer_; std::shared_ptr<jami::AudioInput> audioMixer_;
std::set<std::string, std::less<>> moderators_ {}; std::set<std::string, std::less<>> moderators_ {};
std::set<std::string, std::less<>> participantsMuted_ {}; std::set<std::string, std::less<>> participantsMuted_ {};
std::set<std::string, std::less<>> handsRaised_;
void initRecorder(std::shared_ptr<MediaRecorder>& rec); void initRecorder(std::shared_ptr<MediaRecorder>& rec);
void deinitRecorder(std::shared_ptr<MediaRecorder>& rec); void deinitRecorder(std::shared_ptr<MediaRecorder>& rec);
......
...@@ -97,6 +97,10 @@ DRING_PUBLIC void setModerator(const std::string& confId, ...@@ -97,6 +97,10 @@ DRING_PUBLIC void setModerator(const std::string& confId,
DRING_PUBLIC void muteParticipant(const std::string& confId, DRING_PUBLIC void muteParticipant(const std::string& confId,
const std::string& peerId, const std::string& peerId,
const bool& state); const bool& state);
DRING_PUBLIC void raiseParticipantHand(const std::string& accountId,
const std::string& confId,
const std::string& peerId,
const bool& state);
DRING_PUBLIC void hangupParticipant(const std::string& confId, const std::string& participant); DRING_PUBLIC void hangupParticipant(const std::string& confId, const std::string& participant);
/* Statistic related methods */ /* Statistic related methods */
......
...@@ -3583,6 +3583,22 @@ Manager::muteParticipant(const std::string& confId, ...@@ -3583,6 +3583,22 @@ Manager::muteParticipant(const std::string& confId,
} }
} }
void
Manager::raiseParticipantHand(const std::string& confId,
const std::string& participant,
const bool& state)
{
if (auto conf = getConferenceFromID(confId)) {
conf->setHandRaised(participant, state);
} else if (auto call = getCallFromCallID(confId)) {
std::map<std::string, std::string> messages;
Json::Value root;
root["handRaised"] = participant;
root["handState"] = state ? TRUE_STR : FALSE_STR;
call->sendConfOrder(root);
}
}
void void
Manager::setDefaultModerator(const std::string& accountID, const std::string& peerURI, bool state) Manager::setDefaultModerator(const std::string& accountID, const std::string& peerURI, bool state)
{ {
......
...@@ -1023,6 +1023,9 @@ public: ...@@ -1023,6 +1023,9 @@ public:
void setModerator(const std::string& confId, const std::string& peerId, const bool& state); void setModerator(const std::string& confId, const std::string& peerId, const bool& state);
void muteParticipant(const std::string& confId, const std::string& peerId, const bool& state); void muteParticipant(const std::string& confId, const std::string& peerId, const bool& state);
void hangupParticipant(const std::string& confId, const std::string& participant); void hangupParticipant(const std::string& confId, const std::string& participant);
void raiseParticipantHand(const std::string& confId,
const std::string& participant,
const bool& state);
void setDefaultModerator(const std::string& accountID, const std::string& peerURI, bool state); void setDefaultModerator(const std::string& accountID, const std::string& peerURI, bool state);
std::vector<std::string> getDefaultModerators(const std::string& accountID); std::vector<std::string> getDefaultModerators(const std::string& accountID);
......
...@@ -43,12 +43,14 @@ struct CallData ...@@ -43,12 +43,14 @@ struct CallData
std::string callId {}; std::string callId {};
std::string state {}; std::string state {};
std::atomic_bool moderatorMuted {false}; std::atomic_bool moderatorMuted {false};
std::atomic_bool raisedHand {false};
void reset() void reset()
{ {
callId = ""; callId = "";
state = ""; state = "";
moderatorMuted = false; moderatorMuted = false;
raisedHand = false;
} }
}; };
...@@ -73,6 +75,7 @@ private: ...@@ -73,6 +75,7 @@ private:
void testAudioVideoMutedStates(); void testAudioVideoMutedStates();
void testCreateParticipantsSinks(); void testCreateParticipantsSinks();
void testMuteStatusAfterRemove(); void testMuteStatusAfterRemove();
void testHandsUp();
CPPUNIT_TEST_SUITE(ConferenceTest); CPPUNIT_TEST_SUITE(ConferenceTest);
CPPUNIT_TEST(testGetConference); CPPUNIT_TEST(testGetConference);
...@@ -80,6 +83,7 @@ private: ...@@ -80,6 +83,7 @@ private:
CPPUNIT_TEST(testAudioVideoMutedStates); CPPUNIT_TEST(testAudioVideoMutedStates);
CPPUNIT_TEST(testCreateParticipantsSinks); CPPUNIT_TEST(testCreateParticipantsSinks);
CPPUNIT_TEST(testMuteStatusAfterRemove); CPPUNIT_TEST(testMuteStatusAfterRemove);
CPPUNIT_TEST(testHandsUp);
CPPUNIT_TEST_SUITE_END(); CPPUNIT_TEST_SUITE_END();
// Common parts // Common parts
...@@ -179,10 +183,13 @@ ConferenceTest::registerSignalHandlers() ...@@ -179,10 +183,13 @@ ConferenceTest::registerSignalHandlers()
for (const auto& infos : participantsInfos) { for (const auto& infos : participantsInfos) {
if (infos.at("uri").find(bobUri) != std::string::npos) { if (infos.at("uri").find(bobUri) != std::string::npos) {
bobCall.moderatorMuted = infos.at("audioModeratorMuted") == "true"; bobCall.moderatorMuted = infos.at("audioModeratorMuted") == "true";
bobCall.raisedHand = infos.at("handRaised") == "true";
} else if (infos.at("uri").find(carlaUri) != std::string::npos) { } else if (infos.at("uri").find(carlaUri) != std::string::npos) {
carlaCall.moderatorMuted = infos.at("audioModeratorMuted") == "true"; carlaCall.moderatorMuted = infos.at("audioModeratorMuted") == "true";
carlaCall.raisedHand = infos.at("handRaised") == "true";
} else if (infos.at("uri").find(daviUri) != std::string::npos) { } else if (infos.at("uri").find(daviUri) != std::string::npos) {
daviCall.moderatorMuted = infos.at("audioModeratorMuted") == "true"; daviCall.moderatorMuted = infos.at("audioModeratorMuted") == "true";
daviCall.raisedHand = infos.at("handRaised") == "true";
} }
} }
cv.notify_one(); cv.notify_one();
...@@ -405,6 +412,65 @@ ConferenceTest::testMuteStatusAfterRemove() ...@@ -405,6 +412,65 @@ ConferenceTest::testMuteStatusAfterRemove()
DRing::unregisterSignalHandlers(); DRing::unregisterSignalHandlers();
} }
void
ConferenceTest::testHandsUp()
{
registerSignalHandlers();
auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobId);
auto bobUri = bobAccount->getUsername();
auto daviAccount = Manager::instance().getAccount<JamiAccount>(daviId);
auto daviUri = daviAccount->getUsername();
startConference();
JAMI_INFO("Play with raise hand");
Manager::instance().raiseParticipantHand(confId, bobUri, true);
CPPUNIT_ASSERT(
cv.wait_for(lk, std::chrono::seconds(5), [&] { return bobCall.raisedHand.load(); }));
Manager::instance().raiseParticipantHand(confId, bobUri, false);
CPPUNIT_ASSERT(
cv.wait_for(lk, std::chrono::seconds(5), [&] { return !bobCall.raisedHand.load(); }));
JAMI_INFO("Start call between Alice and Davi");
auto call1 = aliceAccount->newOutgoingCall(daviUri);
CPPUNIT_ASSERT(
cv.wait_for(lk, std::chrono::seconds(20), [&] { return !daviCall.callId.empty(); }));
Manager::instance().answerCall(daviCall.callId);
CPPUNIT_ASSERT(
cv.wait_for(lk, std::chrono::seconds(20), [&] { return daviCall.state == "CURRENT"; }));
Manager::instance().addParticipant(daviCall.callId, confId);
Manager::instance().raiseParticipantHand(confId, daviUri, true);
CPPUNIT_ASSERT(
cv.wait_for(lk, std::chrono::seconds(5), [&] { return daviCall.raisedHand.load(); }));
Manager::instance().hangupCall(daviCall.callId);
CPPUNIT_ASSERT(
cv.wait_for(lk, std::chrono::seconds(20), [&] { return daviCall.state == "OVER"; }));
daviCall.reset();
auto call2 = aliceAccount->newOutgoingCall(daviUri);
CPPUNIT_ASSERT(
cv.wait_for(lk, std::chrono::seconds(20), [&] { return !daviCall.callId.empty(); }));
Manager::instance().answerCall(daviCall.callId);
CPPUNIT_ASSERT(
cv.wait_for(lk, std::chrono::seconds(20), [&] { return daviCall.state == "CURRENT"; }));
Manager::instance().addParticipant(daviCall.callId, confId);
CPPUNIT_ASSERT(
cv.wait_for(lk, std::chrono::seconds(5), [&] { return !daviCall.raisedHand.load(); }));
Manager::instance().hangupCall(daviCall.callId);
CPPUNIT_ASSERT(
cv.wait_for(lk, std::chrono::seconds(20), [&] { return daviCall.state == "OVER"; }));
hangupConference();
DRing::unregisterSignalHandlers();
}
} // namespace test } // namespace test
} // namespace jami } // namespace jami
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment