diff --git a/src/services/__tests__/mediaDevicePreferences.spec.js b/src/services/__tests__/mediaDevicePreferences.spec.js new file mode 100644 index 00000000000..9c0afd9eb22 --- /dev/null +++ b/src/services/__tests__/mediaDevicePreferences.spec.js @@ -0,0 +1,190 @@ +import { + getFirstAvailableMediaDevice, + listMediaDevices, + populateMediaDevicesPreferences, + updateMediaDevicesPreferences, +} from '../mediaDevicePreferences.ts' + +describe('mediaDevicePreferences', () => { + afterEach(() => { + // cleaning up the mess left behind the previous test + jest.clearAllMocks() + }) + + // navigator.enumerateDevices() will list 'default' capture device first + const audioInputDeviceDefault = { deviceId: 'default', groupId: 'def1234567890', kind: 'audioinput', label: 'Default' } + const audioInputDeviceA = { deviceId: 'da1234567890', groupId: 'ga1234567890', kind: 'audioinput', label: 'Audio Input Device A' } + const audioInputDeviceB = { deviceId: 'db1234567890', groupId: 'gb1234567890', kind: 'audioinput', label: 'Audio Input Device B' } + + const videoInputDeviceDefault = { deviceId: 'default', groupId: 'def4567890123', kind: 'videoinput', label: 'Default' } + const videoInputDeviceA = { deviceId: 'da4567890123', groupId: 'ga4567890123', kind: 'videoinput', label: 'Video Input Device A' } + const videoInputDeviceB = { deviceId: 'db4567890123', groupId: 'gb4567890123', kind: 'videoinput', label: 'Video Input Device B' } + + const audioOutputDeviceDefault = { deviceId: 'default', groupId: 'def7890123456', kind: 'audiooutput', label: 'Default' } + const audioOutputDeviceA = { deviceId: 'da7890123456', groupId: 'ga7890123456', kind: 'audiooutput', label: 'Audio Output Device A' } + const audioOutputDeviceB = { deviceId: 'db7890123456', groupId: 'gb7890123456', kind: 'audiooutput', label: 'Audio Output Device B' } + + const allDevices = [audioInputDeviceDefault, audioInputDeviceA, audioInputDeviceB, + videoInputDeviceDefault, videoInputDeviceA, videoInputDeviceB, + audioOutputDeviceDefault, audioOutputDeviceA, audioOutputDeviceB] + const audioInputPreferenceList = [audioInputDeviceDefault, audioInputDeviceA, audioInputDeviceB] + const videoInputPreferenceList = [videoInputDeviceDefault, videoInputDeviceA, videoInputDeviceB] + + describe('listMediaDevices', () => { + it('list all input devices from preference lists', () => { + const attributes = { devices: allDevices, audioInputId: undefined, videoInputId: undefined } + const output = listMediaDevices(attributes, audioInputPreferenceList, videoInputPreferenceList) + + // Assert: should show all registered devices, apart from default / outputs + const inputDevices = allDevices.filter(device => device.kind !== 'audiooutput' && device.deviceId !== 'default') + inputDevices.forEach(device => { + expect(output).toContain(device.deviceId) + }) + }) + + it('show selected devices from preference lists', () => { + const attributes = { devices: allDevices, audioInputId: audioInputDeviceA.deviceId, videoInputId: videoInputDeviceA.deviceId } + const output = listMediaDevices(attributes, audioInputPreferenceList, videoInputPreferenceList) + + // Assert: should show a label next to selected registered devices + const selectedDeviceIds = [audioInputDeviceA.deviceId, videoInputDeviceA.deviceId] + selectedDeviceIds.forEach(deviceId => { + expect(output).toContain(deviceId + ' (selected)') + }) + }) + + it('show unplugged devices from preference lists', () => { + const unpluggedDeviceIds = [audioInputDeviceA.deviceId, videoInputDeviceA.deviceId] + const attributes = { + devices: allDevices.filter(device => !unpluggedDeviceIds.includes(device.deviceId)), + audioInputId: undefined, + videoInputId: undefined, + } + const output = listMediaDevices(attributes, audioInputPreferenceList, videoInputPreferenceList) + + // Assert: should show a label next to unplugged registered devices + unpluggedDeviceIds.forEach(deviceId => { + expect(output).toContain(deviceId + ' (unplugged)') + }) + }) + }) + + describe('getFirstAvailableMediaDevice', () => { + it('returns id of first available device from preference list', () => { + const output = getFirstAvailableMediaDevice(allDevices, audioInputPreferenceList) + + // Assert: should return default id + expect(output).toBe('default') + }) + + it('returns id of first available device from preference list (default device is unavailable)', () => { + const output = getFirstAvailableMediaDevice( + allDevices.filter(device => device.deviceId !== 'default'), + audioInputPreferenceList, + ) + + // Assert: should return id of device A + expect(output).toBe(audioInputPreferenceList[1].deviceId) + }) + + it('returns undefined if there is no available devices from preference list', () => { + const output = getFirstAvailableMediaDevice( + allDevices.filter(device => device.kind !== 'audioinput'), + audioInputPreferenceList, + ) + + // Assert: should return provided fallback id + expect(output).not.toBeDefined() + }) + }) + + describe('populateMediaDevicesPreferences', () => { + beforeEach(() => { + console.debug = jest.fn() + }) + + it('returns preference lists with all available devices', () => { + const output = populateMediaDevicesPreferences(allDevices, [], []) + + // Assert: should contain all available devices, apart from default / outputs + expect(output).toMatchObject({ newAudioInputList: audioInputPreferenceList, newVideoInputList: videoInputPreferenceList }) + }) + + it('returns null if preference lists were not updated', () => { + const output = populateMediaDevicesPreferences(allDevices, audioInputPreferenceList, videoInputPreferenceList) + + // Assert + expect(output).toMatchObject({ newAudioInputList: null, newVideoInputList: null }) + }) + }) + + describe('updateMediaDevicesPreferences', () => { + it('returns null if preference lists were not updated (no id or default id provided)', () => { + const ids = [null, undefined, 'default'] + + const getOutput = (id) => { + const attributes = { devices: allDevices, audioInputId: id, videoInputId: id } + return updateMediaDevicesPreferences(attributes, audioInputPreferenceList, videoInputPreferenceList) + } + + // Assert + ids.forEach(id => { + expect(getOutput(id)).toMatchObject({ newAudioInputList: null, newVideoInputList: null }) + }) + }) + + it('returns updated preference lists (device A id provided)', () => { + const attributes = { devices: allDevices, audioInputId: audioInputDeviceA.deviceId, videoInputId: videoInputDeviceA.deviceId } + const output = updateMediaDevicesPreferences(attributes, audioInputPreferenceList, videoInputPreferenceList) + + // Assert: should put device A on top of default device + expect(output).toMatchObject({ + newAudioInputList: [audioInputDeviceA, audioInputDeviceDefault, audioInputDeviceB], + newVideoInputList: [videoInputDeviceA, videoInputDeviceDefault, videoInputDeviceB], + }) + }) + + it('returns null if preference lists were not updated (device A id provided but not available)', () => { + const attributes = { + devices: allDevices.filter(device => !['da1234567890', 'da4567890123'].includes(device.deviceId)), + audioInputId: audioInputDeviceA.deviceId, + videoInputId: videoInputDeviceA.deviceId, + } + const output = updateMediaDevicesPreferences(attributes, audioInputPreferenceList, videoInputPreferenceList) + + // Assert + expect(output).toMatchObject({ newAudioInputList: null, newVideoInputList: null }) + }) + + it('returns null if preference lists were not updated (all devices are not available)', () => { + const attributes = { + devices: allDevices.filter(device => !['audioinput', 'videoinput'].includes(device.kind)), + audioInputId: audioInputDeviceA.deviceId, + videoInputId: videoInputDeviceA.deviceId, + } + const output = updateMediaDevicesPreferences(attributes, audioInputPreferenceList, videoInputPreferenceList) + + // Assert + expect(output).toMatchObject({ newAudioInputList: null, newVideoInputList: null }) + }) + + it('returns updated preference lists (device B id provided, but not registered, default device and device A not available)', () => { + const attributes = { + devices: allDevices.filter(device => !['default', 'da1234567890', 'da4567890123'].includes(device.deviceId)), + audioInputId: audioInputDeviceB.deviceId, + videoInputId: videoInputDeviceB.deviceId, + } + const output = updateMediaDevicesPreferences( + attributes, + [audioInputDeviceDefault, audioInputDeviceA], + [videoInputDeviceDefault, videoInputDeviceA], + ) + + // Assert: should put device C on top of device B, but not the device A + expect(output).toMatchObject({ + newAudioInputList: [audioInputDeviceDefault, audioInputDeviceA, audioInputDeviceB], + newVideoInputList: [videoInputDeviceDefault, videoInputDeviceA, videoInputDeviceB], + }) + }) + }) +}) diff --git a/src/services/mediaDevicePreferences.ts b/src/services/mediaDevicePreferences.ts index 6693e7948ba..88c8e56dab1 100644 --- a/src/services/mediaDevicePreferences.ts +++ b/src/services/mediaDevicePreferences.ts @@ -20,33 +20,49 @@ * */ +type InputId = string | undefined | null +type InputListUpdated = MediaDeviceInfo[] | null +type InputLists = { + newAudioInputList: InputListUpdated, + newVideoInputList: InputListUpdated, +} +type Attributes = { + devices: MediaDeviceInfo[], + audioInputId: InputId, + videoInputId: InputId, +} + +enum DeviceKind { + AudioInput = 'audioinput', + VideoInput = 'videoinput', + AudioOutput = 'audiooutput', +} + /** * List all registered devices in order of their preferences * Show whether device is currently unplugged or selected, if information is available * - * @param devices list of available devices - * @param audioInputId id of currently selected audio input - * @param videoInputId id of currently selected video input + * @param attributes MediaDeviceManager attributes * @param audioInputList list of registered audio devices in order of preference * @param videoInputList list of registered video devices in order of preference + * @return {string} preference list in readable format */ -function listMediaDevices(devices: MediaDeviceInfo[], audioInputId: string, videoInputId: string, audioInputList: MediaDeviceInfo[], videoInputList: MediaDeviceInfo[]): void { - const availableDevices = devices.map(device => device.deviceId).filter(id => id !== 'default') +function listMediaDevices(attributes: Attributes, audioInputList: MediaDeviceInfo[], videoInputList: MediaDeviceInfo[]): string { + const availableDevices = attributes.devices.map(device => device.deviceId) const getDeviceString = (device: MediaDeviceInfo, index: number) => { const isUnplugged = !availableDevices.includes(device.deviceId) ? ' (unplugged)' : '' const isSelected = () => { - if (device.kind === 'audioinput') { - return device.deviceId === audioInputId ? ' (selected)' : '' - } else if (device.kind === 'videoinput') { - return device.deviceId === videoInputId ? ' (selected)' : '' + if (device.kind === DeviceKind.AudioInput) { + return device.deviceId === attributes.audioInputId ? ' (selected)' : '' + } else if (device.kind === DeviceKind.VideoInput) { + return device.deviceId === attributes.videoInputId ? ' (selected)' : '' } } return ` ${index + 1}. ${device.label} | ${device.deviceId}` + isUnplugged + isSelected() } - // eslint-disable-next-line no-console - console.log(`Media devices: + return (`Media devices: Audio input: ${audioInputList.map(getDeviceString).join('\n')} @@ -58,16 +74,14 @@ ${videoInputList.map(getDeviceString).join('\n')} /** * Get the first available device from the preference list. * - * Returns id of device from the list / provided fallback id / 'default' id + * Returns id of device from the list * * @param devices list of available devices * @param inputList list of registered audio/video devices in order of preference - * @param [fallbackId] id of currently selected input - * @return first available (plugged) device id or fallback + * @return {string|undefined} first available (plugged) device id */ -function getFirstAvailableMediaDevice(devices: MediaDeviceInfo[], inputList: MediaDeviceInfo[], fallbackId?: string): string | undefined { - const availableDevices = devices.map(device => device.deviceId).filter(id => id !== 'default') - return inputList.find(device => availableDevices.includes(device.deviceId))?.deviceId ?? fallbackId +function getFirstAvailableMediaDevice(devices: MediaDeviceInfo[], inputList: MediaDeviceInfo[]): string | undefined { + return inputList.find(device => devices.some(d => d.kind === device.kind && d.deviceId === device.deviceId))?.deviceId } /** @@ -75,20 +89,11 @@ function getFirstAvailableMediaDevice(devices: MediaDeviceInfo[], inputList: Med * * @param device device * @param devicesList list of registered devices in order of preference - * @param promote whether device should be promoted (to be used in updateMediaDevicesPreferences) - * @return updated devices list + * @return {MediaDeviceInfo[]} updated devices list */ -function registerNewMediaDevice(device: MediaDeviceInfo, devicesList: MediaDeviceInfo[], promote: boolean = false): MediaDeviceInfo[] { - const newDevicesList = devicesList.slice() +function registerNewMediaDevice(device: MediaDeviceInfo, devicesList: MediaDeviceInfo[]): MediaDeviceInfo[] { console.debug('Registering new device:', device) - - if (promote) { - newDevicesList.unshift(device) - } else { - newDevicesList.push(device) - } - - return newDevicesList + return [...devicesList, device] } /** @@ -102,43 +107,44 @@ function registerNewMediaDevice(device: MediaDeviceInfo, devicesList: MediaDevic * * Returns changed preference lists for audio / video devices (null, if it hasn't been changed) * + * @param kind kind of device * @param devices list of available devices * @param inputList list of registered audio/video devices in order of preference * @param inputId id of currently selected input - * @return updated devices list (null, if it has not been changed) + * @return {InputListUpdated} updated devices list (null, if it has not been changed) */ -function promoteMediaDevice(devices: MediaDeviceInfo[], inputList: MediaDeviceInfo[], inputId: string | null) { - const newInputList = inputList.slice() +function promoteMediaDevice(kind: DeviceKind, devices: MediaDeviceInfo[], inputList: MediaDeviceInfo[], inputId: InputId): InputListUpdated { + if (!inputId) { + return null + } // Get the index of the first plugged device - const availableDevices = devices.map(device => device.deviceId).filter(id => id !== 'default') - const firstPluggedIndex = newInputList.findIndex(device => availableDevices.includes(device.deviceId)) - const insertPosition = firstPluggedIndex === -1 ? newInputList.length : firstPluggedIndex + const availableDevices = devices.filter(device => device.kind === kind) + const deviceToPromote = availableDevices.find(device => device.deviceId === inputId) + if (!deviceToPromote) { + return null + } + + const firstPluggedIndex = inputList.findIndex(device => availableDevices.some(d => d.deviceId === device.deviceId)) + const insertPosition = firstPluggedIndex === -1 ? inputList.length : firstPluggedIndex // Get the index of the currently selected device - const currentDevicePosition = newInputList.findIndex(device => device.deviceId === inputId) + const currentDevicePosition = inputList.findIndex(device => device.deviceId === inputId) if (currentDevicePosition === insertPosition) { // preferences list is unchanged return null } - let deviceToPromote = null - if (currentDevicePosition === -1 && inputId !== 'default' && inputId !== null) { - // If device was not registered in preferences list, get it from devices list - deviceToPromote = devices.find(device => device.deviceId === inputId) - } else if (currentDevicePosition > 0) { - // Otherwise extract it from preferences list - deviceToPromote = newInputList.splice(currentDevicePosition, 1)[0] - } + const newInputList = inputList.slice() - if (deviceToPromote) { - // Put the device at the new position - newInputList.splice(insertPosition, 0, deviceToPromote) - return newInputList - } else { - return null + if (currentDevicePosition > 0) { + // Extract promoted device it from preferences list + newInputList.splice(currentDevicePosition, 1) } + + newInputList.splice(insertPosition, 0, deviceToPromote) + return newInputList } /** @@ -149,22 +155,22 @@ function promoteMediaDevice(devices: MediaDeviceInfo[], inputList: MediaDeviceIn * @param devices list of available devices * @param audioInputList list of registered audio devices in order of preference * @param videoInputList list of registered video devices in order of preference - * @return object with updated devices lists (null, if they have not been changed) + * @return {InputLists} object with updated devices lists (null, if they have not been changed) */ -function populateMediaDevicesPreferences(devices: MediaDeviceInfo[], audioInputList: MediaDeviceInfo[], videoInputList: MediaDeviceInfo[]) { +function populateMediaDevicesPreferences(devices: MediaDeviceInfo[], audioInputList: MediaDeviceInfo[], videoInputList: MediaDeviceInfo[]): InputLists { let newAudioInputList = null let newVideoInputList = null for (const device of devices) { - if (device.kind === 'audioinput') { + if (device.deviceId && device.kind === DeviceKind.AudioInput) { // Add to the list of known devices - if (device.deviceId !== 'default' && !audioInputList.some(input => input.deviceId === device.deviceId)) { - newAudioInputList = registerNewMediaDevice(device, audioInputList) + if (!audioInputList.some(input => input.deviceId === device.deviceId)) { + newAudioInputList = registerNewMediaDevice(device, newAudioInputList ?? audioInputList) } - } else if (device.kind === 'videoinput') { + } else if (device.deviceId && device.kind === DeviceKind.VideoInput) { // Add to the list of known devices - if (device.deviceId !== 'default' && !videoInputList.some(input => input.deviceId === device.deviceId)) { - newVideoInputList = registerNewMediaDevice(device, videoInputList) + if (!videoInputList.some(input => input.deviceId === device.deviceId)) { + newVideoInputList = registerNewMediaDevice(device, newVideoInputList ?? videoInputList) } } } @@ -181,16 +187,15 @@ function populateMediaDevicesPreferences(devices: MediaDeviceInfo[], audioInputL * * Returns changed preference lists for audio / video devices (null, if it hasn't been changed) * - * @param devices list of available devices - * @param audioInputId id of currently selected audio input - * @param videoInputId id of currently selected video input + * @param attributes MediaDeviceManager attributes * @param audioInputList list of registered audio devices in order of preference * @param videoInputList list of registered video devices in order of preference + * @return {InputLists} object with updated devices lists (null, if they have not been changed) */ -function updateMediaDevicesPreferences(devices: MediaDeviceInfo[], audioInputId: string, videoInputId: string, audioInputList: MediaDeviceInfo[], videoInputList: MediaDeviceInfo[]) { +function updateMediaDevicesPreferences(attributes: Attributes, audioInputList: MediaDeviceInfo[], videoInputList: MediaDeviceInfo[]): InputLists { return { - newAudioInputList: promoteMediaDevice(devices, audioInputList, audioInputId), - newVideoInputList: promoteMediaDevice(devices, videoInputList, videoInputId), + newAudioInputList: promoteMediaDevice(DeviceKind.AudioInput, attributes.devices, audioInputList, attributes.audioInputId), + newVideoInputList: promoteMediaDevice(DeviceKind.VideoInput, attributes.devices, videoInputList, attributes.videoInputId), } } diff --git a/src/utils/webrtc/MediaDevicesManager.js b/src/utils/webrtc/MediaDevicesManager.js index 5bbc20fdb81..ef3b3917b28 100644 --- a/src/utils/webrtc/MediaDevicesManager.js +++ b/src/utils/webrtc/MediaDevicesManager.js @@ -94,9 +94,6 @@ export default function MediaDevicesManager() { this._knownDevices = {} - this._fallbackAudioInputId = undefined - this._fallbackVideoInputId = undefined - const audioInputPreferences = BrowserStorage.getItem('audioInputPreferences') this._preferenceAudioInputList = audioInputPreferences !== null ? JSON.parse(audioInputPreferences) : [] @@ -191,6 +188,8 @@ MediaDevicesManager.prototype = { this._pendingEnumerateDevicesPromise = navigator.mediaDevices.enumerateDevices().then(devices => { const previousAudioInputId = this.attributes.audioInputId const previousVideoInputId = this.attributes.videoInputId + const previousFirstAvailableAudioInputId = getFirstAvailableMediaDevice(this.attributes.devices, this._preferenceAudioInputList) + const previousFirstAvailableVideoInputId = getFirstAvailableMediaDevice(this.attributes.devices, this._preferenceVideoInputList) const removedDevices = this.attributes.devices.filter(oldDevice => !devices.find(device => oldDevice.deviceId === device.deviceId && oldDevice.kind === device.kind)) const updatedDevices = devices.filter(device => this.attributes.devices.find(oldDevice => device.deviceId === oldDevice.deviceId && device.kind === oldDevice.kind)) @@ -206,20 +205,15 @@ MediaDevicesManager.prototype = { this._addDevice(addedDevice) }) - // Fallback in case we didn't find the previously picked device - if (this.attributes.audioInputId === undefined) { - if (BrowserStorage.getItem('audioInputId')) { - // Couldn't find device by id - console.debug('Could not find previous audio device, falling back to default/first device in the list', BrowserStorage.getItem('audioInputId'), this.attributes.devices) - } - this.attributes.audioInputId = getFirstAvailableMediaDevice(devices, this._preferenceAudioInputList, this._fallbackAudioInputId) ?? 'default' + // Selecting preferred device in case it was removed/unplugged, or it is a first initialization after reload, + // or we add/plug preferred device and overwriting automatic selection + if (this.attributes.audioInputId === undefined || this.attributes.audioInputId === previousFirstAvailableAudioInputId) { + this.attributes.audioInputId = getFirstAvailableMediaDevice(devices, this._preferenceAudioInputList) + console.debug(listMediaDevices(this.attributes, this._preferenceAudioInputList, this._preferenceVideoInputList)) } - if (this.attributes.videoInputId === undefined) { - if (BrowserStorage.getItem('videoInputId')) { - // Couldn't find device by id, try the label - console.debug('Could not find previous video device, falling back to default/first device in the list', BrowserStorage.getItem('videoInputId'), this.attributes.devices) - } - this.attributes.videoInputId = getFirstAvailableMediaDevice(devices, this._preferenceVideoInputList, this._fallbackVideoInputId) ?? 'default' + if (this.attributes.videoInputId === undefined || this.attributes.videoInputId === previousFirstAvailableVideoInputId) { + this.attributes.videoInputId = getFirstAvailableMediaDevice(devices, this._preferenceVideoInputList) + console.debug(listMediaDevices(this.attributes, this._preferenceAudioInputList, this._preferenceVideoInputList)) } // Trigger change events after all the devices are processed to @@ -260,9 +254,7 @@ MediaDevicesManager.prototype = { updatePreferences() { const { newAudioInputList, newVideoInputList } = updateMediaDevicesPreferences( - this.attributes.devices, - this.attributes.audioInputId, - this.attributes.videoInputId, + this.attributes, this._preferenceAudioInputList, this._preferenceVideoInputList, ) @@ -282,15 +274,17 @@ MediaDevicesManager.prototype = { * Show whether device is currently unplugged or selected, if information is available */ listDevices() { - navigator.mediaDevices.enumerateDevices().then(devices => { - listMediaDevices( - devices, - this.attributes.audioInputId, - this.attributes.videoInputId, - this._preferenceAudioInputList, - this._preferenceVideoInputList, - ) - }) + if (this.attributes.devices.length) { + console.info(listMediaDevices(this.attributes, this._preferenceAudioInputList, this._preferenceVideoInputList)) + } else { + navigator.mediaDevices.enumerateDevices().then(devices => { + console.info(listMediaDevices( + { devices, audioInputId: this.attributes.audioInputId, videoInputId: this.attributes.videoInputId }, + this._preferenceAudioInputList, + this._preferenceVideoInputList, + )) + }) + } }, _removeDevice(removedDevice) { @@ -298,21 +292,10 @@ MediaDevicesManager.prototype = { if (removedDeviceIndex >= 0) { this.attributes.devices.splice(removedDeviceIndex, 1) } - - if (removedDevice.kind === 'audioinput') { - if (this._fallbackAudioInputId === removedDevice.deviceId) { - this._fallbackAudioInputId = getFirstAvailableMediaDevice(this.attributes.devices, this._preferenceAudioInputList, undefined) - } - if (this.attributes.audioInputId === removedDevice.deviceId) { - this.attributes.audioInputId = getFirstAvailableMediaDevice(this.attributes.devices, this._preferenceAudioInputList, this._fallbackAudioInputId) - } - } else if (removedDevice.kind === 'videoinput') { - if (this._fallbackVideoInputId === removedDevice.deviceId) { - this._fallbackVideoInputId = getFirstAvailableMediaDevice(this.attributes.devices, this._preferenceVideoInputList, undefined) - } - if (this.attributes.videoInputId === removedDevice.deviceId) { - this.attributes.videoInputId = getFirstAvailableMediaDevice(this.attributes.devices, this._preferenceVideoInputList, this._fallbackVideoInputId) - } + if (removedDevice.kind === 'audioinput' && removedDevice.deviceId === this.attributes.audioInputId) { + this.attributes.audioInputId = undefined + } else if (removedDevice.kind === 'videoinput' && removedDevice.deviceId === this.attributes.videoInputId) { + this.attributes.videoInputId = undefined } }, @@ -362,28 +345,6 @@ MediaDevicesManager.prototype = { // Always refresh the known device with the latest values. this._knownDevices[addedDevice.kind + '-' + addedDevice.deviceId] = addedDevice - - // Restore previously selected device if it becomes available again. - // Additionally, set first available device as fallback, and override - // any fallback previously set if the default device is added. - if (addedDevice.kind === 'audioinput') { - if (BrowserStorage.getItem('audioInputId') === addedDevice.deviceId - || getFirstAvailableMediaDevice(this.attributes.devices, this._preferenceAudioInputList, this._fallbackAudioInputId)) { - this.attributes.audioInputId = addedDevice.deviceId - } - if (!this._fallbackAudioInputId || addedDevice.deviceId === 'default') { - this._fallbackAudioInputId = addedDevice.deviceId - } - } else if (addedDevice.kind === 'videoinput') { - if (BrowserStorage.getItem('videoInputId') === addedDevice.deviceId - || getFirstAvailableMediaDevice(this.attributes.devices, this._preferenceVideoInputList, this._fallbackVideoInputId)) { - this.attributes.videoInputId = addedDevice.deviceId - } - if (!this._fallbackVideoInputId || addedDevice.deviceId === 'default') { - this._fallbackVideoInputId = addedDevice.deviceId - } - } - this.attributes.devices.push(addedDevice) },