1
0
Fork 0
mirror of https://git.jami.net/savoirfairelinux/jami-client-qt.git synced 2025-08-04 14:55:43 +02:00

vad: show a drop shadow around talking participants

use "voiceActivity" from the conferences informations to show
talking participants

https://git.jami.net/savoirfairelinux/jami-daemon/-/issues/741

Change-Id: Iaedc61ce485ff03464128b5a17e0a6a0ea9d2c2e
This commit is contained in:
Sébastien Blin 2022-08-01 11:06:32 -04:00
parent 17e97ded71
commit d7d29156db
9 changed files with 49 additions and 26 deletions

View file

@ -98,6 +98,9 @@ CallParticipantsModel::data(const QModelIndex& index, int role) const
case Role::HandRaised: case Role::HandRaised:
return QVariant::fromValue( return QVariant::fromValue(
participant.item.value(lrc::api::ParticipantsInfosStrings::HANDRAISED)); participant.item.value(lrc::api::ParticipantsInfosStrings::HANDRAISED));
case Role::VoiceActivity:
return QVariant::fromValue(
participant.item.value(lrc::api::ParticipantsInfosStrings::VOICEACTIVITY));
} }
return QVariant(); return QVariant();
} }

View file

@ -45,6 +45,7 @@
X(IsModerator) \ X(IsModerator) \
X(IsLocal) \ X(IsLocal) \
X(IsContact) \ X(IsContact) \
X(VoiceActivity) \
X(HandRaised) X(HandRaised)
namespace CallParticipant { namespace CallParticipant {

View file

@ -175,7 +175,7 @@ Rectangle {
id: participantsLayer id: participantsLayer
anchors.fill: parent anchors.fill: parent
anchors.centerIn: parent anchors.centerIn: parent
anchors.margins: 3 anchors.margins: 1
visible: participantsLayer.count !== 0 visible: participantsLayer.count !== 0
participantsSide: callOverlay.participantsSide participantsSide: callOverlay.participantsSide

View file

@ -56,6 +56,7 @@ Item {
property bool participantIsModeratorMuted: false property bool participantIsModeratorMuted: false
property bool participantHandIsRaised: false property bool participantHandIsRaised: false
property bool videoMuted: true property bool videoMuted: true
property bool voiceActive: false
property bool isLocalMuted: true property bool isLocalMuted: true
property bool meHost: CallAdapter.isCurrentHost() property bool meHost: CallAdapter.isCurrentHost()
@ -90,9 +91,21 @@ Item {
} }
} }
Rectangle {
z: -1
color: JamiTheme.buttonTintedBlue
radius: 10
visible:voiceActive
width: participantIsActive ? mediaDistRender.contentRect.width + 2 : undefined
height: participantIsActive ? mediaDistRender.contentRect.height + 2 : undefined
anchors.centerIn: participantIsActive ? parent : undefined
anchors.fill: participantIsActive ? undefined : parent
}
VideoView { VideoView {
id: mediaDistRender id: mediaDistRender
anchors.fill: parent anchors.fill: parent
anchors.margins: 2
rendererId: root.sinkId rendererId: root.sinkId
crop: !participantIsActive crop: !participantIsActive
@ -118,17 +131,13 @@ Item {
} }
} }
overlayItems: Rectangle { overlayItems: Item {
id: overlayRect id: overlayRect
width: participantIsActive ? mediaDistRender.contentRect.width : undefined width: participantIsActive ? mediaDistRender.contentRect.width - 2 : undefined
height: participantIsActive ? mediaDistRender.contentRect.height : undefined height: participantIsActive ? mediaDistRender.contentRect.height - 2 : undefined
anchors.centerIn: participantIsActive ? parent : undefined anchors.centerIn: participantIsActive ? parent : undefined
anchors.fill: participantIsActive ? undefined : parent anchors.fill: participantIsActive ? undefined : parent
color: "transparent"
Item {
anchors.fill: parent
HoverHandler { HoverHandler {
onPointChanged: { onPointChanged: {
@ -145,12 +154,10 @@ Item {
participantRect.opacity = hovered ? 1 : 0 participantRect.opacity = hovered ? 1 : 0
} }
} }
}
Rectangle { Item {
id: participantRect id: participantRect
anchors.fill: parent anchors.fill: parent
color: "transparent"
opacity: 0 opacity: 0
// Participant buttons for moderation // Participant buttons for moderation
@ -182,11 +189,10 @@ Item {
// - In another participant, if i am not moderator, the mute state is isLocalMuted || participantIsModeratorMuted // - In another participant, if i am not moderator, the mute state is isLocalMuted || participantIsModeratorMuted
// - In another participant, if i am moderator, the mute state is isLocalMuted // - In another participant, if i am moderator, the mute state is isLocalMuted
// - In my video, the mute state is isLocalMuted // - In my video, the mute state is isLocalMuted
Rectangle { Item {
id: participantIndicators id: participantIndicators
width: participantRect.width width: participantRect.width
height: shapeHeight height: shapeHeight
color: "transparent"
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
Shape { Shape {

View file

@ -19,8 +19,8 @@
import QtQuick import QtQuick
import QtQuick.Layouts 1.15 import QtQuick.Layouts
import QtQuick.Controls 2.15 import QtQuick.Controls
import net.jami.Adapters 1.1 import net.jami.Adapters 1.1
import net.jami.Models 1.1 import net.jami.Models 1.1
@ -55,6 +55,8 @@ Item {
id: callVideoMedia id: callVideoMedia
ParticipantOverlay { ParticipantOverlay {
id: overlay
anchors.fill: parent anchors.fill: parent
anchors.leftMargin: leftMargin_ anchors.leftMargin: leftMargin_
@ -71,6 +73,7 @@ Item {
videoMuted: videoMuted_ videoMuted: videoMuted_
participantIsActive: active_ participantIsActive: active_
isLocalMuted: audioLocalMuted_ isLocalMuted: audioLocalMuted_
voiceActive: voiceActive_
participantIsModeratorMuted: audioModeratorMuted_ participantIsModeratorMuted: audioModeratorMuted_
participantHandIsRaised: isHandRaised_ participantHandIsRaised: isHandRaised_

View file

@ -120,6 +120,7 @@ SplitView {
property bool audioLocalMuted_: AudioLocalMuted property bool audioLocalMuted_: AudioLocalMuted
property bool audioModeratorMuted_: AudioModeratorMuted property bool audioModeratorMuted_: AudioModeratorMuted
property bool isHandRaised_: HandRaised property bool isHandRaised_: HandRaised
property bool voiceActive_: VoiceActivity
} }
} }
} }
@ -307,6 +308,7 @@ SplitView {
property bool audioLocalMuted_: AudioLocalMuted property bool audioLocalMuted_: AudioLocalMuted
property bool audioModeratorMuted_: AudioModeratorMuted property bool audioModeratorMuted_: AudioModeratorMuted
property bool isHandRaised_: HandRaised property bool isHandRaised_: HandRaised
property bool voiceActive_: VoiceActivity
} }
} }
} }

View file

@ -215,6 +215,7 @@ SplitView {
property bool audioLocalMuted_: AudioLocalMuted property bool audioLocalMuted_: AudioLocalMuted
property bool audioModeratorMuted_: AudioModeratorMuted property bool audioModeratorMuted_: AudioModeratorMuted
property bool isHandRaised_: HandRaised property bool isHandRaised_: HandRaised
property bool voiceActive_: VoiceActivity
} }
} }
} }
@ -288,6 +289,7 @@ SplitView {
property bool audioLocalMuted_: AudioLocalMuted property bool audioLocalMuted_: AudioLocalMuted
property bool audioModeratorMuted_: AudioModeratorMuted property bool audioModeratorMuted_: AudioModeratorMuted
property bool isHandRaised_: HandRaised property bool isHandRaised_: HandRaised
property bool voiceActive_: VoiceActivity
} }
} }
} }

