diff --git a/src/calladapter.cpp b/src/calladapter.cpp index 23854a758f39c8ec0a25ac1a15ee4387df306eb2..2797a82d2923ea9a8baa68bc3dbb560c66546a9b 100644 --- a/src/calladapter.cpp +++ b/src/calladapter.cpp @@ -331,6 +331,7 @@ CallAdapter::connectCallModel(const QString& accountId) auto& callModel = accInfo.callModel; auto call = callModel->getCall(confId); const auto convInfo = LRCInstance::getConversationFromCallId(confId); + bool currentMuted = false; if (!convInfo.uid.isEmpty()) { // Convert to QML QVariantList map; @@ -350,6 +351,7 @@ CallAdapter::connectCallModel(const QString& accountId) if (bestName == accInfo.profileInfo.uri) { bestName = tr("me"); data["isLocal"] = true; + currentMuted = participant["audioMuted"] == "true"; if (participant["videoMuted"] == "true") data["avatar"] = accInfo.profileInfo.avatar; } else { @@ -366,6 +368,19 @@ CallAdapter::connectCallModel(const QString& accountId) data["bestName"] = bestName; map.push_back(QVariant(data)); } + + // Link local mute to conference mute + auto* convModel = LRCInstance::getCurrentConversationModel(); + const auto convInfo = convModel->getConversationForUID(convUid_); + if (!convInfo.uid.isEmpty()) { + auto call = LRCInstance::getCallInfoForConversation(convInfo); + if (call) { + if (currentMuted != call->audioMuted) { + muteThisCallToggle(); + updateCallOverlay(convInfo); + } + } + } emit updateParticipantsInfos(map, accountId, confId); } }); @@ -700,6 +715,68 @@ CallAdapter::setModerator(const QString& uri, const bool state) } catch (...) {} } +void +CallAdapter::muteParticipant(const QString& uri, const bool state) { + + auto* callModel = LRCInstance::getAccountInfo(accountId_).callModel.get(); + auto* convModel = LRCInstance::getCurrentConversationModel(); + const auto conversation = convModel->getConversationForUID(LRCInstance::getCurrentConvUid()); + auto confId = conversation.confId; + if (confId.isEmpty()) + confId = conversation.callId; + try { + const auto call = callModel->getCall(confId); + callModel->muteParticipant(confId, uri, state); + } catch (...) {} +} + +bool +CallAdapter::isMuted(const QString& uri) const +{ + auto* convModel = LRCInstance::getCurrentConversationModel(); + const auto convInfo = convModel->getConversationForUID(convUid_); + auto* callModel = LRCInstance::getAccountInfo(accountId_).callModel.get(); + auto confId = convInfo.confId.isEmpty() ? convInfo.callId : convInfo.confId; + try { + auto call = callModel->getCall(confId); + if (call.participantsInfos.size() == 0) { + return false; + } else { + for (const auto& participant : call.participantsInfos) { + if (participant["uri"] == uri) + return participant["audioMuted"] == "true"; + } + } + return false; + } catch (...) { + } + return false; +} + +bool +CallAdapter::isCurrentMuted() const +{ + auto* convModel = LRCInstance::getCurrentConversationModel(); + const auto convInfo = convModel->getConversationForUID(convUid_); + if (!convInfo.uid.isEmpty()) { + auto* callModel = LRCInstance::getAccountInfo(accountId_).callModel.get(); + try { + auto call = callModel->getCall(convInfo.callId); + if (call.participantsInfos.size() == 0) { + return false; + } else { + auto& accInfo = LRCInstance::accountModel().getAccountInfo(accountId_); + for (const auto& participant : call.participantsInfos) { + if (participant["uri"] == accInfo.profileInfo.uri) + return participant["audioMuted"] == "true"; + } + } + return false; + } catch (...) { + } + } + return true; +} int CallAdapter::getCurrentLayoutType() const diff --git a/src/calladapter.h b/src/calladapter.h index a2a0da421575c3ce65897b8df4d9401972ee7a65..af6a3a25526f92eeb0edda6e35b0370040483174 100644 --- a/src/calladapter.h +++ b/src/calladapter.h @@ -68,6 +68,9 @@ public: Q_INVOKABLE void videoPauseThisCallToggle(); Q_INVOKABLE bool isRecordingThisCall(); Q_INVOKABLE QVariantList getConferencesInfos(); + Q_INVOKABLE void muteParticipant(const QString& uri, const bool state); + Q_INVOKABLE bool isMuted(const QString& uri) const; + Q_INVOKABLE bool isCurrentMuted() const; signals: void callStatusChanged(int index, const QString& accountId, const QString& convUid); diff --git a/src/mainview/components/CallOverlay.qml b/src/mainview/components/CallOverlay.qml index 05bbe0dabb57462a1d72b62bc0b9b66fff310c5a..d2c8bae009a25880a2b4c6e819db46e3c364e428 100644 --- a/src/mainview/components/CallOverlay.qml +++ b/src/mainview/components/CallOverlay.qml @@ -74,7 +74,7 @@ Rectangle { function closePotentialMediaHandlerPicker() { MediaHandlerPickerCreation.closeMediaHandlerPicker() } - + function handleParticipantsInfo(infos) { videoCallOverlay.updateMenu() var isModerator = CallAdapter.isCurrentModerator() diff --git a/src/mainview/components/ParticipantContextMenu.qml b/src/mainview/components/ParticipantContextMenu.qml index e508dabf9c3b4ea2daf98b3b3b0ed381c5e354d6..5c9f4985ac3dcc0e0cbcbac55b04b22cda9094b4 100644 --- a/src/mainview/components/ParticipantContextMenu.qml +++ b/src/mainview/components/ParticipantContextMenu.qml @@ -37,6 +37,8 @@ Item { property var showMinimize: false property var showSetModerator: false property var showUnsetModerator: false + property var showMute: false + property var showUnmute: false function openMenu(){ ContextMenuGenerator.initMenu() @@ -74,6 +76,21 @@ Item { CallAdapter.setModerator(uri, false) }) + if (showMute) + ContextMenuGenerator.addMenuItem(qsTr("Mute participant"), + "qrc:/images/icons/mic_off-24px.svg", + function (){ + CallAdapter.muteParticipant(uri, true) + }) + + if (showUnmute) + ContextMenuGenerator.addMenuItem(qsTr("Unmute participant"), + "qrc:/images/icons/mic-24px.svg", + function (){ + CallAdapter.muteParticipant(uri, false) + }) + + root.height = ContextMenuGenerator.getMenu().height root.width = ContextMenuGenerator.getMenu().width ContextMenuGenerator.getMenu().open() diff --git a/src/mainview/components/ParticipantOverlay.qml b/src/mainview/components/ParticipantOverlay.qml index fc3cb6d8acb69c1f71d26dcac7ab6347aed6d58b..38e19e753d8abefad534418cf49fc701a1d3f07d 100644 --- a/src/mainview/components/ParticipantOverlay.qml +++ b/src/mainview/components/ParticipantOverlay.qml @@ -158,6 +158,7 @@ Rectangle { var isModerator = CallAdapter.isModerator(uri) var isHost = CallAdapter.isCurrentHost() var participantIsHost = CallAdapter.participantIsHost(uri) + var isMuted = CallAdapter.isMuted(uri) injectedContextMenu.showHangup = !root.isLocal && showEndCall injectedContextMenu.showMaximize = showMaximized injectedContextMenu.showMinimize = showMinimized @@ -167,6 +168,8 @@ Rectangle { injectedContextMenu.y = mousePos.y - injectedContextMenu.height injectedContextMenu.showSetModerator = (isHost && !participantIsHost && !isModerator) injectedContextMenu.showUnsetModerator = (isHost && !participantIsHost && isModerator) + injectedContextMenu.showMute = !isMuted + injectedContextMenu.showUnmute = isMuted && root.isLocal injectedContextMenu.openMenu() } }