fix(base/tracks): local track for video already exists

The _setMuted method in a corner case was making an attempt to create
second video track, because it was not taking pending tracks into
account.
This commit is contained in:
paweldomas 2018-04-06 15:04:25 -05:00 committed by Lyubo Marinov
parent 157800c494
commit c03e66954d
3 changed files with 48 additions and 15 deletions

View File

@ -20,7 +20,7 @@ import {
TRACK_UPDATED,
TRACK_WILL_CREATE
} from './actionTypes';
import { createLocalTracksF } from './functions';
import { createLocalTracksF, getLocalTrack, getLocalTracks } from './functions';
const logger = require('jitsi-meet-logger').getLogger(__filename);
@ -45,8 +45,9 @@ export function createDesiredLocalTracks(...desiredTypes) {
}
const availableTypes
= state['features/base/tracks']
.filter(t => t.local)
= getLocalTracks(
state['features/base/tracks'],
/* includePending */ true)
.map(t => t.mediaType);
// We need to create the desired tracks which are not already available.
@ -85,8 +86,10 @@ export function createLocalTracksA(options = {}) {
// to implement them) and the right thing to do is to ask for each
// device separately.
for (const device of devices) {
if (getState()['features/base/tracks']
.find(t => t.local && t.mediaType === device)) {
if (getLocalTrack(
getState()['features/base/tracks'],
device,
/* includePending */ true)) {
throw new Error(`Local track for ${device} already exists`);
}

View File

@ -106,21 +106,32 @@ export function getLocalAudioTrack(tracks) {
*
* @param {Track[]} tracks - List of all tracks.
* @param {MEDIA_TYPE} mediaType - Media type.
* @param {boolean} [includePending] - Indicates whether a local track is to be
* returned if it is still pending. A local track is pending if
* {@code getUserMedia} is still executing to create it and, consequently, its
* {@code jitsiTrack} property is {@code undefined}. By default a pending local
* track is not returned.
* @returns {(Track|undefined)}
*/
export function getLocalTrack(tracks, mediaType) {
return getLocalTracks(tracks).find(t => t.mediaType === mediaType);
export function getLocalTrack(tracks, mediaType, includePending = false) {
return (
getLocalTracks(tracks, includePending)
.find(t => t.mediaType === mediaType));
}
/**
* Returns an array containing the local tracks with a (valid)
* Returns an array containing the local tracks with or without a (valid)
* {@code JitsiTrack}.
*
* @param {Track[]} tracks - An array containing all local tracks.
* @param {boolean} [includePending] - Indicates whether a local track is to be
* returned if it is still pending. A local track is pending if
* {@code getUserMedia} is still executing to create it and, consequently, its
* {@code jitsiTrack} property is {@code undefined}. By default a pending local
* track is not returned.
* @returns {Track[]}
*/
export function getLocalTracks(tracks) {
export function getLocalTracks(tracks, includePending = false) {
// XXX A local track is considered ready only once it has its `jitsiTrack`
// property set by the `TRACK_ADDED` action. Until then there is a stub
// added just before the `getUserMedia` call with a cancellable
@ -128,7 +139,7 @@ export function getLocalTracks(tracks) {
// has not yet been added to the redux store. Once GUM is cancelled, it will
// never make it to the store nor there will be any
// `TRACK_ADDED`/`TRACK_REMOVED` actions dispatched for it.
return tracks.filter(t => t.local && t.jitsiTrack);
return tracks.filter(t => t.local && (t.jitsiTrack || includePending));
}
/**

View File

@ -147,12 +147,24 @@ MiddlewareRegistry.register(store => next => action => {
* with the specified {@code mediaType} is to be retrieved.
* @param {MEDIA_TYPE} mediaType - The {@code MEDIA_TYPE} of the local track to
* be retrieved from the specified {@code store}.
* @param {boolean} [includePending] - Indicates whether a local track is to be
* returned if it is still pending. A local track is pending if
* {@code getUserMedia} is still executing to create it and, consequently, its
* {@code jitsiTrack} property is {@code undefined}. By default a pending local
* track is not returned.
* @private
* @returns {Track} The local {@code Track} associated with the specified
* {@code mediaType} in the specified {@code store}.
*/
function _getLocalTrack({ getState }, mediaType: MEDIA_TYPE) {
return getLocalTrack(getState()['features/base/tracks'], mediaType);
function _getLocalTrack(
{ getState }: { getState: Function },
mediaType: MEDIA_TYPE,
includePending: boolean = false) {
return (
getLocalTrack(
getState()['features/base/tracks'],
mediaType,
includePending));
}
/**
@ -167,10 +179,17 @@ function _getLocalTrack({ getState }, mediaType: MEDIA_TYPE) {
* @returns {void}
*/
function _setMuted(store, { ensureTrack, muted }, mediaType: MEDIA_TYPE) {
const localTrack = _getLocalTrack(store, mediaType);
const localTrack
= _getLocalTrack(store, mediaType, /* includePending */ true);
if (localTrack) {
setTrackMuted(localTrack.jitsiTrack, muted);
// The `jitsiTrack` property will have a value only for a localTrack for
// which `getUserMedia` has already completed. If there's no
// `jitsiTrack`, then the `muted` state will be applied once the
// `jitsiTrack` is created.
const { jitsiTrack } = localTrack;
jitsiTrack && setTrackMuted(jitsiTrack, muted);
} else if (!muted && ensureTrack && typeof APP === 'undefined') {
// FIXME: This only runs on mobile now because web has its own way of
// creating local tracks. Adjust the check once they are unified.