diff --git a/conference.js b/conference.js index 918ea35be..7decf5221 100644 --- a/conference.js +++ b/conference.js @@ -923,6 +923,35 @@ export default { : isVideoMutedByUser(APP.store); }, + /** + * Verify if there is an ongoing system audio sharing session and apply to the provided track + * as a AudioMixer effect. + * + * @param {*} localAudioTrack - track to which system audio track will be applied as an effect, most likely + * microphone local audio track. + */ + async _maybeApplyAudioMixerEffect(localAudioTrack) { + + // At the time of writing this comment there were two separate flows for toggling screen-sharing + // and system audio sharing, the first is the legacy method using the functionality from conference.js + // the second is used when both sendMultipleVideoStreams and sourceNameSignaling flags are set to true. + // The second flow uses functionality from base/conference/middleware.web.js. + // We check if system audio sharing was done using the first flow by verifying this._desktopAudioStream and + // for the second by checking 'features/screen-share' state. + const { desktopAudioTrack } = APP.store.getState()['features/screen-share']; + const currentDesktopAudioTrack = this._desktopAudioStream || desktopAudioTrack; + + // If system audio is already being sent, mix it with the provided audio track. + if (currentDesktopAudioTrack) { + // In case system audio sharing was done in the absence of an initial mic audio track, there is no + // AudioMixerEffect so we have to remove system audio track from the room before setting it as an effect. + await room.replaceTrack(currentDesktopAudioTrack, null); + this._mixerEffect = new AudioMixerEffect(currentDesktopAudioTrack); + logger.debug('Mixing new audio track with existing screen audio track.'); + await localAudioTrack.setEffect(this._mixerEffect); + } + }, + /** * Simulates toolbar button click for audio mute. Used by shortcuts and API. * @param {boolean} mute true for mute and false for unmute. @@ -976,7 +1005,11 @@ export default { // Rollback the audio muted status by using null track return null; }) - .then(audioTrack => this.useAudioStream(audioTrack)); + .then(async audioTrack => { + await this._maybeApplyAudioMixerEffect(audioTrack); + + this.useAudioStream(audioTrack); + }); } else { muteLocalAudio(mute); } @@ -2572,13 +2605,7 @@ export default { return stream; }) .then(async stream => { - // In case screen sharing audio is also shared we mix it with new input stream. The old _mixerEffect - // will be cleaned up when the existing track is replaced. - if (this._mixerEffect) { - this._mixerEffect = new AudioMixerEffect(this._desktopAudioStream); - - await stream.setEffect(this._mixerEffect); - } + await this._maybeApplyAudioMixerEffect(stream); return this.useAudioStream(stream); })