View file

@ -52,6 +52,7 @@ const QString AUDIOLOCALMUTED = "audioLocalMuted";
const QString AUDIOMODERATORMUTED = "audioModeratorMuted"; const QString AUDIOMODERATORMUTED = "audioModeratorMuted";
const QString ISMODERATOR = "isModerator"; const QString ISMODERATOR = "isModerator";
const QString HANDRAISED = "handRaised"; const QString HANDRAISED = "handRaised";
const QString VOICEACTIVITY = "voiceActivity";
const QString STREAMID = "sinkId"; // TODO update const QString STREAMID = "sinkId"; // TODO update
const QString BESTNAME = "bestName"; const QString BESTNAME = "bestName";
const QString ISLOCAL = "isLocal"; const QString ISLOCAL = "isLocal";
@ -81,6 +82,7 @@ struct ParticipantInfos
audioModeratorMuted = infos[ParticipantsInfosStrings::AUDIOMODERATORMUTED] == "true"; audioModeratorMuted = infos[ParticipantsInfosStrings::AUDIOMODERATORMUTED] == "true";
isModerator = infos[ParticipantsInfosStrings::ISMODERATOR] == "true"; isModerator = infos[ParticipantsInfosStrings::ISMODERATOR] == "true";
handRaised = infos[ParticipantsInfosStrings::HANDRAISED] == "true"; handRaised = infos[ParticipantsInfosStrings::HANDRAISED] == "true";
voiceActivity = infos[ParticipantsInfosStrings::VOICEACTIVITY] == "true";
if (infos[ParticipantsInfosStrings::STREAMID].isEmpty()) if (infos[ParticipantsInfosStrings::STREAMID].isEmpty())
sinkId = callId + uri + device; sinkId = callId + uri + device;
@ -107,6 +109,7 @@ struct ParticipantInfos
bool islocal {false}; bool islocal {false};
bool isContact {false}; bool isContact {false};
bool handRaised {false}; bool handRaised {false};
bool voiceActivity {false};
bool operator==(const ParticipantInfos& other) const bool operator==(const ParticipantInfos& other) const
{ {
@ -115,7 +118,7 @@ struct ParticipantInfos
&& audioModeratorMuted == other.audioModeratorMuted && avatar == other.avatar && audioModeratorMuted == other.audioModeratorMuted && avatar == other.avatar
&& bestName == other.bestName && isContact == other.isContact && bestName == other.bestName && isContact == other.isContact
&& islocal == other.islocal && videoMuted == other.videoMuted && islocal == other.islocal && videoMuted == other.videoMuted
&& handRaised == other.handRaised; && handRaised == other.handRaised && voiceActivity == other.voiceActivity;
} }
}; };

