Merge pull request #21167 from prlanzarin/u30/fix/audio-unmute-audiosettings-close

fix(audio): ensure initial local mute state when muteOnStart=true
This commit is contained in:
Paulo Lanzarin 2024-09-13 09:58:42 -03:00 committed by GitHub
commit 8b3ea9a1ee
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -58,7 +58,7 @@ class AudioManager {
};
this.defineProperties({
isMuted: makeVar(false),
isMuted: makeVar(true),
isConnected: makeVar(false),
isConnecting: makeVar(false),
isHangingUp: makeVar(false),
@ -67,7 +67,6 @@ class AudioManager {
isTalking: makeVar(false),
isWaitingPermissions: makeVar(false),
error: makeVar(null),
muteHandle: makeVar(null),
autoplayBlocked: makeVar(false),
isReconnecting: makeVar(false),
bypassGUM: makeVar(false),
@ -89,6 +88,7 @@ class AudioManager {
};
this.BREAKOUT_AUDIO_TRANSFER_STATES = BREAKOUT_AUDIO_TRANSFER_STATES;
this._voiceActivityObserver = null;
window.addEventListener('StopAudioTracks', () => this.forceExitAudio());
}
@ -192,17 +192,37 @@ class AudioManager {
&& this.fullAudioBridge?.supportsTransparentListenOnly();
}
async init(userData, audioEventHandler) {
observeVoiceActivity() {
// Observe voice activity changes to update any relevant *local* states
// (see onVoiceUserChanges)
if (!this._voiceActivityObserver) {
const subHash = stringToHash(JSON.stringify({
subscription: VOICE_ACTIVITY,
}));
this._voiceActivityObserver = GrahqlSubscriptionStore.makeSubscription(VOICE_ACTIVITY);
window.addEventListener('graphqlSubscription', (e) => {
const { subscriptionHash, response } = e.detail;
if (subscriptionHash === subHash) {
if (response) {
const { data } = response;
const voiceUser = data.user_voice_activity_stream.find((v) => v.userId === Auth.userID);
this.onVoiceUserChanges(voiceUser);
}
}
});
}
}
init(userData, audioEventHandler) {
this.userData = userData;
this.inputDeviceId = getStoredAudioInputDeviceId() || DEFAULT_INPUT_DEVICE_ID;
this.outputDeviceId = getCurrentAudioSinkId();
this._applyCachedOutputDeviceId();
this._trackPermissionStatus();
this.loadBridges(userData);
this.userData = userData;
this.initialized = true;
this.audioEventHandler = audioEventHandler;
await this.loadBridges(userData);
this.transparentListenOnlySupported = this.supportsTransparentListenOnly();
this.audioEventHandler = audioEventHandler;
this.initialized = true;
}
/**
@ -212,7 +232,7 @@ class AudioManager {
* @param {Object} userData The Object representing user data to be passed to
* the bridge.
*/
async loadBridges(userData) {
loadBridges(userData) {
let FullAudioBridge = SIPBridge;
let ListenOnlyBridge = SFUAudioBridge;
@ -448,8 +468,19 @@ class AudioManager {
onAudioJoining() {
this.isConnecting = true;
this.isMuted = false;
this.isMuted = true;
this.error = false;
this.observeVoiceActivity();
// Ensure the local mute state (this.isMuted) is aligned with the initial
// placeholder value before joining audio.
// Currently, the server sets the placeholder mute state to *true*, and this
// is only communicated via observeVoiceActivity's subscription if the initial
// state differs from the placeholder or when the state changes.
// Refer to user_voice_activity DB schema for details.
// tl;dr: without enforcing the initial mute state here, the client won't be
// locally muted if the audio channel starts muted (e.g., dialplan-level
// muteOnStart).
this.setSenderTrackEnabled(!this.isMuted);
return Promise.resolve();
}
@ -501,24 +532,6 @@ class AudioManager {
this.isConnecting = false;
const STATS = window.meetingClientSettings.public.stats;
// listen to the VoiceUsers changes and update the flag
if (!this.muteHandle) {
const subHash = stringToHash(JSON.stringify({
subscription: VOICE_ACTIVITY,
}));
this.muteHandle = GrahqlSubscriptionStore.makeSubscription(VOICE_ACTIVITY);
window.addEventListener('graphqlSubscription', (e) => {
const { subscriptionHash, response } = e.detail;
if (subscriptionHash === subHash) {
if (response) {
const { data } = response;
const voiceUser = data.user_voice_activity_stream.find((v) => v.userId === Auth.userID);
this.onVoiceUserChanges(voiceUser);
}
}
});
}
const secondsToActivateAudio = (new Date() - this.audioJoinStartTime) / 1000;
if (!this.logAudioJoinTime) {