Skip to content

Commit

Permalink
fix: moderated unmute when client is remotely muted
Browse files Browse the repository at this point in the history
  • Loading branch information
marcin-bazyl committed Nov 20, 2024
1 parent aaa7b13 commit bab60b0
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 33 deletions.
3 changes: 2 additions & 1 deletion packages/@webex/plugin-meetings/src/locus-info/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1406,7 +1406,7 @@ export default class LocusInfo extends EventsScope {
}
);
}
if (parsedSelves.updates.isMutedByOthersChanged) {
if (parsedSelves.updates.isMutedByOthersChanged.changed) {
this.emitScoped(
{
file: 'locus-info',
Expand All @@ -1416,6 +1416,7 @@ export default class LocusInfo extends EventsScope {
{
muted: parsedSelves.current.remoteMuted,
unmuteAllowed: parsedSelves.current.unmuteAllowed,
isModifiedBySelf: parsedSelves.updates.isMutedByOthersChanged.isModifiedBySelf,
}
);
}
Expand Down
26 changes: 14 additions & 12 deletions packages/@webex/plugin-meetings/src/locus-info/selfUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -419,25 +419,27 @@ SelfUtils.mutedByOthersChanged = (oldSelf, changedSelf) => {
throw new ParameterError('New self must be defined to determine if self was muted by others.');
}

const isModifiedBySelf = changedSelf.selfIdentity === changedSelf.modifiedBy;

if (!oldSelf || oldSelf.remoteMuted === null) {
if (changedSelf.remoteMuted) {
return true; // this happens when mute on-entry is enabled
return {changed: false, isModifiedBySelf}; // this happens when mute on-entry is enabled
}

// we don't want to be sending the 'meeting:self:unmutedByOthers' notification on meeting join
return false;
}

// there is no need to trigger user update if no one muted user
if (changedSelf.selfIdentity === changedSelf.modifiedBy) {
return false;
return {changed: false, isModifiedBySelf};
}

return (
changedSelf.remoteMuted !== null &&
(oldSelf.remoteMuted !== changedSelf.remoteMuted ||
(changedSelf.remoteMuted && oldSelf.unmuteAllowed !== changedSelf.unmuteAllowed))
console.log(
`marcin: mutedByOthersChanged: old.remoteMuted=${oldSelf.remoteMuted} new.remoteMuted=${changedSelf.remoteMuted} selfId=${changedSelf.selfIdentity} modifiedBy=${changedSelf.modifiedBy}`
);

return {
changed:
changedSelf.remoteMuted !== null &&
(oldSelf.remoteMuted !== changedSelf.remoteMuted ||
(changedSelf.remoteMuted && oldSelf.unmuteAllowed !== changedSelf.unmuteAllowed)),
isModifiedBySelf,
};
};

SelfUtils.localAudioUnmuteRequestedByServer = (oldSelf: any = {}, changedSelf: any) => {
Expand Down
48 changes: 28 additions & 20 deletions packages/@webex/plugin-meetings/src/meeting/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3144,26 +3144,34 @@ export default class Meeting extends StatelessWebexPlugin {

this.locusInfo.on(LOCUSINFO.EVENTS.SELF_REMOTE_MUTE_STATUS_UPDATED, (payload) => {
if (payload) {
if (this.audio) {
this.audio.handleServerRemoteMuteUpdate(this, payload.muted, payload.unmuteAllowed);
}
// with "mute on entry" server will send us remote mute even if we don't have media configured,
// so if being muted by others, always send the notification,
// but if being unmuted, only send it if we are also locally unmuted
if (payload.muted || !this.audio?.isMuted()) {
Trigger.trigger(
this,
{
file: 'meeting/index',
function: 'setUpLocusInfoSelfListener',
},
payload.muted
? EVENT_TRIGGERS.MEETING_SELF_MUTED_BY_OTHERS
: EVENT_TRIGGERS.MEETING_SELF_UNMUTED_BY_OTHERS,
{
payload,
}
);
const ignore = this.audio
? this.audio.shouldIgnoreRemoteMuteUpdate(payload.muted, payload.isModifiedBySelf)
: false;

if (!ignore) {
if (this.audio) {
this.audio.handleServerRemoteMuteUpdate(this, payload.muted, payload.unmuteAllowed);
}
// with "mute on entry" server will send us remote mute even if we don't have media configured,
// so if being muted by others, always send the notification,
// but if being unmuted, only send it if we are also locally unmuted
if (payload.muted || !this.audio?.isMuted()) {
Trigger.trigger(
this,
{
file: 'meeting/index',
function: 'setUpLocusInfoSelfListener',
},
payload.muted
? EVENT_TRIGGERS.MEETING_SELF_MUTED_BY_OTHERS
: EVENT_TRIGGERS.MEETING_SELF_UNMUTED_BY_OTHERS,
{
payload,
}
);
}
} else {
console.log(`marcin: ignoring remote mute update payload.muted=${payload.muted}`);
}
}
});
Expand Down
28 changes: 28 additions & 0 deletions packages/@webex/plugin-meetings/src/meeting/muteState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export class MuteState {
};
server: {localMute: boolean; remoteMute: boolean; unmuteAllowed: boolean};
syncToServerInProgress: boolean;
isRemoteUnmutePendingLocusDtoUpdate: boolean; // true if we've sent a remote unmute request to Locus and haven't received a Locus DTO confirming it happened, yet
};

type: any;
Expand Down Expand Up @@ -62,6 +63,7 @@ export class MuteState {
unmuteAllowed: type === AUDIO ? meeting.unmuteAllowed : meeting.unmuteVideoAllowed ?? true,
},
syncToServerInProgress: false,
isRemoteUnmutePendingLocusDtoUpdate: false,
};
}

Expand Down Expand Up @@ -327,6 +329,13 @@ export class MuteState {
`Meeting:muteState#sendRemoteMuteRequestToServer --> ${this.type}: sending remote mute:${remoteMute} to server`
);

this.state.isRemoteUnmutePendingLocusDtoUpdate = true;

setTimeout(() => {
console.log('marcin: resetting isRemoteUnmutePendingLocusDtoUpdate after timeout');
this.state.isRemoteUnmutePendingLocusDtoUpdate = false;
}, 10 * 1000);

return meeting.members
.muteMember(meeting.members.selfId, remoteMute, this.type === AUDIO)
.then(() => {
Expand All @@ -337,6 +346,8 @@ export class MuteState {
this.state.server.remoteMute = remoteMute;
})
.catch((remoteUpdateError) => {
this.state.isRemoteUnmutePendingLocusDtoUpdate = false;

LoggerProxy.logger.warn(
`Meeting:muteState#sendRemoteMuteRequestToServer --> ${this.type}: failed to apply remote mute ${remoteMute} to server: ${remoteUpdateError}`
);
Expand All @@ -359,6 +370,23 @@ export class MuteState {
}
}

public shouldIgnoreRemoteMuteUpdate(remoteMute: boolean, isModifiedBySelf: boolean) {
console.log(
`marcin: shouldIgnoreRemoteMuteUpdate: flag=${this.state.isRemoteUnmutePendingLocusDtoUpdate} remoteMute=${remoteMute}, isModifiedBySelf=${isModifiedBySelf}`
);
if (this.state.isRemoteUnmutePendingLocusDtoUpdate && isModifiedBySelf && !remoteMute) {
console.log('marcin: FIX: ignoring remote mute update');

this.state.isRemoteUnmutePendingLocusDtoUpdate = false;

return true;
}

console.log('marcin: FIX: NOT ignoring remote mute update');

return false;
}

/**
* This method should be called whenever the server remote mute state is changed
*
Expand Down

0 comments on commit bab60b0

Please sign in to comment.