diff --git a/src/utils/media/pipeline/TrackEnabler.js b/src/utils/media/pipeline/TrackEnabler.js
index 6b7dca755c3..552903547c1 100644
--- a/src/utils/media/pipeline/TrackEnabler.js
+++ b/src/utils/media/pipeline/TrackEnabler.js
@@ -65,11 +65,15 @@ export default class TrackEnabler extends TrackSinkSource {
}
_handleInputTrack(trackId, track) {
- this._setOutputTrack('default', track)
-
+ // Ignore the enabled state of the input and force the desired state by
+ // the node. The state must be forced before setting the output track to
+ // ensure that it will have the desired state from the start (and thus
+ // "_setOutputTrackEnabled" can not be used).
if (track && track.enabled !== this._enabled) {
- this._setOutputTrackEnabled('default', this._enabled)
+ track.enabled = this._enabled
}
+
+ this._setOutputTrack('default', track)
}
_handleInputTrackEnabled(trackId, enabled) {
diff --git a/src/utils/media/pipeline/TrackEnabler.spec.js b/src/utils/media/pipeline/TrackEnabler.spec.js
new file mode 100644
index 00000000000..7cafe2a9aa7
--- /dev/null
+++ b/src/utils/media/pipeline/TrackEnabler.spec.js
@@ -0,0 +1,443 @@
+/**
+ *
+ * @copyright Copyright (c) 2022, Daniel Calviño Sánchez (danxuliu@gmail.com)
+ *
+ * @license AGPL-3.0-or-later
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+import TrackEnabler from './TrackEnabler'
+
+/**
+ * Helper function to create MediaStreamTrack mocks with just the attributes and
+ * methods used by TrackEnabler.
+ *
+ * @param {string} id the ID of the track
+ */
+function newMediaStreamTrackMock(id) {
+ /**
+ * MediaStreamTrackMock constructor.
+ */
+ function MediaStreamTrackMock() {
+ this.id = id
+ this.enabled = true
+ // "ended" event is not being tested, so there is no need to add even a
+ // stub for the event listener methods.
+ this.addEventListener = jest.fn()
+ this.removeEventListener = jest.fn()
+ }
+ return new MediaStreamTrackMock()
+}
+
+describe('TrackToStream', () => {
+ let trackEnabler
+ let outputTrackSetHandler
+ let outputTrackEnabledHandler
+ let expectedTrackEnabledStateInOutputTrackSetEvent
+
+ beforeEach(() => {
+ trackEnabler = new TrackEnabler()
+
+ expectedTrackEnabledStateInOutputTrackSetEvent = undefined
+
+ outputTrackSetHandler = jest.fn((trackEnabler, trackId, track) => {
+ if (expectedTrackEnabledStateInOutputTrackSetEvent !== undefined) {
+ expect(track.enabled).toBe(expectedTrackEnabledStateInOutputTrackSetEvent)
+ }
+ })
+ outputTrackEnabledHandler = jest.fn()
+
+ trackEnabler.on('outputTrackSet', outputTrackSetHandler)
+ trackEnabler.on('outputTrackEnabled', outputTrackEnabledHandler)
+ })
+
+ test('is enabled by default', () => {
+ expect(trackEnabler.isEnabled()).toBe(true)
+ })
+
+ describe('enable/disable node', () => {
+ test('does nothing if disabled when there is no input track', () => {
+ trackEnabler.setEnabled(false)
+
+ expect(trackEnabler.isEnabled()).toBe(false)
+ expect(outputTrackSetHandler).toHaveBeenCalledTimes(0)
+ expect(outputTrackEnabledHandler).toHaveBeenCalledTimes(0)
+ })
+
+ test('does nothing if enabled when there is no input track', () => {
+ trackEnabler.setEnabled(false)
+ trackEnabler.setEnabled(true)
+
+ expect(trackEnabler.isEnabled()).toBe(true)
+ expect(outputTrackSetHandler).toHaveBeenCalledTimes(0)
+ expect(outputTrackEnabledHandler).toHaveBeenCalledTimes(0)
+ })
+ })
+
+ describe('set input track', () => {
+ test('sets enabled input track as its output track', () => {
+ const inputTrack = newMediaStreamTrackMock('input')
+
+ expectedTrackEnabledStateInOutputTrackSetEvent = true
+
+ trackEnabler._setInputTrack('default', inputTrack)
+
+ expect(outputTrackSetHandler).toHaveBeenCalledTimes(1)
+ expect(outputTrackSetHandler).toHaveBeenCalledWith(trackEnabler, 'default', inputTrack)
+ expect(outputTrackEnabledHandler).toHaveBeenCalledTimes(0)
+ expect(inputTrack.enabled).toBe(true)
+ })
+
+ test('sets disabled input track as its output track', () => {
+ const inputTrack = newMediaStreamTrackMock('input')
+
+ trackEnabler.setEnabled(false)
+
+ expectedTrackEnabledStateInOutputTrackSetEvent = false
+
+ inputTrack.enabled = false
+ trackEnabler._setInputTrack('default', inputTrack)
+
+ expect(outputTrackSetHandler).toHaveBeenCalledTimes(1)
+ expect(outputTrackSetHandler).toHaveBeenCalledWith(trackEnabler, 'default', inputTrack)
+ expect(outputTrackEnabledHandler).toHaveBeenCalledTimes(0)
+ expect(inputTrack.enabled).toBe(false)
+ })
+
+ test('sets disabled input track as its output track enabling it when node is enabled', () => {
+ const inputTrack = newMediaStreamTrackMock('input')
+
+ expectedTrackEnabledStateInOutputTrackSetEvent = true
+
+ inputTrack.enabled = false
+ trackEnabler._setInputTrack('default', inputTrack)
+
+ expect(outputTrackSetHandler).toHaveBeenCalledTimes(1)
+ expect(outputTrackSetHandler).toHaveBeenCalledWith(trackEnabler, 'default', inputTrack)
+ expect(outputTrackEnabledHandler).toHaveBeenCalledTimes(0)
+ expect(inputTrack.enabled).toBe(true)
+ })
+
+ test('sets enabled input track as its output track disabling it when node is disabled', () => {
+ const inputTrack = newMediaStreamTrackMock('input')
+
+ trackEnabler.setEnabled(false)
+
+ expectedTrackEnabledStateInOutputTrackSetEvent = false
+
+ inputTrack.enabled = true
+ trackEnabler._setInputTrack('default', inputTrack)
+
+ expect(outputTrackSetHandler).toHaveBeenCalledTimes(1)
+ expect(outputTrackSetHandler).toHaveBeenCalledWith(trackEnabler, 'default', inputTrack)
+ expect(outputTrackEnabledHandler).toHaveBeenCalledTimes(0)
+ expect(inputTrack.enabled).toBe(false)
+ })
+ })
+
+ describe('enable/disable node after setting input track', () => {
+ test('enables input track when node is enabled', () => {
+ const inputTrack = newMediaStreamTrackMock('input')
+
+ trackEnabler.setEnabled(false)
+
+ inputTrack.enabled = false
+ trackEnabler._setInputTrack('default', inputTrack)
+
+ outputTrackSetHandler.mockClear()
+ outputTrackEnabledHandler.mockClear()
+
+ trackEnabler.setEnabled(true)
+
+ expect(outputTrackSetHandler).toHaveBeenCalledTimes(0)
+ expect(outputTrackEnabledHandler).toHaveBeenCalledTimes(1)
+ expect(outputTrackEnabledHandler).toHaveBeenCalledWith(trackEnabler, 'default', true)
+ expect(inputTrack.enabled).toBe(true)
+ })
+
+ test('disables input track when node is disabled', () => {
+ const inputTrack = newMediaStreamTrackMock('input')
+
+ trackEnabler._setInputTrack('default', inputTrack)
+
+ outputTrackSetHandler.mockClear()
+ outputTrackEnabledHandler.mockClear()
+
+ trackEnabler.setEnabled(false)
+
+ expect(outputTrackSetHandler).toHaveBeenCalledTimes(0)
+ expect(outputTrackEnabledHandler).toHaveBeenCalledTimes(1)
+ expect(outputTrackEnabledHandler).toHaveBeenCalledWith(trackEnabler, 'default', false)
+ expect(inputTrack.enabled).toBe(false)
+ })
+ })
+
+ describe('enable/disable input track', () => {
+ test('enables input track again if input track is disabled when node is enabled', () => {
+ const inputTrack = newMediaStreamTrackMock('input')
+
+ trackEnabler._setInputTrack('default', inputTrack)
+
+ outputTrackSetHandler.mockClear()
+ outputTrackEnabledHandler.mockClear()
+
+ inputTrack.enabled = false
+ trackEnabler._setInputTrackEnabled('default', false)
+
+ expect(outputTrackSetHandler).toHaveBeenCalledTimes(0)
+ expect(outputTrackEnabledHandler).toHaveBeenCalledTimes(1)
+ expect(outputTrackEnabledHandler).toHaveBeenCalledWith(trackEnabler, 'default', true)
+ expect(inputTrack.enabled).toBe(true)
+ })
+
+ test('disables input track again if input track is enabled when node is disabled', () => {
+ const inputTrack = newMediaStreamTrackMock('input')
+
+ trackEnabler.setEnabled(false)
+
+ inputTrack.enabled = false
+ trackEnabler._setInputTrack('default', inputTrack)
+
+ outputTrackSetHandler.mockClear()
+ outputTrackEnabledHandler.mockClear()
+
+ inputTrack.enabled = true
+ trackEnabler._setInputTrackEnabled('default', true)
+
+ expect(outputTrackSetHandler).toHaveBeenCalledTimes(0)
+ expect(outputTrackEnabledHandler).toHaveBeenCalledTimes(1)
+ expect(outputTrackEnabledHandler).toHaveBeenCalledWith(trackEnabler, 'default', false)
+ expect(inputTrack.enabled).toBe(false)
+ })
+
+ test('does nothing if input track is enabled again when node is enabled', () => {
+ const inputTrack = newMediaStreamTrackMock('input')
+
+ trackEnabler._setInputTrack('default', inputTrack)
+
+ outputTrackSetHandler.mockClear()
+ outputTrackEnabledHandler.mockClear()
+
+ trackEnabler._setInputTrackEnabled('default', true)
+
+ expect(outputTrackSetHandler).toHaveBeenCalledTimes(0)
+ expect(outputTrackEnabledHandler).toHaveBeenCalledTimes(0)
+ expect(inputTrack.enabled).toBe(true)
+ })
+
+ test('does nothing if input track is disabled again when node is disabled', () => {
+ const inputTrack = newMediaStreamTrackMock('input')
+
+ trackEnabler.setEnabled(false)
+
+ inputTrack.enabled = false
+ trackEnabler._setInputTrack('default', inputTrack)
+
+ outputTrackSetHandler.mockClear()
+ outputTrackEnabledHandler.mockClear()
+
+ trackEnabler._setInputTrackEnabled('default', false)
+
+ expect(outputTrackSetHandler).toHaveBeenCalledTimes(0)
+ expect(outputTrackEnabledHandler).toHaveBeenCalledTimes(0)
+ expect(inputTrack.enabled).toBe(false)
+ })
+ })
+
+ describe('remove input track', () => {
+ test('removes output track when removing input track', () => {
+ const inputTrack = newMediaStreamTrackMock('input')
+
+ trackEnabler._setInputTrack('default', inputTrack)
+
+ outputTrackSetHandler.mockClear()
+ outputTrackEnabledHandler.mockClear()
+
+ trackEnabler._setInputTrack('default', null)
+
+ expect(outputTrackSetHandler).toHaveBeenCalledTimes(1)
+ expect(outputTrackSetHandler).toHaveBeenCalledWith(trackEnabler, 'default', null)
+ expect(outputTrackEnabledHandler).toHaveBeenCalledTimes(0)
+ })
+ })
+
+ describe('update input track', () => {
+ test('sets input track as its output track when setting same enabled input track again', () => {
+ const inputTrack = newMediaStreamTrackMock('input')
+
+ trackEnabler._setInputTrack('default', inputTrack)
+
+ outputTrackSetHandler.mockClear()
+ outputTrackEnabledHandler.mockClear()
+
+ expectedTrackEnabledStateInOutputTrackSetEvent = true
+
+ trackEnabler._setInputTrack('default', inputTrack)
+
+ expect(outputTrackSetHandler).toHaveBeenCalledTimes(1)
+ expect(outputTrackSetHandler).toHaveBeenCalledWith(trackEnabler, 'default', inputTrack)
+ expect(outputTrackEnabledHandler).toHaveBeenCalledTimes(0)
+ expect(inputTrack.enabled).toBe(true)
+ })
+
+ test('sets input track as its output track when setting same disabled input track again', () => {
+ const inputTrack = newMediaStreamTrackMock('input')
+
+ trackEnabler.setEnabled(false)
+
+ inputTrack.enabled = false
+ trackEnabler._setInputTrack('default', inputTrack)
+
+ outputTrackSetHandler.mockClear()
+ outputTrackEnabledHandler.mockClear()
+
+ expectedTrackEnabledStateInOutputTrackSetEvent = false
+
+ trackEnabler._setInputTrack('default', inputTrack)
+
+ expect(outputTrackSetHandler).toHaveBeenCalledTimes(1)
+ expect(outputTrackSetHandler).toHaveBeenCalledWith(trackEnabler, 'default', inputTrack)
+ expect(outputTrackEnabledHandler).toHaveBeenCalledTimes(0)
+ expect(inputTrack.enabled).toBe(false)
+ })
+
+ test('sets input track as its output track enabling it when setting same now disabled input track again', () => {
+ const inputTrack = newMediaStreamTrackMock('input')
+
+ trackEnabler._setInputTrack('default', inputTrack)
+
+ outputTrackSetHandler.mockClear()
+ outputTrackEnabledHandler.mockClear()
+
+ expectedTrackEnabledStateInOutputTrackSetEvent = true
+
+ inputTrack.enabled = false
+ trackEnabler._setInputTrack('default', inputTrack)
+
+ expect(outputTrackSetHandler).toHaveBeenCalledTimes(1)
+ expect(outputTrackSetHandler).toHaveBeenCalledWith(trackEnabler, 'default', inputTrack)
+ expect(outputTrackEnabledHandler).toHaveBeenCalledTimes(0)
+ expect(inputTrack.enabled).toBe(true)
+ })
+
+ test('sets input track as its output track disabling it when setting same now enabled input track again', () => {
+ const inputTrack = newMediaStreamTrackMock('input')
+
+ trackEnabler.setEnabled(false)
+
+ inputTrack.enabled = false
+ trackEnabler._setInputTrack('default', inputTrack)
+
+ outputTrackSetHandler.mockClear()
+ outputTrackEnabledHandler.mockClear()
+
+ expectedTrackEnabledStateInOutputTrackSetEvent = false
+
+ inputTrack.enabled = true
+ trackEnabler._setInputTrack('default', inputTrack)
+
+ expect(outputTrackSetHandler).toHaveBeenCalledTimes(1)
+ expect(outputTrackSetHandler).toHaveBeenCalledWith(trackEnabler, 'default', inputTrack)
+ expect(outputTrackEnabledHandler).toHaveBeenCalledTimes(0)
+ expect(inputTrack.enabled).toBe(false)
+ })
+
+ test('sets input track as its output track when setting another enabled input track', () => {
+ const inputTrack = newMediaStreamTrackMock('input')
+ const inputTrack2 = newMediaStreamTrackMock('input2')
+
+ trackEnabler._setInputTrack('default', inputTrack)
+
+ outputTrackSetHandler.mockClear()
+ outputTrackEnabledHandler.mockClear()
+
+ expectedTrackEnabledStateInOutputTrackSetEvent = true
+
+ trackEnabler._setInputTrack('default', inputTrack2)
+
+ expect(outputTrackSetHandler).toHaveBeenCalledTimes(1)
+ expect(outputTrackSetHandler).toHaveBeenCalledWith(trackEnabler, 'default', inputTrack2)
+ expect(outputTrackEnabledHandler).toHaveBeenCalledTimes(0)
+ expect(inputTrack.enabled).toBe(true)
+ })
+
+ test('sets input track as its output track when setting another disabled input track', () => {
+ const inputTrack = newMediaStreamTrackMock('input')
+ const inputTrack2 = newMediaStreamTrackMock('input2')
+
+ trackEnabler.setEnabled(false)
+
+ inputTrack.enabled = false
+ trackEnabler._setInputTrack('default', inputTrack)
+
+ outputTrackSetHandler.mockClear()
+ outputTrackEnabledHandler.mockClear()
+
+ expectedTrackEnabledStateInOutputTrackSetEvent = false
+
+ inputTrack2.enabled = false
+ trackEnabler._setInputTrack('default', inputTrack2)
+
+ expect(outputTrackSetHandler).toHaveBeenCalledTimes(1)
+ expect(outputTrackSetHandler).toHaveBeenCalledWith(trackEnabler, 'default', inputTrack2)
+ expect(outputTrackEnabledHandler).toHaveBeenCalledTimes(0)
+ expect(inputTrack.enabled).toBe(false)
+ })
+
+ test('sets input track as its output track enabling it when setting another now disabled input track', () => {
+ const inputTrack = newMediaStreamTrackMock('input')
+ const inputTrack2 = newMediaStreamTrackMock('input2')
+
+ trackEnabler._setInputTrack('default', inputTrack)
+
+ outputTrackSetHandler.mockClear()
+ outputTrackEnabledHandler.mockClear()
+
+ expectedTrackEnabledStateInOutputTrackSetEvent = true
+
+ inputTrack2.enabled = false
+ trackEnabler._setInputTrack('default', inputTrack2)
+
+ expect(outputTrackSetHandler).toHaveBeenCalledTimes(1)
+ expect(outputTrackSetHandler).toHaveBeenCalledWith(trackEnabler, 'default', inputTrack2)
+ expect(outputTrackEnabledHandler).toHaveBeenCalledTimes(0)
+ expect(inputTrack.enabled).toBe(true)
+ })
+
+ test('sets input track as its output track disabling it when setting another now enabled input track', () => {
+ const inputTrack = newMediaStreamTrackMock('input')
+ const inputTrack2 = newMediaStreamTrackMock('input2')
+
+ trackEnabler.setEnabled(false)
+
+ inputTrack.enabled = false
+ trackEnabler._setInputTrack('default', inputTrack)
+
+ outputTrackSetHandler.mockClear()
+ outputTrackEnabledHandler.mockClear()
+
+ expectedTrackEnabledStateInOutputTrackSetEvent = false
+
+ inputTrack2.enabled = true
+ trackEnabler._setInputTrack('default', inputTrack2)
+
+ expect(outputTrackSetHandler).toHaveBeenCalledTimes(1)
+ expect(outputTrackSetHandler).toHaveBeenCalledWith(trackEnabler, 'default', inputTrack2)
+ expect(outputTrackEnabledHandler).toHaveBeenCalledTimes(0)
+ expect(inputTrack.enabled).toBe(false)
+ })
+ })
+})
diff --git a/src/utils/media/pipeline/TrackToStream.js b/src/utils/media/pipeline/TrackToStream.js
index 562cc3e5035..d2b773f88b9 100644
--- a/src/utils/media/pipeline/TrackToStream.js
+++ b/src/utils/media/pipeline/TrackToStream.js
@@ -56,6 +56,8 @@ export default class TrackToStream extends TrackSink {
this._superEmitterMixin()
this._stream = null
+
+ this._trackEnabledStates = {}
}
addInputTrackSlot(trackId) {
@@ -69,6 +71,13 @@ export default class TrackToStream extends TrackSink {
_handleInputTrack(trackId, newTrack, oldTrack) {
// Only constraints changed, nothing to do
if (newTrack === oldTrack) {
+ // But trigger "trackEnabled" if the state changed
+ if (newTrack && this._trackEnabledStates[trackId] !== newTrack.enabled) {
+ this._trackEnabledStates[trackId] = newTrack.enabled
+
+ this._trigger('trackEnabled', [newTrack, newTrack.enabled])
+ }
+
return
}
@@ -86,6 +95,8 @@ export default class TrackToStream extends TrackSink {
this._stream.addTrack(newTrack)
}
+ this._trackEnabledStates[trackId] = newTrack?.enabled
+
this._trigger('trackReplaced', [newTrack, oldTrack])
if (this._stream && this._stream.getTracks().length === 0) {
@@ -98,6 +109,8 @@ export default class TrackToStream extends TrackSink {
}
_handleInputTrackEnabled(trackId, enabled) {
+ this._trackEnabledStates[trackId] = enabled
+
this._trigger('trackEnabled', [this.getInputTrack(trackId), enabled])
}
diff --git a/src/utils/media/pipeline/TrackToStream.spec.js b/src/utils/media/pipeline/TrackToStream.spec.js
new file mode 100644
index 00000000000..007a5e28b51
--- /dev/null
+++ b/src/utils/media/pipeline/TrackToStream.spec.js
@@ -0,0 +1,403 @@
+/**
+ *
+ * @copyright Copyright (c) 2022, Daniel Calviño Sánchez (danxuliu@gmail.com)
+ *
+ * @license AGPL-3.0-or-later
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+import TrackToStream from './TrackToStream'
+
+/**
+ * Helper function to create MediaStreamTrack mocks with just the attributes
+ * used by TrackToStream.
+ *
+ * @param {string} id the ID of the track
+ */
+function newMediaStreamTrackMock(id) {
+ /**
+ * MediaStreamTrackMock constructor.
+ */
+ function MediaStreamTrackMock() {
+ this.id = id
+ this.enabled = true
+ }
+ return new MediaStreamTrackMock()
+}
+
+describe('TrackToStream', () => {
+ let trackToStream
+ let streamSetHandler
+ let trackReplacedHandler
+ let trackEnabledHandler
+
+ beforeAll(() => {
+ // MediaStream is used in TrackToStream but not implemented in jsdom, so
+ // a stub is needed.
+ window.MediaStream = function() {
+ this._tracks = []
+
+ this.addTrack = jest.fn((track) => {
+ const index = this._tracks.indexOf(track)
+ if (index >= 0) {
+ console.error('Tried to add again track already added to stream')
+ return
+ }
+ this._tracks.push(track)
+ })
+ this.removeTrack = jest.fn((track) => {
+ const index = this._tracks.indexOf(track)
+ if (index < 0) {
+ console.error('Tried to delete track not added to stream')
+ return
+ }
+ this._tracks.splice(index, 1)
+ })
+ this.getTracks = jest.fn(() => {
+ return this._tracks
+ })
+ }
+ })
+
+ beforeEach(() => {
+ trackToStream = new TrackToStream()
+ trackToStream.addInputTrackSlot('audio')
+ trackToStream.addInputTrackSlot('video')
+
+ streamSetHandler = jest.fn()
+ trackReplacedHandler = jest.fn()
+ trackEnabledHandler = jest.fn()
+
+ trackToStream.on('streamSet', streamSetHandler)
+ trackToStream.on('trackReplaced', trackReplacedHandler)
+ trackToStream.on('trackEnabled', trackEnabledHandler)
+ })
+
+ test('has no stream by default', () => {
+ expect(trackToStream.getStream()).toBe(null)
+ })
+
+ describe('set input track', () => {
+ test('creates stream and adds track when setting first input track', () => {
+ const audioTrack = newMediaStreamTrackMock('audio')
+
+ trackToStream._setInputTrack('audio', audioTrack)
+
+ expect(trackToStream.getStream()).not.toBe(null)
+ expect(trackToStream.getStream().getTracks().length).toBe(1)
+ expect(trackToStream.getStream().getTracks()).toContain(audioTrack)
+ expect(streamSetHandler).toHaveBeenCalledTimes(1)
+ expect(streamSetHandler).toHaveBeenCalledWith(trackToStream, trackToStream.getStream(), null)
+ expect(trackReplacedHandler).toHaveBeenCalledTimes(1)
+ expect(trackReplacedHandler).toHaveBeenCalledWith(trackToStream, audioTrack, null)
+ expect(trackEnabledHandler).toHaveBeenCalledTimes(0)
+ })
+
+ test('adds track to existing stream when setting second input track', () => {
+ const audioTrack = newMediaStreamTrackMock('audio')
+ const videoTrack = newMediaStreamTrackMock('video')
+
+ trackToStream._setInputTrack('audio', audioTrack)
+
+ const stream = trackToStream.getStream()
+
+ trackToStream._setInputTrack('video', videoTrack)
+
+ expect(trackToStream.getStream()).not.toBe(null)
+ expect(trackToStream.getStream()).toBe(stream)
+ expect(trackToStream.getStream().getTracks().length).toBe(2)
+ expect(trackToStream.getStream().getTracks()).toContain(audioTrack)
+ expect(trackToStream.getStream().getTracks()).toContain(videoTrack)
+ expect(streamSetHandler).toHaveBeenCalledTimes(1)
+ expect(streamSetHandler).toHaveBeenCalledWith(trackToStream, trackToStream.getStream(), null)
+ expect(trackReplacedHandler).toHaveBeenCalledTimes(2)
+ expect(trackReplacedHandler).toHaveBeenNthCalledWith(1, trackToStream, audioTrack, null)
+ expect(trackReplacedHandler).toHaveBeenNthCalledWith(2, trackToStream, videoTrack, null)
+ expect(trackEnabledHandler).toHaveBeenCalledTimes(0)
+ })
+
+ test('does not trigger trackEnabled when setting disabled input track', () => {
+ const audioTrack = newMediaStreamTrackMock('audio')
+
+ audioTrack.enabled = false
+ trackToStream._setInputTrack('audio', audioTrack)
+
+ expect(trackToStream.getStream()).not.toBe(null)
+ expect(trackToStream.getStream().getTracks().length).toBe(1)
+ expect(trackToStream.getStream().getTracks()).toContain(audioTrack)
+ expect(streamSetHandler).toHaveBeenCalledTimes(1)
+ expect(streamSetHandler).toHaveBeenCalledWith(trackToStream, trackToStream.getStream(), null)
+ expect(trackReplacedHandler).toHaveBeenCalledTimes(1)
+ expect(trackReplacedHandler).toHaveBeenCalledWith(trackToStream, audioTrack, null)
+ expect(trackEnabledHandler).toHaveBeenCalledTimes(0)
+ })
+
+ test('creates another stream when setting first input track again after removing it', () => {
+ const audioTrack = newMediaStreamTrackMock('audio')
+
+ trackToStream._setInputTrack('audio', audioTrack)
+
+ const stream = trackToStream.getStream()
+
+ trackToStream._setInputTrack('audio', null)
+
+ streamSetHandler.mockClear()
+ trackReplacedHandler.mockClear()
+ trackEnabledHandler.mockClear()
+
+ trackToStream._setInputTrack('audio', audioTrack)
+
+ expect(trackToStream.getStream()).not.toBe(stream)
+ expect(trackToStream.getStream()).not.toBe(null)
+ expect(trackToStream.getStream().getTracks().length).toBe(1)
+ expect(trackToStream.getStream().getTracks()).toContain(audioTrack)
+ expect(streamSetHandler).toHaveBeenCalledTimes(1)
+ expect(streamSetHandler).toHaveBeenCalledWith(trackToStream, trackToStream.getStream(), null)
+ expect(trackReplacedHandler).toHaveBeenCalledTimes(1)
+ expect(trackReplacedHandler).toHaveBeenCalledWith(trackToStream, audioTrack, null)
+ expect(trackEnabledHandler).toHaveBeenCalledTimes(0)
+ })
+ })
+
+ describe('enable/disable input track', () => {
+ test('triggers event if input track is disabled', () => {
+ const audioTrack = newMediaStreamTrackMock('audio')
+
+ audioTrack.enabled = true
+ trackToStream._setInputTrack('audio', audioTrack)
+
+ audioTrack.enabled = false
+ trackToStream._setInputTrackEnabled('audio', false)
+
+ expect(trackEnabledHandler).toHaveBeenCalledTimes(1)
+ expect(trackEnabledHandler).toHaveBeenCalledWith(trackToStream, audioTrack, false)
+ })
+
+ test('triggers event if input track is enabled', () => {
+ const audioTrack = newMediaStreamTrackMock('audio')
+
+ audioTrack.enabled = false
+ trackToStream._setInputTrack('audio', audioTrack)
+
+ audioTrack.enabled = true
+ trackToStream._setInputTrackEnabled('audio', true)
+
+ expect(trackEnabledHandler).toHaveBeenCalledTimes(1)
+ expect(trackEnabledHandler).toHaveBeenCalledWith(trackToStream, audioTrack, true)
+ })
+ })
+
+ describe('remove input track', () => {
+ test('removes track from existing stream when removing input track', () => {
+ const audioTrack = newMediaStreamTrackMock('audio')
+ const videoTrack = newMediaStreamTrackMock('video')
+
+ trackToStream._setInputTrack('audio', audioTrack)
+ trackToStream._setInputTrack('video', videoTrack)
+
+ const stream = trackToStream.getStream()
+
+ streamSetHandler.mockClear()
+ trackReplacedHandler.mockClear()
+ trackEnabledHandler.mockClear()
+
+ trackToStream._setInputTrack('audio', null)
+
+ expect(trackToStream.getStream()).not.toBe(null)
+ expect(trackToStream.getStream()).toBe(stream)
+ expect(trackToStream.getStream().getTracks().length).toBe(1)
+ expect(trackToStream.getStream().getTracks()).not.toContain(audioTrack)
+ expect(trackToStream.getStream().getTracks()).toContain(videoTrack)
+ expect(streamSetHandler).toHaveBeenCalledTimes(0)
+ expect(trackReplacedHandler).toHaveBeenCalledTimes(1)
+ expect(trackReplacedHandler).toHaveBeenCalledWith(trackToStream, null, audioTrack)
+ expect(trackEnabledHandler).toHaveBeenCalledTimes(0)
+ })
+
+ test('removes track and stream when removing remaining input track', () => {
+ const audioTrack = newMediaStreamTrackMock('audio')
+ const videoTrack = newMediaStreamTrackMock('video')
+
+ trackToStream._setInputTrack('audio', audioTrack)
+ trackToStream._setInputTrack('video', videoTrack)
+
+ const stream = trackToStream.getStream()
+ expect(stream).not.toBe(null)
+
+ streamSetHandler.mockClear()
+ trackReplacedHandler.mockClear()
+ trackEnabledHandler.mockClear()
+
+ trackToStream._setInputTrack('audio', null)
+ trackToStream._setInputTrack('video', null)
+
+ expect(trackToStream.getStream()).toBe(null)
+ expect(streamSetHandler).toHaveBeenCalledTimes(1)
+ expect(streamSetHandler).toHaveBeenCalledWith(trackToStream, null, stream)
+ expect(trackReplacedHandler).toHaveBeenCalledTimes(2)
+ expect(trackReplacedHandler).toHaveBeenNthCalledWith(1, trackToStream, null, audioTrack)
+ expect(trackReplacedHandler).toHaveBeenNthCalledWith(2, trackToStream, null, videoTrack)
+ expect(trackEnabledHandler).toHaveBeenCalledTimes(0)
+ })
+ })
+
+ describe('update input track', () => {
+ test('does nothing when setting same input track again', () => {
+ const audioTrack = newMediaStreamTrackMock('audio')
+
+ trackToStream._setInputTrack('audio', audioTrack)
+
+ const stream = trackToStream.getStream()
+
+ streamSetHandler.mockClear()
+ trackReplacedHandler.mockClear()
+ trackEnabledHandler.mockClear()
+
+ trackToStream._setInputTrack('audio', audioTrack)
+
+ expect(trackToStream.getStream()).not.toBe(null)
+ expect(trackToStream.getStream()).toBe(stream)
+ expect(trackToStream.getStream().getTracks().length).toBe(1)
+ expect(trackToStream.getStream().getTracks()).toContain(audioTrack)
+ expect(streamSetHandler).toHaveBeenCalledTimes(0)
+ expect(trackReplacedHandler).toHaveBeenCalledTimes(0)
+ expect(trackEnabledHandler).toHaveBeenCalledTimes(0)
+ })
+
+ test('triggers event when setting same now disabled input track again', () => {
+ const audioTrack = newMediaStreamTrackMock('audio')
+
+ trackToStream._setInputTrack('audio', audioTrack)
+
+ const stream = trackToStream.getStream()
+
+ streamSetHandler.mockClear()
+ trackReplacedHandler.mockClear()
+ trackEnabledHandler.mockClear()
+
+ audioTrack.enabled = false
+ trackToStream._setInputTrack('audio', audioTrack)
+
+ expect(trackToStream.getStream()).not.toBe(null)
+ expect(trackToStream.getStream()).toBe(stream)
+ expect(trackToStream.getStream().getTracks().length).toBe(1)
+ expect(trackToStream.getStream().getTracks()).toContain(audioTrack)
+ expect(streamSetHandler).toHaveBeenCalledTimes(0)
+ expect(trackReplacedHandler).toHaveBeenCalledTimes(0)
+ expect(trackEnabledHandler).toHaveBeenCalledTimes(1)
+ expect(trackEnabledHandler).toHaveBeenCalledWith(trackToStream, audioTrack, false)
+ })
+
+ test('triggers event when setting same now enabled input track again', () => {
+ const audioTrack = newMediaStreamTrackMock('audio')
+
+ audioTrack.enabled = false
+ trackToStream._setInputTrack('audio', audioTrack)
+
+ const stream = trackToStream.getStream()
+
+ streamSetHandler.mockClear()
+ trackReplacedHandler.mockClear()
+ trackEnabledHandler.mockClear()
+
+ audioTrack.enabled = true
+ trackToStream._setInputTrack('audio', audioTrack)
+
+ expect(trackToStream.getStream()).not.toBe(null)
+ expect(trackToStream.getStream()).toBe(stream)
+ expect(trackToStream.getStream().getTracks().length).toBe(1)
+ expect(trackToStream.getStream().getTracks()).toContain(audioTrack)
+ expect(streamSetHandler).toHaveBeenCalledTimes(0)
+ expect(trackReplacedHandler).toHaveBeenCalledTimes(0)
+ expect(trackEnabledHandler).toHaveBeenCalledTimes(1)
+ expect(trackEnabledHandler).toHaveBeenCalledWith(trackToStream, audioTrack, true)
+ })
+
+ test('replaces track in existing stream when setting another input track', () => {
+ const audioTrack = newMediaStreamTrackMock('audio')
+ const audioTrack2 = newMediaStreamTrackMock('audio2')
+
+ trackToStream._setInputTrack('audio', audioTrack)
+
+ const stream = trackToStream.getStream()
+
+ streamSetHandler.mockClear()
+ trackReplacedHandler.mockClear()
+ trackEnabledHandler.mockClear()
+
+ trackToStream._setInputTrack('audio', audioTrack2)
+
+ expect(trackToStream.getStream()).not.toBe(null)
+ expect(trackToStream.getStream()).toBe(stream)
+ expect(trackToStream.getStream().getTracks().length).toBe(1)
+ expect(trackToStream.getStream().getTracks()).toContain(audioTrack2)
+ expect(streamSetHandler).toHaveBeenCalledTimes(0)
+ expect(trackReplacedHandler).toHaveBeenCalledTimes(1)
+ expect(trackReplacedHandler).toHaveBeenCalledWith(trackToStream, audioTrack2, audioTrack)
+ expect(trackEnabledHandler).toHaveBeenCalledTimes(0)
+ })
+
+ test('does not trigger trackEnabled when setting another now disabled input track', () => {
+ const audioTrack = newMediaStreamTrackMock('audio')
+ const audioTrack2 = newMediaStreamTrackMock('audio2')
+
+ trackToStream._setInputTrack('audio', audioTrack)
+
+ const stream = trackToStream.getStream()
+
+ streamSetHandler.mockClear()
+ trackReplacedHandler.mockClear()
+ trackEnabledHandler.mockClear()
+
+ audioTrack2.enabled = false
+ trackToStream._setInputTrack('audio', audioTrack2)
+
+ expect(trackToStream.getStream()).not.toBe(null)
+ expect(trackToStream.getStream()).toBe(stream)
+ expect(trackToStream.getStream().getTracks().length).toBe(1)
+ expect(trackToStream.getStream().getTracks()).toContain(audioTrack2)
+ expect(streamSetHandler).toHaveBeenCalledTimes(0)
+ expect(trackReplacedHandler).toHaveBeenCalledTimes(1)
+ expect(trackReplacedHandler).toHaveBeenCalledWith(trackToStream, audioTrack2, audioTrack)
+ expect(trackEnabledHandler).toHaveBeenCalledTimes(0)
+ })
+
+ test('does not trigger trackEnabled when setting another now enabled input track', () => {
+ const audioTrack = newMediaStreamTrackMock('audio')
+ const audioTrack2 = newMediaStreamTrackMock('audio2')
+
+ audioTrack.enabled = false
+ trackToStream._setInputTrack('audio', audioTrack)
+
+ streamSetHandler.mockClear()
+ trackReplacedHandler.mockClear()
+ trackEnabledHandler.mockClear()
+
+ const stream = trackToStream.getStream()
+
+ trackToStream._setInputTrack('audio', audioTrack2)
+
+ expect(trackToStream.getStream()).not.toBe(null)
+ expect(trackToStream.getStream()).toBe(stream)
+ expect(trackToStream.getStream().getTracks().length).toBe(1)
+ expect(trackToStream.getStream().getTracks()).toContain(audioTrack2)
+ expect(streamSetHandler).toHaveBeenCalledTimes(0)
+ expect(trackReplacedHandler).toHaveBeenCalledTimes(1)
+ expect(trackReplacedHandler).toHaveBeenCalledWith(trackToStream, audioTrack2, audioTrack)
+ expect(trackEnabledHandler).toHaveBeenCalledTimes(0)
+ })
+ })
+})
diff --git a/src/utils/webrtc/index.js b/src/utils/webrtc/index.js
index 7963edc50c0..8ff284cbb5e 100644
--- a/src/utils/webrtc/index.js
+++ b/src/utils/webrtc/index.js
@@ -193,26 +193,26 @@ async function signalingJoinCall(token, flags) {
const enableVideo = !localStorage.getItem('videoDisabled_' + token)
const enableVirtualBackground = !!localStorage.getItem('virtualBackgroundEnabled_' + token)
+ if (enableAudio) {
+ localMediaModel.enableAudio()
+ } else {
+ localMediaModel.disableAudio()
+ }
+ if (enableVideo) {
+ localMediaModel.enableVideo()
+ } else {
+ localMediaModel.disableVideo()
+ }
+ if (enableVirtualBackground) {
+ localMediaModel.enableVirtualBackground()
+ } else {
+ localMediaModel.disableVirtualBackground()
+ }
+
const startCallOnceLocalMediaStarted = (configuration) => {
webRtc.off('localMediaStarted', startCallOnceLocalMediaStarted)
webRtc.off('localMediaError', startCallOnceLocalMediaError)
- if (enableAudio) {
- localMediaModel.enableAudio()
- } else {
- localMediaModel.disableAudio()
- }
- if (enableVideo) {
- localMediaModel.enableVideo()
- } else {
- localMediaModel.disableVideo()
- }
- if (enableVirtualBackground) {
- localMediaModel.enableVirtualBackground()
- } else {
- localMediaModel.disableVirtualBackground()
- }
-
startCall(_signaling, configuration)
}
const startCallOnceLocalMediaError = () => {
diff --git a/src/utils/webrtc/models/LocalMediaModel.js b/src/utils/webrtc/models/LocalMediaModel.js
index 3f87eb8c262..09313597121 100644
--- a/src/utils/webrtc/models/LocalMediaModel.js
+++ b/src/utils/webrtc/models/LocalMediaModel.js
@@ -52,16 +52,13 @@ export default function LocalMediaModel() {
this._handleLocalStreamRequestFailedRetryNoVideoBound = this._handleLocalStreamRequestFailedRetryNoVideo.bind(this)
this._handleLocalStreamRequestFailedBound = this._handleLocalStreamRequestFailed.bind(this)
this._handleLocalStreamChangedBound = this._handleLocalStreamChanged.bind(this)
+ this._handleLocalTrackEnabledChangedBound = this._handleLocalTrackEnabledChanged.bind(this)
this._handleLocalStreamStoppedBound = this._handleLocalStreamStopped.bind(this)
- this._handleAudioOnBound = this._handleAudioOn.bind(this)
- this._handleAudioOffBound = this._handleAudioOff.bind(this)
this._handleVolumeChangeBound = this._handleVolumeChange.bind(this)
this._handleSpeakingBound = this._handleSpeaking.bind(this)
this._handleStoppedSpeakingBound = this._handleStoppedSpeaking.bind(this)
this._handleSpeakingWhileMutedBound = this._handleSpeakingWhileMuted.bind(this)
this._handleStoppedSpeakingWhileMutedBound = this._handleStoppedSpeakingWhileMuted.bind(this)
- this._handleVideoOnBound = this._handleVideoOn.bind(this)
- this._handleVideoOffBound = this._handleVideoOff.bind(this)
this._handleVirtualBackgroundLoadFailedBound = this._handleVirtualBackgroundLoadFailed.bind(this)
this._handleVirtualBackgroundOnBound = this._handleVirtualBackgroundOn.bind(this)
this._handleVirtualBackgroundOffBound = this._handleVirtualBackgroundOff.bind(this)
@@ -97,16 +94,13 @@ LocalMediaModel.prototype = {
this._webRtc.webrtc.off('localStreamRequestFailedRetryNoVideo', this._handleLocalStreamRequestFailedBound)
this._webRtc.webrtc.off('localStreamRequestFailed', this._handleLocalStreamRequestFailedBound)
this._webRtc.webrtc.off('localStreamChanged', this._handleLocalStreamChangedBound)
+ this._webRtc.webrtc.off('localTrackEnabledChanged', this._handleLocalTrackEnabledChangedBound)
this._webRtc.webrtc.off('localStreamStopped', this._handleLocalStreamStoppedBound)
- this._webRtc.webrtc.off('audioOn', this._handleAudioOnBound)
- this._webRtc.webrtc.off('audioOff', this._handleAudioOffBound)
this._webRtc.webrtc.off('volumeChange', this._handleVolumeChangeBound)
this._webRtc.webrtc.off('speaking', this._handleSpeakingBound)
this._webRtc.webrtc.off('stoppedSpeaking', this._handleStoppedSpeakingBound)
this._webRtc.webrtc.off('speakingWhileMuted', this._handleSpeakingWhileMutedBound)
this._webRtc.webrtc.off('stoppedSpeakingWhileMuted', this._handleStoppedSpeakingWhileMutedBound)
- this._webRtc.webrtc.off('videoOn', this._handleVideoOnBound)
- this._webRtc.webrtc.off('videoOff', this._handleVideoOffBound)
this._webRtc.webrtc.off('virtualBackgroundLoadFailed', this._handleVirtualBackgroundLoadFailedBound)
this._webRtc.webrtc.off('virtualBackgroundOn', this._handleVirtualBackgroundOnBound)
this._webRtc.webrtc.off('virtualBackgroundOff', this._handleVirtualBackgroundOffBound)
@@ -134,16 +128,13 @@ LocalMediaModel.prototype = {
this._webRtc.webrtc.on('localStreamRequestFailedRetryNoVideo', this._handleLocalStreamRequestFailedRetryNoVideoBound)
this._webRtc.webrtc.on('localStreamRequestFailed', this._handleLocalStreamRequestFailedBound)
this._webRtc.webrtc.on('localStreamChanged', this._handleLocalStreamChangedBound)
+ this._webRtc.webrtc.on('localTrackEnabledChanged', this._handleLocalTrackEnabledChangedBound)
this._webRtc.webrtc.on('localStreamStopped', this._handleLocalStreamStoppedBound)
- this._webRtc.webrtc.on('audioOn', this._handleAudioOnBound)
- this._webRtc.webrtc.on('audioOff', this._handleAudioOffBound)
this._webRtc.webrtc.on('volumeChange', this._handleVolumeChangeBound)
this._webRtc.webrtc.on('speaking', this._handleSpeakingBound)
this._webRtc.webrtc.on('stoppedSpeaking', this._handleStoppedSpeakingBound)
this._webRtc.webrtc.on('speakingWhileMuted', this._handleSpeakingWhileMutedBound)
this._webRtc.webrtc.on('stoppedSpeakingWhileMuted', this._handleStoppedSpeakingWhileMutedBound)
- this._webRtc.webrtc.on('videoOn', this._handleVideoOnBound)
- this._webRtc.webrtc.on('videoOff', this._handleVideoOffBound)
this._webRtc.webrtc.on('virtualBackgroundLoadFailed', this._handleVirtualBackgroundLoadFailedBound)
this._webRtc.webrtc.on('virtualBackgroundOn', this._handleVirtualBackgroundOnBound)
this._webRtc.webrtc.on('virtualBackgroundOff', this._handleVirtualBackgroundOffBound)
@@ -170,9 +161,7 @@ LocalMediaModel.prototype = {
// local stream will be active at the same time.
this.set('localStream', localStream)
- this.set('token', store.getters.getToken())
-
- this._setInitialMediaState(configuration)
+ this._setInitialState(localStream)
},
_handleLocalStreamRequestFailedRetryNoVideo(constraints, error) {
@@ -186,33 +175,13 @@ LocalMediaModel.prototype = {
_handleLocalStreamRequestFailed() {
this.set('localStream', null)
- this._setInitialMediaState({ audio: false, video: false })
+ this._setInitialState(null)
},
- _setInitialMediaState(configuration) {
- if (configuration.audio !== false) {
- this.set('audioAvailable', true)
- if (this.get('audioEnabled')) {
- this.enableAudio()
- } else {
- this.disableAudio()
- }
- } else {
- this.set('audioEnabled', false)
- this.set('audioAvailable', false)
- }
+ _setInitialState(localStream) {
+ this.set('token', store.getters.getToken())
- if (configuration.video !== false) {
- this.set('videoAvailable', true)
- if (this.get('videoEnabled')) {
- this.enableVideo()
- } else {
- this.disableVideo()
- }
- } else {
- this.set('videoEnabled', false)
- this.set('videoAvailable', false)
- }
+ this._updateMediaAvailability(localStream)
this.set('raisedHand', { state: false, timestamp: Date.now() })
},
@@ -227,19 +196,41 @@ LocalMediaModel.prototype = {
_updateMediaAvailability(localStream) {
if (localStream && localStream.getAudioTracks().length > 0) {
this.set('audioAvailable', true)
+ this.set('audioEnabled', localStream.getAudioTracks()[0].enabled)
} else {
this.disableAudio()
+ // "audioEnabled" needs to be explicitly set to false, as there is
+ // no audio track and thus disabling the audio will not trigger the
+ // handler for "localTrackEnabledChanged"; calling "disableAudio()"
+ // just ensures that the audio will be initially disabled if it
+ // becomes available again later.
+ this.set('audioEnabled', false)
this.set('audioAvailable', false)
}
if (localStream && localStream.getVideoTracks().length > 0) {
this.set('videoAvailable', true)
+ this.set('videoEnabled', localStream.getVideoTracks()[0].enabled)
} else {
this.disableVideo()
+ // "videoEnabled" needs to be explicitly set to false, as there is
+ // no video track and thus disabling the video will not trigger the
+ // handler for "localTrackEnabledChanged"; calling "disableVideo()"
+ // just ensures that the video will be initially disabled if it
+ // becomes available again later.
+ this.set('videoEnabled', false)
this.set('videoAvailable', false)
}
},
+ _handleLocalTrackEnabledChanged(track, stream) {
+ if (track.kind === 'audio') {
+ this.set('audioEnabled', track.enabled)
+ } else if (track.kind === 'video') {
+ this.set('videoEnabled', track.enabled)
+ }
+ },
+
_handleLocalStreamStopped(localStream) {
if (this.get('localStream') !== localStream) {
return
@@ -253,22 +244,6 @@ LocalMediaModel.prototype = {
this.set('videoAvailable', false)
},
- _handleAudioOn() {
- if (!this.get('audioAvailable')) {
- return
- }
-
- this.set('audioEnabled', true)
- },
-
- _handleAudioOff() {
- if (!this.get('audioAvailable')) {
- return
- }
-
- this.set('audioEnabled', false)
- },
-
_handleVolumeChange(currentVolume, volumeThreshold) {
if (!this.get('audioAvailable')) {
return
@@ -310,22 +285,6 @@ LocalMediaModel.prototype = {
this.set('speakingWhileMuted', false)
},
- _handleVideoOn() {
- if (!this.get('videoAvailable')) {
- return
- }
-
- this.set('videoEnabled', true)
- },
-
- _handleVideoOff() {
- if (!this.get('videoAvailable')) {
- return
- }
-
- this.set('videoEnabled', false)
- },
-
_handleVirtualBackgroundLoadFailed() {
this.set('virtualBackgroundAvailable', false)
},
@@ -352,9 +311,6 @@ LocalMediaModel.prototype = {
}
localStorage.removeItem('audioDisabled_' + this.get('token'))
- if (!this.get('audioAvailable')) {
- return
- }
this._webRtc.unmute()
},
@@ -365,12 +321,6 @@ LocalMediaModel.prototype = {
}
localStorage.setItem('audioDisabled_' + this.get('token'), 'true')
- if (!this.get('audioAvailable')) {
- // Ensure that the audio will be disabled once available.
- this.set('audioEnabled', false)
-
- return
- }
this._webRtc.mute()
},
@@ -381,9 +331,6 @@ LocalMediaModel.prototype = {
}
localStorage.removeItem('videoDisabled_' + this.get('token'))
- if (!this.get('videoAvailable')) {
- return
- }
this._webRtc.resumeVideo()
},
@@ -394,12 +341,6 @@ LocalMediaModel.prototype = {
}
localStorage.setItem('videoDisabled_' + this.get('token'), 'true')
- if (!this.get('videoAvailable')) {
- // Ensure that the video will be disabled once available.
- this.set('videoEnabled', false)
-
- return
- }
this._webRtc.pauseVideo()
},