ref(iframe-api-devices): Use labels instead of IDs
This commit is contained in:
parent
ed1d3d3df5
commit
4967488e56
26
doc/api.md
26
doc/api.md
|
@ -51,9 +51,9 @@ var domain = "meet.jit.si";
|
|||
var options = {
|
||||
...
|
||||
devices: {
|
||||
'audioInput': '<device_id>',
|
||||
'audioOutput': '<device_id>',
|
||||
'videoInput': '<device_id>'
|
||||
'audioInput': '<deviceLabel>',
|
||||
'audioOutput': '<deviceLabel>',
|
||||
'videoInput': '<deviceLabel>'
|
||||
}
|
||||
}
|
||||
var api = new JitsiMeetExternalAPI(domain, options);
|
||||
|
@ -109,14 +109,14 @@ api.getAvailableDevices().then(function(devices) {
|
|||
...
|
||||
});
|
||||
```
|
||||
* **getCurrentDevices** - Retrieve a list with the devices that are currently sected.
|
||||
* **getCurrentDevices** - Retrieve a list with the devices that are currently selected.
|
||||
|
||||
```javascript
|
||||
api.getCurrentDevices().then(function(devices) {
|
||||
// devices = {
|
||||
// 'audioInput': 'deviceID',
|
||||
// 'audioOutput': 'deviceID',
|
||||
// 'videoInput': 'deviceID'
|
||||
// 'audioInput': 'deviceLabel',
|
||||
// 'audioOutput': 'deviceLabel',
|
||||
// 'videoInput': 'deviceLabel'
|
||||
// }
|
||||
...
|
||||
});
|
||||
|
@ -143,20 +143,20 @@ api.isMultipleAudioInputSupported().then(function(isMultipleAudioInputSupported)
|
|||
...
|
||||
});
|
||||
```
|
||||
* **setAudioInputDevice** - Sets the audio input device to the one with the id that is passed.
|
||||
* **setAudioInputDevice** - Sets the audio input device to the one with the label that is passed.
|
||||
|
||||
```javascript
|
||||
api.setAudioInputDevice(deviceId);
|
||||
api.setAudioInputDevice(deviceLabel);
|
||||
```
|
||||
* **setAudioOutputDevice** - Sets the audio output device to the one with the id that is passed.
|
||||
* **setAudioOutputDevice** - Sets the audio output device to the one with the label that is passed.
|
||||
|
||||
```javascript
|
||||
api.setAudioOutputDevice(deviceId);
|
||||
api.setAudioOutputDevice(deviceLabel);
|
||||
```
|
||||
* **setVideoInputDevice** - Sets the video input device to the one with the id that is passed.
|
||||
* **setVideoInputDevice** - Sets the video input device to the one with the label that is passed.
|
||||
|
||||
```javascript
|
||||
api.setVideoInputDevice(deviceId);
|
||||
api.setVideoInputDevice(deviceLabel);
|
||||
```
|
||||
|
||||
You can control the embedded Jitsi Meet conference using the `JitsiMeetExternalAPI` object by using `executeCommand`:
|
||||
|
|
|
@ -105,12 +105,12 @@ export function isMultipleAudioInputSupported(transport: Object) {
|
|||
*
|
||||
* @param {Transport} transport - The @code{Transport} instance responsible for
|
||||
* the external communication.
|
||||
* @param {string} id - The id of the new device.
|
||||
* @param {string} label - The label of the new device.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export function setAudioInputDevice(transport: Object, id: string) {
|
||||
export function setAudioInputDevice(transport: Object, label: string) {
|
||||
return _setDevice(transport, {
|
||||
id,
|
||||
label,
|
||||
kind: 'audioinput'
|
||||
});
|
||||
}
|
||||
|
@ -120,12 +120,12 @@ export function setAudioInputDevice(transport: Object, id: string) {
|
|||
*
|
||||
* @param {Transport} transport - The @code{Transport} instance responsible for
|
||||
* the external communication.
|
||||
* @param {string} id - The id of the new device.
|
||||
* @param {string} label - The label of the new device.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export function setAudioOutputDevice(transport: Object, id: string) {
|
||||
export function setAudioOutputDevice(transport: Object, label: string) {
|
||||
return _setDevice(transport, {
|
||||
id,
|
||||
label,
|
||||
kind: 'audiooutput'
|
||||
});
|
||||
}
|
||||
|
@ -151,12 +151,12 @@ function _setDevice(transport: Object, device) {
|
|||
*
|
||||
* @param {Transport} transport - The @code{Transport} instance responsible for
|
||||
* the external communication.
|
||||
* @param {string} id - The id of the new device.
|
||||
* @param {string} label - The label of the new device.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export function setVideoInputDevice(transport: Object, id: string) {
|
||||
export function setVideoInputDevice(transport: Object, label: string) {
|
||||
return _setDevice(transport, {
|
||||
id,
|
||||
label,
|
||||
kind: 'videoinput'
|
||||
});
|
||||
}
|
||||
|
|
|
@ -30,3 +30,24 @@ export const SET_VIDEO_INPUT_DEVICE = 'SET_VIDEO_INPUT_DEVICE';
|
|||
* }
|
||||
*/
|
||||
export const UPDATE_DEVICE_LIST = 'UPDATE_DEVICE_LIST';
|
||||
|
||||
/**
|
||||
* The type of Redux action which will add a pending device requests that will
|
||||
* be executed later when it is possible (when the conference is joined).
|
||||
*
|
||||
* {
|
||||
* type: ADD_PENDING_DEVICE_REQUEST,
|
||||
* request: Object
|
||||
* }
|
||||
*/
|
||||
export const ADD_PENDING_DEVICE_REQUEST = 'ADD_PENDING_DEVICE_REQUEST';
|
||||
|
||||
/**
|
||||
* The type of Redux action which will remove all pending device requests.
|
||||
*
|
||||
* {
|
||||
* type: REMOVE_PENDING_DEVICE_REQUESTS,
|
||||
* request: Object
|
||||
* }
|
||||
*/
|
||||
export const REMOVE_PENDING_DEVICE_REQUESTS = 'REMOVE_PENDING_DEVICE_REQUESTS';
|
||||
|
|
|
@ -2,11 +2,92 @@ import JitsiMeetJS from '../lib-jitsi-meet';
|
|||
import { updateSettings } from '../settings';
|
||||
|
||||
import {
|
||||
ADD_PENDING_DEVICE_REQUEST,
|
||||
REMOVE_PENDING_DEVICE_REQUESTS,
|
||||
SET_AUDIO_INPUT_DEVICE,
|
||||
SET_VIDEO_INPUT_DEVICE,
|
||||
UPDATE_DEVICE_LIST
|
||||
} from './actionTypes';
|
||||
import { getDevicesFromURL } from './functions';
|
||||
import {
|
||||
areDeviceLabelsInitialized,
|
||||
getDeviceIdByLabel,
|
||||
getDevicesFromURL
|
||||
} from './functions';
|
||||
|
||||
/**
|
||||
* Adds a pending device request.
|
||||
*
|
||||
* @param {Object} request - The request to be added.
|
||||
* @returns {{
|
||||
* type: ADD_PENDING_DEVICE_REQUEST,
|
||||
* request: Object
|
||||
* }}
|
||||
*/
|
||||
export function addPendingDeviceRequest(request) {
|
||||
return {
|
||||
type: ADD_PENDING_DEVICE_REQUEST,
|
||||
request
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the initial A/V devices before the conference has started.
|
||||
*
|
||||
* @returns {Function}
|
||||
*/
|
||||
export function configureInitialDevices() {
|
||||
return (dispatch, getState) => new Promise(resolve => {
|
||||
const deviceLabels = getDevicesFromURL(getState());
|
||||
|
||||
if (deviceLabels) {
|
||||
dispatch(getAvailableDevices()).then(() => {
|
||||
const state = getState();
|
||||
|
||||
if (!areDeviceLabelsInitialized(state)) {
|
||||
// The labels are not available if the A/V permissions are
|
||||
// not yet granted.
|
||||
|
||||
Object.keys(deviceLabels).forEach(key => {
|
||||
dispatch(addPendingDeviceRequest({
|
||||
type: 'devices',
|
||||
name: 'setDevice',
|
||||
device: {
|
||||
kind: key.toLowerCase(),
|
||||
label: deviceLabels[key]
|
||||
},
|
||||
// eslint-disable-next-line no-empty-function
|
||||
responseCallback() {}
|
||||
}));
|
||||
});
|
||||
resolve();
|
||||
|
||||
return;
|
||||
}
|
||||
const newSettings = {};
|
||||
const devicesKeysToSettingsKeys = {
|
||||
audioInput: 'micDeviceId',
|
||||
audioOutput: 'audioOutputDeviceId',
|
||||
videoInput: 'cameraDeviceId'
|
||||
};
|
||||
|
||||
Object.keys(deviceLabels).forEach(key => {
|
||||
const label = deviceLabels[key];
|
||||
const deviceId = getDeviceIdByLabel(state, label);
|
||||
|
||||
if (deviceId) {
|
||||
newSettings[devicesKeysToSettingsKeys[key]] = deviceId;
|
||||
}
|
||||
});
|
||||
|
||||
dispatch(updateSettings(newSettings));
|
||||
resolve();
|
||||
});
|
||||
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries for connected A/V input and output devices and updates the redux
|
||||
|
@ -31,6 +112,20 @@ export function getAvailableDevices() {
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove all pending device requests.
|
||||
*
|
||||
* @returns {{
|
||||
* type: REMOVE_PENDING_DEVICE_REQUESTS
|
||||
* }}
|
||||
*/
|
||||
export function removePendingDeviceRequests() {
|
||||
return {
|
||||
type: REMOVE_PENDING_DEVICE_REQUESTS
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Signals to update the currently used audio input device.
|
||||
*
|
||||
|
@ -80,21 +175,3 @@ export function updateDeviceList(devices) {
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the initial A/V devices before the conference has started.
|
||||
*
|
||||
* @returns {Function}
|
||||
*/
|
||||
export function configureInitialDevices() {
|
||||
return (dispatch, getState) => new Promise(resolve => {
|
||||
const devices = getDevicesFromURL(getState());
|
||||
|
||||
if (devices) {
|
||||
dispatch(updateSettings({
|
||||
...devices
|
||||
}));
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,30 @@ import { parseURLParams } from '../config';
|
|||
import JitsiMeetJS from '../lib-jitsi-meet';
|
||||
import { updateSettings } from '../settings';
|
||||
|
||||
declare var APP: Object;
|
||||
|
||||
/**
|
||||
* Detects the use case when the labels are not available if the A/V permissions
|
||||
* are not yet granted.
|
||||
*
|
||||
* @param {Object} state - The redux state.
|
||||
* @returns {boolean} - True if the labels are already initialized and false
|
||||
* otherwise.
|
||||
*/
|
||||
export function areDeviceLabelsInitialized(state: Object) {
|
||||
if (APP.conference._localTracksInitialized) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (const type of [ 'audioInput', 'audioOutput', 'videoInput' ]) {
|
||||
if (state['features/base/devices'][type].find(d => Boolean(d.label))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get device id of the audio output device which is currently in use.
|
||||
* Empty string stands for default device.
|
||||
|
@ -15,21 +39,50 @@ export function getAudioOutputDeviceId() {
|
|||
}
|
||||
|
||||
/**
|
||||
* Set device id of the audio output device which is currently in use.
|
||||
* Empty string stands for default device.
|
||||
* Finds a device with a label that matches the passed label and returns its id.
|
||||
*
|
||||
* @param {string} newId - New audio output device id.
|
||||
* @param {Function} dispatch - The Redux dispatch function.
|
||||
* @returns {Promise}
|
||||
* @param {Object} state - The redux state.
|
||||
* @param {string} label - The label.
|
||||
* @returns {string|undefined}
|
||||
*/
|
||||
export function setAudioOutputDeviceId(
|
||||
newId: string = 'default',
|
||||
dispatch: Function): Promise<*> {
|
||||
return JitsiMeetJS.mediaDevices.setAudioOutputDevice(newId)
|
||||
.then(() =>
|
||||
dispatch(updateSettings({
|
||||
audioOutputDeviceId: newId
|
||||
})));
|
||||
export function getDeviceIdByLabel(state: Object, label: string) {
|
||||
const types = [ 'audioInput', 'audioOutput', 'videoInput' ];
|
||||
|
||||
for (const type of types) {
|
||||
const device
|
||||
= state['features/base/devices'][type].find(d => d.label === label);
|
||||
|
||||
if (device) {
|
||||
return device.deviceId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the devices set in the URL.
|
||||
*
|
||||
* @param {Object} state - The redux state.
|
||||
* @returns {Object|undefined}
|
||||
*/
|
||||
export function getDevicesFromURL(state: Object) {
|
||||
const urlParams
|
||||
= parseURLParams(state['features/base/connection'].locationURL);
|
||||
|
||||
const audioOutput = urlParams['devices.audioOutput'];
|
||||
const videoInput = urlParams['devices.videoInput'];
|
||||
const audioInput = urlParams['devices.audioInput'];
|
||||
|
||||
if (!audioOutput && !videoInput && !audioInput) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const devices = {};
|
||||
|
||||
audioOutput && (devices.audioOutput = audioOutput);
|
||||
videoInput && (devices.videoInput = videoInput);
|
||||
audioInput && (devices.audioInput = audioInput);
|
||||
|
||||
return devices;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -50,28 +103,19 @@ export function groupDevicesByKind(devices: Object[]): Object {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the devices set in the URL.
|
||||
* Set device id of the audio output device which is currently in use.
|
||||
* Empty string stands for default device.
|
||||
*
|
||||
* @param {Object} state - The redux state.
|
||||
* @returns {Object|undefined}
|
||||
* @param {string} newId - New audio output device id.
|
||||
* @param {Function} dispatch - The Redux dispatch function.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export function getDevicesFromURL(state: Object) {
|
||||
const urlParams
|
||||
= parseURLParams(state['features/base/connection'].locationURL);
|
||||
|
||||
const audioOutputDeviceId = urlParams['devices.audioOutput'];
|
||||
const cameraDeviceId = urlParams['devices.videoInput'];
|
||||
const micDeviceId = urlParams['devices.audioInput'];
|
||||
|
||||
if (!audioOutputDeviceId && !cameraDeviceId && !micDeviceId) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const devices = {};
|
||||
|
||||
audioOutputDeviceId && (devices.audioOutputDeviceId = audioOutputDeviceId);
|
||||
cameraDeviceId && (devices.cameraDeviceId = cameraDeviceId);
|
||||
micDeviceId && (devices.micDeviceId = micDeviceId);
|
||||
|
||||
return devices;
|
||||
export function setAudioOutputDeviceId(
|
||||
newId: string = 'default',
|
||||
dispatch: Function): Promise<*> {
|
||||
return JitsiMeetJS.mediaDevices.setAudioOutputDevice(newId)
|
||||
.then(() =>
|
||||
dispatch(updateSettings({
|
||||
audioOutputDeviceId: newId
|
||||
})));
|
||||
}
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
/* global APP */
|
||||
|
||||
import { CONFERENCE_JOINED } from '../conference';
|
||||
import { processRequest } from '../../device-selection';
|
||||
import { MiddlewareRegistry } from '../redux';
|
||||
import UIEvents from '../../../../service/UI/UIEvents';
|
||||
|
||||
import { MiddlewareRegistry } from '../redux';
|
||||
|
||||
import { removePendingDeviceRequests } from './actions';
|
||||
import {
|
||||
SET_AUDIO_INPUT_DEVICE,
|
||||
SET_VIDEO_INPUT_DEVICE
|
||||
|
@ -18,6 +20,8 @@ import {
|
|||
// eslint-disable-next-line no-unused-vars
|
||||
MiddlewareRegistry.register(store => next => action => {
|
||||
switch (action.type) {
|
||||
case CONFERENCE_JOINED:
|
||||
return _conferenceJoined(store, next, action);
|
||||
case SET_AUDIO_INPUT_DEVICE:
|
||||
APP.UI.emitEvent(UIEvents.AUDIO_DEVICE_CHANGED, action.deviceId);
|
||||
break;
|
||||
|
@ -28,3 +32,34 @@ MiddlewareRegistry.register(store => next => action => {
|
|||
|
||||
return next(action);
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Does extra sync up on properties that may need to be updated after the
|
||||
* conference was joined.
|
||||
*
|
||||
* @param {Store} store - The redux store in which the specified {@code action}
|
||||
* is being dispatched.
|
||||
* @param {Dispatch} next - The redux {@code dispatch} function to dispatch the
|
||||
* specified {@code action} to the specified {@code store}.
|
||||
* @param {Action} action - The redux action {@code CONFERENCE_JOINED} which is
|
||||
* being dispatched in the specified {@code store}.
|
||||
* @private
|
||||
* @returns {Object} The value returned by {@code next(action)}.
|
||||
*/
|
||||
function _conferenceJoined({ dispatch, getState }, next, action) {
|
||||
const result = next(action);
|
||||
const state = getState();
|
||||
const { pendingRequests } = state['features/base/devices'];
|
||||
|
||||
pendingRequests.forEach(request => {
|
||||
processRequest(
|
||||
dispatch,
|
||||
getState,
|
||||
request,
|
||||
request.responseCallback);
|
||||
});
|
||||
dispatch(removePendingDeviceRequests());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
import {
|
||||
ADD_PENDING_DEVICE_REQUEST,
|
||||
REMOVE_PENDING_DEVICE_REQUESTS,
|
||||
SET_AUDIO_INPUT_DEVICE,
|
||||
SET_VIDEO_INPUT_DEVICE,
|
||||
UPDATE_DEVICE_LIST
|
||||
|
@ -10,7 +12,8 @@ import { ReducerRegistry } from '../redux';
|
|||
const DEFAULT_STATE = {
|
||||
audioInput: [],
|
||||
audioOutput: [],
|
||||
videoInput: []
|
||||
videoInput: [],
|
||||
pendingRequests: []
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -31,10 +34,26 @@ ReducerRegistry.register(
|
|||
const deviceList = groupDevicesByKind(action.devices);
|
||||
|
||||
return {
|
||||
pendingRequests: state.pendingRequests,
|
||||
...deviceList
|
||||
};
|
||||
}
|
||||
|
||||
case ADD_PENDING_DEVICE_REQUEST:
|
||||
return {
|
||||
...state,
|
||||
pendingRequests: [
|
||||
...state.pendingRequests,
|
||||
action.request
|
||||
]
|
||||
};
|
||||
|
||||
case REMOVE_PENDING_DEVICE_REQUESTS:
|
||||
return {
|
||||
...state,
|
||||
pendingRequests: [ ]
|
||||
};
|
||||
|
||||
// TODO: Changing of current audio and video device id is currently
|
||||
// handled outside of react/redux. Fall through to default logic for
|
||||
// now.
|
||||
|
|
|
@ -1,7 +1,13 @@
|
|||
// @flow
|
||||
|
||||
import type { Dispatch } from 'redux';
|
||||
|
||||
import {
|
||||
addPendingDeviceRequest,
|
||||
areDeviceLabelsInitialized,
|
||||
getAudioOutputDeviceId,
|
||||
getAvailableDevices,
|
||||
getDeviceIdByLabel,
|
||||
groupDevicesByKind,
|
||||
setAudioInputDevice,
|
||||
setAudioOutputDeviceId,
|
||||
|
@ -49,13 +55,15 @@ export function getDeviceSelectionDialogProps(stateful: Object | Function) {
|
|||
* @returns {boolean}
|
||||
*/
|
||||
export function processRequest( // eslint-disable-line max-params
|
||||
dispatch: Dispatch<*>,
|
||||
dispatch: Dispatch<any>,
|
||||
getState: Function,
|
||||
request: Object,
|
||||
responseCallback: Function) {
|
||||
if (request.type === 'devices') {
|
||||
const state = getState();
|
||||
const settings = state['features/base/settings'];
|
||||
const { conference } = state['features/base/conference'];
|
||||
let result = true;
|
||||
|
||||
switch (request.name) {
|
||||
case 'isDeviceListAvailable':
|
||||
|
@ -70,35 +78,95 @@ export function processRequest( // eslint-disable-line max-params
|
|||
responseCallback(JitsiMeetJS.isMultipleAudioInputSupported());
|
||||
break;
|
||||
case 'getCurrentDevices':
|
||||
responseCallback({
|
||||
audioInput: settings.micDeviceId,
|
||||
audioOutput: getAudioOutputDeviceId(),
|
||||
videoInput: settings.cameraDeviceId
|
||||
dispatch(getAvailableDevices()).then(devices => {
|
||||
if (areDeviceLabelsInitialized(state)) {
|
||||
let audioInput, audioOutput, videoInput;
|
||||
const audioOutputDeviceId = getAudioOutputDeviceId();
|
||||
const { cameraDeviceId, micDeviceId } = settings;
|
||||
|
||||
devices.forEach(({ deviceId, label }) => {
|
||||
switch (deviceId) {
|
||||
case micDeviceId:
|
||||
audioInput = label;
|
||||
break;
|
||||
case audioOutputDeviceId:
|
||||
audioOutput = label;
|
||||
break;
|
||||
case cameraDeviceId:
|
||||
videoInput = label;
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
responseCallback({
|
||||
audioInput,
|
||||
audioOutput,
|
||||
videoInput
|
||||
});
|
||||
} else {
|
||||
// The labels are not available if the A/V permissions are
|
||||
// not yet granted.
|
||||
dispatch(addPendingDeviceRequest({
|
||||
type: 'devices',
|
||||
name: 'getCurrentDevices',
|
||||
responseCallback
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
||||
break;
|
||||
case 'getAvailableDevices':
|
||||
dispatch(getAvailableDevices()).then(
|
||||
devices => responseCallback(groupDevicesByKind(devices)));
|
||||
dispatch(getAvailableDevices()).then(devices => {
|
||||
if (areDeviceLabelsInitialized(state)) {
|
||||
responseCallback(groupDevicesByKind(devices));
|
||||
} else {
|
||||
// The labels are not available if the A/V permissions are
|
||||
// not yet granted.
|
||||
dispatch(addPendingDeviceRequest({
|
||||
type: 'devices',
|
||||
name: 'getAvailableDevices',
|
||||
responseCallback
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
||||
break;
|
||||
case 'setDevice': {
|
||||
const { device } = request;
|
||||
|
||||
switch (device.kind) {
|
||||
case 'audioinput':
|
||||
dispatch(setAudioInputDevice(device.id));
|
||||
break;
|
||||
case 'audiooutput':
|
||||
setAudioOutputDeviceId(device.id, dispatch);
|
||||
break;
|
||||
case 'videoinput':
|
||||
dispatch(setVideoInputDevice(device.id));
|
||||
break;
|
||||
default:
|
||||
responseCallback(false);
|
||||
if (!conference) {
|
||||
dispatch(addPendingDeviceRequest({
|
||||
type: 'devices',
|
||||
name: 'setDevice',
|
||||
device,
|
||||
responseCallback
|
||||
}));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
responseCallback(true);
|
||||
const deviceId = getDeviceIdByLabel(state, device.label);
|
||||
|
||||
if (deviceId) {
|
||||
switch (device.kind) {
|
||||
case 'audioinput': {
|
||||
dispatch(setAudioInputDevice(deviceId));
|
||||
break;
|
||||
}
|
||||
case 'audiooutput':
|
||||
setAudioOutputDeviceId(deviceId, dispatch);
|
||||
break;
|
||||
case 'videoinput':
|
||||
dispatch(setVideoInputDevice(deviceId));
|
||||
break;
|
||||
default:
|
||||
result = false;
|
||||
}
|
||||
} else {
|
||||
result = false;
|
||||
}
|
||||
|
||||
responseCallback(result);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
|
Loading…
Reference in New Issue