From 75ec461623bee3a808f5a88a4a66ade729f74bc3 Mon Sep 17 00:00:00 2001 From: Pierre Lespagnol <pierre.lespagnol@savoirfairelinux.com> Date: Mon, 9 Nov 2020 11:02:27 -0500 Subject: [PATCH] conference: host can add or remove moderator Change-Id: Idc4c6db249de7247d02c7cabb897d638c69674f3 --- bin/dbus/cx.ring.Ring.CallManager.xml | 6 ++++ bin/dbus/dbuscallmanager.cpp | 6 ++++ bin/dbus/dbuscallmanager.h | 1 + bin/jni/callmanager.i | 1 + bin/nodejs/callmanager.i | 1 + configure.ac | 2 +- src/client/callmanager.cpp | 8 +++++ src/conference.cpp | 47 +++++++++++++++++++++++++-- src/conference.h | 5 ++- src/dring/callmanager_interface.h | 1 + src/manager.cpp | 9 +++++ src/manager.h | 2 ++ 12 files changed, 84 insertions(+), 5 deletions(-) diff --git a/bin/dbus/cx.ring.Ring.CallManager.xml b/bin/dbus/cx.ring.Ring.CallManager.xml index 7ae32d13dc..febb490e8a 100644 --- a/bin/dbus/cx.ring.Ring.CallManager.xml +++ b/bin/dbus/cx.ring.Ring.CallManager.xml @@ -251,6 +251,12 @@ <arg type="s" name="callId" direction="in"/> </method> + <method name="setModerator" tp:name-for-bindings="setModerator"> + <tp:added version="9.6.0"/> + <arg type="s" name="confId" direction="in"/> + <arg type="s" name="peerId" direction="in"/> + <arg type="b" name="state" direction="in"/> + </method> <method name="isConferenceParticipant" tp:name-for-bindings="isConferenceParticipant"> <arg type="s" name="callID" direction="in"/> diff --git a/bin/dbus/dbuscallmanager.cpp b/bin/dbus/dbuscallmanager.cpp index ff4da48846..9ccbc71462 100644 --- a/bin/dbus/dbuscallmanager.cpp +++ b/bin/dbus/dbuscallmanager.cpp @@ -297,3 +297,9 @@ DBusCallManager::stopSmartInfo() { DRing::stopSmartInfo(); } + +void +DBusCallManager::setModerator(const std::string& confId, const std::string& peerId, const bool& state) +{ + DRing::setModerator(confId, peerId, state); +} diff --git a/bin/dbus/dbuscallmanager.h b/bin/dbus/dbuscallmanager.h index bb3f547c13..ecbe7f64e2 100644 --- a/bin/dbus/dbuscallmanager.h +++ b/bin/dbus/dbuscallmanager.h @@ -101,6 +101,7 @@ class DRING_PUBLIC DBusCallManager : void sendTextMessage(const std::string& callID, const std::map<std::string, std::string>& messages, const bool& isMixed); void startSmartInfo(const uint32_t& refreshTimeMs); void stopSmartInfo(); + void setModerator(const std::string& confId, const std::string& peerId, const bool& state); }; #endif // __RING_CALLMANAGER_H__ diff --git a/bin/jni/callmanager.i b/bin/jni/callmanager.i index 077e6b4b8d..d0167c43c5 100644 --- a/bin/jni/callmanager.i +++ b/bin/jni/callmanager.i @@ -92,6 +92,7 @@ std::vector<std::string> getDisplayNames(const std::string& confID); std::string getConferenceId(const std::string& callID); std::map<std::string, std::string> getConferenceDetails(const std::string& callID); std::vector<std::map<std::string, std::string>> getConferenceInfos(const std::string& confId); +void setModerator(const std::string& confId, const std::string& peerId, const bool& state); /* File Playback methods */ bool startRecordedFilePlayback(const std::string& filepath); diff --git a/bin/nodejs/callmanager.i b/bin/nodejs/callmanager.i index b213005a0b..4b5fdc40fc 100644 --- a/bin/nodejs/callmanager.i +++ b/bin/nodejs/callmanager.i @@ -90,6 +90,7 @@ std::vector<std::string> getDisplayNames(const std::string& confID); std::string getConferenceId(const std::string& callID); std::map<std::string, std::string> getConferenceDetails(const std::string& callID); std::vector<std::map<std::string, std::string>> getConferenceInfos(const std::string& confId); +void setModerator(const std::string& confId, const std::string& peerId, const bool& state); /* File Playback methods */ bool startRecordedFilePlayback(const std::string& filepath); diff --git a/configure.ac b/configure.ac index 604c07c7c0..c59ca27264 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ dnl Jami - configure.ac for automake 1.9 and autoconf 2.59 dnl Process this file with autoconf to produce a configure script. AC_PREREQ([2.65]) -AC_INIT([Jami Daemon],[9.5.0],[ring@gnu.org],[jami]) +AC_INIT([Jami Daemon],[9.6.0],[ring@gnu.org],[jami]) AC_COPYRIGHT([[Copyright (c) Savoir-faire Linux 2004-2020]]) AC_REVISION([$Revision$]) diff --git a/src/client/callmanager.cpp b/src/client/callmanager.cpp index 12616ef286..bd7b63bc7d 100644 --- a/src/client/callmanager.cpp +++ b/src/client/callmanager.cpp @@ -343,4 +343,12 @@ sendTextMessage(const std::string& callID, }); } +void +setModerator(const std::string& confId, + const std::string& peerId, + const bool& state) +{ + jami::Manager::instance().setModerator(confId, peerId, state); +} + } // namespace DRing diff --git a/src/conference.cpp b/src/conference.cpp index 4aa222e352..88550b8eeb 100644 --- a/src/conference.cpp +++ b/src/conference.cpp @@ -53,11 +53,10 @@ Conference::Conference() // conference master. In the future, this should be // retrieven with another way auto accounts = jami::Manager::instance().getAllAccounts<JamiAccount>(); - moderators_.reserve(accounts.size()); for (const auto& account : accounts) { if (!account) continue; - moderators_.emplace_back(account->getUsername()); + moderators_.emplace(account->getUsername()); } #ifdef ENABLE_VIDEO @@ -493,7 +492,7 @@ Conference::onConfOrder(const std::string& callId, const std::string& confOrder) auto uri = call->getPeerNumber(); auto separator = uri.find('@'); if (separator != std::string::npos) - uri = uri.substr(0, separator - 1); + uri = uri.substr(0, separator); if (!isModerator(uri)) { JAMI_WARN("Received conference order from a non master (%s)", uri.c_str()); return; @@ -527,4 +526,46 @@ Conference::isModerator(const std::string& uri) const != moderators_.end(); } +void +Conference::setModerator(const std::string& uri, const bool& state) +{ + for (const auto& p : participants_) { + if (auto call = Manager::instance().callFactory.getCall<SIPCall>(p)) { + auto partURI = call->getPeerNumber(); + auto separator = partURI.find('@'); + if (separator != std::string::npos) + partURI = partURI.substr(0, separator); + if (partURI == uri) { + if (state and not isModerator(uri)) { + JAMI_DBG("Add %s as moderator", partURI.c_str()); + moderators_.emplace(uri); + updateModerators(); + } else if (not state and isModerator(uri)) { + JAMI_DBG("Remove %s as moderator", partURI.c_str()); + moderators_.erase(uri); + updateModerators(); + } + return; + } + } + } + JAMI_WARN("Fail to set %s as moderator (participant not found)", uri.c_str()); +} + +void +Conference::updateModerators() +{ + { + std::lock_guard<std::mutex> lk2(confInfoMutex_); + for (auto& info : confInfo_) { + auto uri = info.uri; + auto separator = uri.find('@'); + if (separator != std::string::npos) + uri = uri.substr(0, separator); + info.isModerator = isModerator(uri); + } + } + sendConferenceInfos(); +} + } // namespace jami diff --git a/src/conference.h b/src/conference.h index 709274b236..51c338aee5 100644 --- a/src/conference.h +++ b/src/conference.h @@ -202,6 +202,7 @@ public: void detachVideo(Observable<std::shared_ptr<MediaFrame>>* frame); void onConfOrder(const std::string& callId, const std::string& order); + void setModerator(const std::string& uri, const bool& state); #ifdef ENABLE_VIDEO std::shared_ptr<video::VideoMixer> getVideoMixer(); @@ -240,10 +241,12 @@ private: #endif std::shared_ptr<jami::AudioInput> audioMixer_; - std::vector<std::string> moderators_ {}; + std::set<std::string> moderators_ {}; void initRecorder(std::shared_ptr<MediaRecorder>& rec); void deinitRecorder(std::shared_ptr<MediaRecorder>& rec); + + void updateModerators(); }; } // namespace jami diff --git a/src/dring/callmanager_interface.h b/src/dring/callmanager_interface.h index 41baed45c6..0fb9873aa1 100644 --- a/src/dring/callmanager_interface.h +++ b/src/dring/callmanager_interface.h @@ -77,6 +77,7 @@ DRING_PUBLIC std::string getConferenceId(const std::string& callID); DRING_PUBLIC std::map<std::string, std::string> getConferenceDetails(const std::string& callID); DRING_PUBLIC std::vector<std::map<std::string, std::string>> getConferenceInfos( const std::string& confId); +DRING_PUBLIC void setModerator(const std::string& confId, const std::string& peerId, const bool& state); /* Statistic related methods */ DRING_PUBLIC void startSmartInfo(uint32_t refreshTimeMs); diff --git a/src/manager.cpp b/src/manager.cpp index 413cd37037..b92a8b592b 100644 --- a/src/manager.cpp +++ b/src/manager.cpp @@ -3222,4 +3222,13 @@ Manager::getNearbyPeers(const std::string& accountID) return {}; } +void +Manager::setModerator(const std::string& confId, const std::string& peerId, const bool& state) +{ + if (auto conf = getConferenceFromID(confId)) { + conf->setModerator(peerId, state); + } else + JAMI_WARN("Fail to change moderator %s, conference %s not found", peerId.c_str(), confId.c_str()); +} + } // namespace jami diff --git a/src/manager.h b/src/manager.h index db7420e28b..759f78fc2a 100644 --- a/src/manager.h +++ b/src/manager.h @@ -934,6 +934,8 @@ public: JamiPluginManager& getJamiPluginManager() const; #endif + void setModerator(const std::string& confId, const std::string& peerId, const bool& state); + private: Manager(); ~Manager(); -- GitLab