View file

@ -115,7 +115,9 @@ CallParticipants::addParticipant(const ParticipantInfos& participant)
std::lock_guard<std::mutex> lk(participantsMtx_); std::lock_guard<std::mutex> lk(participantsMtx_);
auto it = participants_.find(participant.sinkId); auto it = participants_.find(participant.sinkId);
if (it == participants_.end()) { if (it == participants_.end()) {
participants_.insert(std::next(participants_.begin(), idx_), participant.sinkId, participant); participants_.insert(std::next(participants_.begin(), idx_),
participant.sinkId,
participant);
added = true; added = true;
} else { } else {
if (participant == (*it)) if (participant == (*it))
@ -198,6 +200,7 @@ CallParticipants::toQJsonObject(uint index) const
ret[ParticipantsInfosStrings::ISLOCAL] = participant->islocal; ret[ParticipantsInfosStrings::ISLOCAL] = participant->islocal;
ret[ParticipantsInfosStrings::ISCONTACT] = participant->isContact; ret[ParticipantsInfosStrings::ISCONTACT] = participant->isContact;
ret[ParticipantsInfosStrings::HANDRAISED] = participant->handRaised; ret[ParticipantsInfosStrings::HANDRAISED] = participant->handRaised;
ret[ParticipantsInfosStrings::VOICEACTIVITY] = participant->voiceActivity;
ret[ParticipantsInfosStrings::CALLID] = callId_; ret[ParticipantsInfosStrings::CALLID] = callId_;
return ret; return ret;