From d81041443b70662da2f4bae2b513a0c71841f905 Mon Sep 17 00:00:00 2001 From: prlanzarin <4529051+prlanzarin@users.noreply.github.com> Date: Thu, 28 Apr 2022 16:36:22 +0000 Subject: [PATCH] fix(audio): guarantee consistency of selected output devices in AudioSettings The initial selected output device in AudioSettings could be the wrong one if the user's session had an output device ID already stored, but is joining on a new session. That would cause the remote-media tag not to be updated with the correct output device ID when it should (the service.js change) The issue is tackled by guaranteeing the output device ID is set on all ends when AudioSettings/AudioModal mounts. --- .../audio/audio-settings/component.jsx | 53 +++++++++++-------- .../imports/ui/components/audio/service.js | 4 +- 2 files changed, 33 insertions(+), 24 deletions(-) diff --git a/bigbluebutton-html5/imports/ui/components/audio/audio-settings/component.jsx b/bigbluebutton-html5/imports/ui/components/audio/audio-settings/component.jsx index 026fd4c353..24c6a5bf0c 100644 --- a/bigbluebutton-html5/imports/ui/components/audio/audio-settings/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/audio/audio-settings/component.jsx @@ -93,9 +93,12 @@ class AudioSettings extends React.Component { } componentDidMount() { - const { inputDeviceId } = this.state; + const { inputDeviceId, outputDeviceId } = this.state; + this._isMounted = true; - this.handleInputChange(inputDeviceId); + // Guarantee initial in/out devices are initialized on all ends + this.setInputDevice(inputDeviceId); + this.setOutputDevice(outputDeviceId); } componentWillUnmount() { @@ -109,6 +112,32 @@ class AudioSettings extends React.Component { } handleInputChange(deviceId) { + this.setInputDevice(deviceId); + } + + handleOutputChange(deviceId) { + this.setOutputDevice(deviceId); + } + + handleConfirmationClick() { + const { stream } = this.state; + const { + produceStreams, + handleConfirmation, + } = this.props; + + // Stream generation disabled or there isn't any stream: just run the provided callback + if (!produceStreams || !stream) return handleConfirmation(); + + // Stream generation enabled and there is a valid input stream => call + // the confirmation callback with the input stream as arg so it can be used + // in upstream components. The rationale is no surplus gUM calls. + // We're cloning it because the original will be cleaned up on unmount here. + const clonedStream = stream.clone(); + return handleConfirmation(clonedStream); + } + + setInputDevice(deviceId) { const { handleGUMFailure, changeInputDevice, @@ -148,7 +177,7 @@ class AudioSettings extends React.Component { } } - handleOutputChange(deviceId) { + setOutputDevice(deviceId) { const { changeOutputDevice, withEcho, @@ -163,24 +192,6 @@ class AudioSettings extends React.Component { }); } - handleConfirmationClick() { - const { stream } = this.state; - const { - produceStreams, - handleConfirmation, - } = this.props; - - // Stream generation disabled or there isn't any stream: just run the provided callback - if (!produceStreams || !stream) return handleConfirmation(); - - // Stream generation enabled and there is a valid input stream => call - // the confirmation callback with the input stream as arg so it can be used - // in upstream components. The rationale is no surplus gUM calls. - // We're cloning it because the original will be cleaned up on unmount here. - const clonedStream = stream.clone(); - return handleConfirmation(clonedStream); - } - generateInputStream(inputDeviceId) { const { stream } = this.state; diff --git a/bigbluebutton-html5/imports/ui/components/audio/service.js b/bigbluebutton-html5/imports/ui/components/audio/service.js index 868b95ae1e..0aac8d2fdd 100755 --- a/bigbluebutton-html5/imports/ui/components/audio/service.js +++ b/bigbluebutton-html5/imports/ui/components/audio/service.js @@ -112,9 +112,7 @@ export default { changeInputStream: (newInputStream) => { AudioManager.inputStream = newInputStream; }, liveChangeInputDevice: (inputDeviceId) => AudioManager.liveChangeInputDevice(inputDeviceId), changeOutputDevice: (outputDeviceId, isLive) => { - if (AudioManager.outputDeviceId !== outputDeviceId) { - AudioManager.changeOutputDevice(outputDeviceId, isLive); - } + AudioManager.changeOutputDevice(outputDeviceId, isLive); }, isConnected: () => AudioManager.isConnected, isTalking: () => AudioManager.isTalking,