diff --git a/src/call.cpp b/src/call.cpp index 597989aa60bf913a51e36721948c1df1d251b788..38687832e57d41e8feccac3343dcfa3d43082265 100644 --- a/src/call.cpp +++ b/src/call.cpp @@ -643,15 +643,42 @@ Call::setConferenceInfo(const std::string& msg) } } - std::vector<std::map<std::string, std::string>> toSend; { std::lock_guard<std::mutex> lk(confInfoMutex_); - confInfo_ = std::move(newInfo); - toSend = confInfo_.toVectorMapStringString(); + if (confID_.empty()) { + // confID_ empty -> participant set confInfo with the received one + confInfo_ = std::move(newInfo); + std::vector<std::map<std::string, std::string>> toSend = + confInfo_.toVectorMapStringString(); + + // Inform client that layout has changed + jami::emitSignal<DRing::CallSignal::OnConferenceInfosUpdated>(id_, std::move(toSend)); + } else { + // confID_ not empty -> host merge confInfo with the received confInfo + auto oldInfo = confInfo_; + for (auto& newI : newInfo) { + bool isNewParticipant = true; + for (auto& oldI : oldInfo) { + if (newI.uri == oldI.uri) { + oldI = newI; + isNewParticipant = false; + break; + } + } + if (isNewParticipant) { + // ParticipantInfo not present in confInfo -> the sender of newInfo ... + // is currently hosting another conference. Add the unknown participant ... + // to the confInfo + oldInfo.emplace_back(newI); + } + } + confInfo_ = std::move(oldInfo); + + if (auto conf = Manager::instance().getConferenceFromID(confID_)) + conf->updateConferenceInfo(confInfo_); + } } - // Inform client that layout has changed - jami::emitSignal<DRing::CallSignal::OnConferenceInfosUpdated>(id_, std::move(toSend)); } } // namespace jami diff --git a/src/conference.cpp b/src/conference.cpp index b7031719d6c4011dd6991c4fa4be11283b098462..46fb35a332137438000b0ce3b59784ac2d06dca2 100644 --- a/src/conference.cpp +++ b/src/conference.cpp @@ -97,6 +97,7 @@ Conference::Conference() partURI = partURI.substr(0, separator); auto isModerator = shared->isModerator(partURI); newInfo.emplace_back(ParticipantInfo {std::move(uri), + "", active, info.x, info.y, @@ -114,7 +115,7 @@ Conference::Conference() uri = call->getPeerNumber(); auto isModerator = shared->isModerator(uri); newInfo.emplace_back( - ParticipantInfo {std::move(uri), false, 0, 0, 0, 0, true, false, isModerator}); + ParticipantInfo {std::move(uri), "", false, 0, 0, 0, 0, true, false, isModerator}); } { @@ -249,33 +250,37 @@ ConfInfo::toVectorMapStringString() const void Conference::sendConferenceInfos() { - Json::Value jsonArray; - std::vector<std::map<std::string, std::string>> toSend; - { - std::lock_guard<std::mutex> lk2(confInfoMutex_); - for (const auto& info : confInfo_) { - jsonArray.append(info.toJson()); - } - toSend = confInfo_.toVectorMapStringString(); - } - - Json::StreamWriterBuilder builder; - const auto confInfo = Json::writeString(builder, jsonArray); // Inform calls that the layout has changed for (const auto& participant_id : participants_) { + // Produce specific JSON for each participant (2 separate accounts can host ... + // a conference on a same device, the conference is not link to one account). if (auto call = Manager::instance().callFactory.getCall<SIPCall>(participant_id)) { auto w = call->getAccount(); auto account = w.lock(); if (!account) continue; + + ConfInfo confInfo = std::move(getConfInfoHostUri(account->getUsername()+ "@ring.dht")); + Json::Value jsonArray = {}; + std::vector<std::map<std::string, std::string>> toSend = {}; + { + std::lock_guard<std::mutex> lk2(confInfoMutex_); + for (const auto& info : confInfo) { + jsonArray.append(info.toJson()); + } + toSend = confInfo.toVectorMapStringString(); + } + + Json::StreamWriterBuilder builder = {}; + const auto confInfoStr = Json::writeString(builder, jsonArray); call->sendTextMessage(std::map<std::string, std::string> {{"application/confInfo+json", - confInfo}}, - account->getFromUri()); + confInfoStr}}, + account->getFromUri()); } } // Inform client that layout has changed - jami::emitSignal<DRing::CallSignal::OnConferenceInfosUpdated>(id_, std::move(toSend)); + jami::emitSignal<DRing::CallSignal::OnConferenceInfosUpdated>(id_, confInfo_.toVectorMapStringString()); } void @@ -572,4 +577,24 @@ Conference::updateModerators() sendConferenceInfos(); } +ConfInfo +Conference::getConfInfoHostUri(const std::string& uri) +{ + ConfInfo newInfo = confInfo_; + for (auto& info : newInfo) { + if (info.uri.empty()) { + info.uri = uri; + break; + } + } + return newInfo; +} + +void +Conference::updateConferenceInfo(ConfInfo confInfo) +{ + confInfo_ = std::move(confInfo); + sendConferenceInfos(); +} + } // namespace jami diff --git a/src/conference.h b/src/conference.h index 51c338aee55fb4b5e07d85bc06124935a4c063e8..de66bf937f6050f6dd8075428a714e575415f46a 100644 --- a/src/conference.h +++ b/src/conference.h @@ -46,6 +46,7 @@ class VideoMixer; struct ParticipantInfo { std::string uri; + std::string device; bool active {false}; int x {0}; int y {0}; @@ -58,6 +59,7 @@ struct ParticipantInfo void fromJson(const Json::Value& v) { uri = v["uri"].asString(); + device = v["device"].asString(); active = v["active"].asBool(); x = v["x"].asInt(); y = v["y"].asInt(); @@ -72,6 +74,7 @@ struct ParticipantInfo { Json::Value val; val["uri"] = uri; + val["device"] = device; val["active"] = active; val["x"] = x; val["y"] = y; @@ -86,6 +89,7 @@ struct ParticipantInfo std::map<std::string, std::string> toMap() const { return {{"uri", uri}, + {"device", device}, {"active", active ? "true" : "false"}, {"x", std::to_string(x)}, {"y", std::to_string(y)}, @@ -215,6 +219,8 @@ public: return confInfo_.toVectorMapStringString(); } + void updateConferenceInfo(ConfInfo confInfo); + private: std::weak_ptr<Conference> weak() { @@ -247,6 +253,8 @@ private: void deinitRecorder(std::shared_ptr<MediaRecorder>& rec); void updateModerators(); + + ConfInfo getConfInfoHostUri(const std::string& uri); }; } // namespace jami