fix(prejoin): Replace the stored audio/video tracks when device list changes

When on prejoin screen, if the device list changes (devices are added or removed),
the newly created tracks do not properly replace the old ones, resulting in
errors after joining the meeting and trying to change the devices.
This change fixes the problem.
This commit is contained in:
Vlad Piersec 2020-06-26 11:54:12 +03:00 committed by Zoltan Bettenbuk
parent 28632752ba
commit 2b5787163e
2 changed files with 53 additions and 12 deletions

View File

@ -95,6 +95,8 @@ import {
createLocalPresenterTrack, createLocalPresenterTrack,
createLocalTracksF, createLocalTracksF,
destroyLocalTracks, destroyLocalTracks,
getLocalJitsiAudioTrack,
getLocalJitsiVideoTrack,
isLocalVideoTrackMuted, isLocalVideoTrackMuted,
isLocalTrackMuted, isLocalTrackMuted,
isUserInteractionRequiredForUnmute, isUserInteractionRequiredForUnmute,
@ -118,7 +120,8 @@ import { mediaPermissionPromptVisibilityChanged } from './react/features/overlay
import { suspendDetected } from './react/features/power-monitor'; import { suspendDetected } from './react/features/power-monitor';
import { import {
initPrejoin, initPrejoin,
isPrejoinPageEnabled isPrejoinPageEnabled,
isPrejoinPageVisible
} from './react/features/prejoin'; } from './react/features/prejoin';
import { createRnnoiseProcessorPromise } from './react/features/rnnoise'; import { createRnnoiseProcessorPromise } from './react/features/rnnoise';
import { toggleScreenshotCaptureEffect } from './react/features/screenshot-capture'; import { toggleScreenshotCaptureEffect } from './react/features/screenshot-capture';
@ -1400,19 +1403,32 @@ export default {
/** /**
* Start using provided video stream. * Start using provided video stream.
* Stops previous video stream. * Stops previous video stream.
* @param {JitsiLocalTrack} [stream] new stream to use or null * @param {JitsiLocalTrack} newTrack - new track to use or null
* @returns {Promise} * @returns {Promise}
*/ */
useVideoStream(newStream) { useVideoStream(newTrack) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
_replaceLocalVideoTrackQueue.enqueue(onFinish => { _replaceLocalVideoTrackQueue.enqueue(onFinish => {
const state = APP.store.getState();
// When the prejoin page is displayed localVideo is not set
// so just replace the video track from the store with the new one.
if (isPrejoinPageVisible(state)) {
const oldTrack = getLocalJitsiVideoTrack(state);
return APP.store.dispatch(replaceLocalTrack(oldTrack, newTrack))
.then(resolve)
.catch(reject)
.then(onFinish);
}
APP.store.dispatch( APP.store.dispatch(
replaceLocalTrack(this.localVideo, newStream, room)) replaceLocalTrack(this.localVideo, newTrack, room))
.then(() => { .then(() => {
this.localVideo = newStream; this.localVideo = newTrack;
this._setSharingScreen(newStream); this._setSharingScreen(newTrack);
if (newStream) { if (newTrack) {
APP.UI.addLocalVideoStream(newStream); APP.UI.addLocalVideoStream(newTrack);
} }
this.setVideoMuteStatus(this.isLocalVideoMuted()); this.setVideoMuteStatus(this.isLocalVideoMuted());
}) })
@ -1453,16 +1469,29 @@ export default {
/** /**
* Start using provided audio stream. * Start using provided audio stream.
* Stops previous audio stream. * Stops previous audio stream.
* @param {JitsiLocalTrack} [stream] new stream to use or null * @param {JitsiLocalTrack} newTrack - new track to use or null
* @returns {Promise} * @returns {Promise}
*/ */
useAudioStream(newStream) { useAudioStream(newTrack) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
_replaceLocalAudioTrackQueue.enqueue(onFinish => { _replaceLocalAudioTrackQueue.enqueue(onFinish => {
const state = APP.store.getState();
// When the prejoin page is displayed localAudio is not set
// so just replace the audio track from the store with the new one.
if (isPrejoinPageVisible(state)) {
const oldTrack = getLocalJitsiAudioTrack(state);
return APP.store.dispatch(replaceLocalTrack(oldTrack, newTrack))
.then(resolve)
.catch(reject)
.then(onFinish);
}
APP.store.dispatch( APP.store.dispatch(
replaceLocalTrack(this.localAudio, newStream, room)) replaceLocalTrack(this.localAudio, newTrack, room))
.then(() => { .then(() => {
this.localAudio = newStream; this.localAudio = newTrack;
this.setAudioMuteStatus(this.isLocalAudioMuted()); this.setAudioMuteStatus(this.isLocalAudioMuted());
}) })
.then(resolve) .then(resolve)

View File

@ -210,6 +210,18 @@ export function getLocalJitsiVideoTrack(state) {
return track?.jitsiTrack; return track?.jitsiTrack;
} }
/**
* Returns the stored local audio track.
*
* @param {Object} state - The redux state.
* @returns {Object}
*/
export function getLocalJitsiAudioTrack(state) {
const track = getLocalAudioTrack(state['features/base/tracks']);
return track?.jitsiTrack;
}
/** /**
* Returns track of specified media type for specified participant id. * Returns track of specified media type for specified participant id.
* *