Bladeren bron

fix(api-devices): Initial device function calls

j8
Hristo Terezov 6 jaren geleden
bovenliggende
commit
ed1d3d3df5

+ 16
- 0
doc/api.md Bestand weergeven

@@ -29,6 +29,7 @@ Its constructor gets a number of options:
29 29
     * **jwt**: (optional) [JWT](https://jwt.io/) token.
30 30
     * **onload**: (optional) handler for the iframe onload event.
31 31
     * **invitees**: (optional) Array of objects containing information about new participants that will be invited in the call.
32
+    * **devices**: (optional) A map containing information about the initial devices that will be used in the call.
32 33
 
33 34
 Example:
34 35
 
@@ -43,6 +44,21 @@ var options = {
43 44
 var api = new JitsiMeetExternalAPI(domain, options);
44 45
 ```
45 46
 
47
+You can set the initial media devices for the call:
48
+
49
+```javascript
50
+var domain = "meet.jit.si";
51
+var options = {
52
+    ...
53
+    devices: {
54
+        'audioInput': '<device_id>',
55
+        'audioOutput': '<device_id>',
56
+        'videoInput': '<device_id>'
57
+    }
58
+}
59
+var api = new JitsiMeetExternalAPI(domain, options);
60
+```
61
+
46 62
 You can overwrite options set in [config.js] and [interface_config.js].
47 63
 For example, to enable the filmstrip-only interface mode, you can use:
48 64
 

+ 6
- 2
modules/API/external/external_api.js Bestand weergeven

@@ -221,6 +221,8 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
221 221
      * for iframe onload event.
222 222
      * @param {Array<Object>} [options.invitees] - Array of objects containing
223 223
      * information about new participants that will be invited in the call.
224
+     * @param {Array<Object>} [options.devices] - Array of objects containing
225
+     * information about the initial devices that will be used in the call.
224 226
      */
225 227
     constructor(domain, ...args) {
226 228
         super();
@@ -234,7 +236,8 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
234 236
             noSSL = false,
235 237
             jwt = undefined,
236 238
             onload = undefined,
237
-            invitees
239
+            invitees,
240
+            devices
238 241
         } = parseArguments(args);
239 242
 
240 243
         this._parentNode = parentNode;
@@ -243,7 +246,8 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
243 246
             interfaceConfigOverwrite,
244 247
             jwt,
245 248
             noSSL,
246
-            roomName
249
+            roomName,
250
+            devices
247 251
         });
248 252
         this._createIFrame(height, width, onload);
249 253
         this._transport = new Transport({

+ 9
- 6
react/features/base/connection/actions.web.js Bestand weergeven

@@ -7,6 +7,8 @@ declare var config: Object;
7 7
 
8 8
 const logger = require('jitsi-meet-logger').getLogger(__filename);
9 9
 
10
+import { configureInitialDevices } from '../devices';
11
+
10 12
 export {
11 13
     connectionEstablished,
12 14
     connectionFailed,
@@ -25,12 +27,13 @@ export function connect() {
25 27
 
26 28
         // XXX For web based version we use conference initialization logic
27 29
         // from the old app (at the moment of writing).
28
-        return APP.conference.init({
29
-            roomName: room
30
-        }).catch(error => {
31
-            APP.API.notifyConferenceLeft(APP.conference.roomName);
32
-            logger.error(error);
33
-        });
30
+        return dispatch(configureInitialDevices()).then(
31
+            () => APP.conference.init({
32
+                roomName: room
33
+            }).catch(error => {
34
+                APP.API.notifyConferenceLeft(APP.conference.roomName);
35
+                logger.error(error);
36
+            }));
34 37
     };
35 38
 }
36 39
 

+ 21
- 0
react/features/base/devices/actions.js Bestand weergeven

@@ -1,10 +1,12 @@
1 1
 import JitsiMeetJS from '../lib-jitsi-meet';
2
+import { updateSettings } from '../settings';
2 3
 
3 4
 import {
4 5
     SET_AUDIO_INPUT_DEVICE,
5 6
     SET_VIDEO_INPUT_DEVICE,
6 7
     UPDATE_DEVICE_LIST
7 8
 } from './actionTypes';
9
+import { getDevicesFromURL } from './functions';
8 10
 
9 11
 /**
10 12
  * Queries for connected A/V input and output devices and updates the redux
@@ -77,3 +79,22 @@ export function updateDeviceList(devices) {
77 79
         devices
78 80
     };
79 81
 }
82
+
83
+/**
84
+ * Configures the initial A/V devices before the conference has started.
85
+ *
86
+ * @returns {Function}
87
+ */
88
+export function configureInitialDevices() {
89
+    return (dispatch, getState) => new Promise(resolve => {
90
+        const devices = getDevicesFromURL(getState());
91
+
92
+        if (devices) {
93
+            dispatch(updateSettings({
94
+                ...devices
95
+            }));
96
+            resolve();
97
+        }
98
+    });
99
+}
100
+

+ 45
- 0
react/features/base/devices/functions.js Bestand weergeven

@@ -1,5 +1,6 @@
1 1
 // @flow
2 2
 
3
+import { parseURLParams } from '../config';
3 4
 import JitsiMeetJS from '../lib-jitsi-meet';
4 5
 import { updateSettings } from '../settings';
5 6
 
@@ -30,3 +31,47 @@ export function setAudioOutputDeviceId(
30 31
                 audioOutputDeviceId: newId
31 32
             })));
32 33
 }
34
+
35
+/**
36
+ * Converts an array of media devices into an object organized by device kind.
37
+ *
38
+ * @param {Array<MediaDeviceInfo>} devices - Available media devices.
39
+ * @private
40
+ * @returns {Object} An object with the media devices split by type. The keys
41
+ * are device type and the values are arrays with devices matching the device
42
+ * type.
43
+ */
44
+export function groupDevicesByKind(devices: Object[]): Object {
45
+    return {
46
+        audioInput: devices.filter(device => device.kind === 'audioinput'),
47
+        audioOutput: devices.filter(device => device.kind === 'audiooutput'),
48
+        videoInput: devices.filter(device => device.kind === 'videoinput')
49
+    };
50
+}
51
+
52
+/**
53
+ * Returns the devices set in the URL.
54
+ *
55
+ * @param {Object} state - The redux state.
56
+ * @returns {Object|undefined}
57
+ */
58
+export function getDevicesFromURL(state: Object) {
59
+    const urlParams
60
+        = parseURLParams(state['features/base/connection'].locationURL);
61
+
62
+    const audioOutputDeviceId = urlParams['devices.audioOutput'];
63
+    const cameraDeviceId = urlParams['devices.videoInput'];
64
+    const micDeviceId = urlParams['devices.audioInput'];
65
+
66
+    if (!audioOutputDeviceId && !cameraDeviceId && !micDeviceId) {
67
+        return undefined;
68
+    }
69
+
70
+    const devices = {};
71
+
72
+    audioOutputDeviceId && (devices.audioOutputDeviceId = audioOutputDeviceId);
73
+    cameraDeviceId && (devices.cameraDeviceId = cameraDeviceId);
74
+    micDeviceId && (devices.micDeviceId = micDeviceId);
75
+
76
+    return devices;
77
+}

+ 2
- 17
react/features/base/devices/reducer.js Bestand weergeven

@@ -3,6 +3,7 @@ import {
3 3
     SET_VIDEO_INPUT_DEVICE,
4 4
     UPDATE_DEVICE_LIST
5 5
 } from './actionTypes';
6
+import { groupDevicesByKind } from './functions';
6 7
 
7 8
 import { ReducerRegistry } from '../redux';
8 9
 
@@ -27,7 +28,7 @@ ReducerRegistry.register(
27 28
     (state = DEFAULT_STATE, action) => {
28 29
         switch (action.type) {
29 30
         case UPDATE_DEVICE_LIST: {
30
-            const deviceList = _groupDevicesByKind(action.devices);
31
+            const deviceList = groupDevicesByKind(action.devices);
31 32
 
32 33
             return {
33 34
                 ...deviceList
@@ -44,19 +45,3 @@ ReducerRegistry.register(
44 45
         }
45 46
     });
46 47
 
47
-/**
48
- * Converts an array of media devices into an object organized by device kind.
49
- *
50
- * @param {Array<MediaDeviceInfo>} devices - Available media devices.
51
- * @private
52
- * @returns {Object} An object with the media devices split by type. The keys
53
- * are device type and the values are arrays with devices matching the device
54
- * type.
55
- */
56
-function _groupDevicesByKind(devices) {
57
-    return {
58
-        audioInput: devices.filter(device => device.kind === 'audioinput'),
59
-        audioOutput: devices.filter(device => device.kind === 'audiooutput'),
60
-        videoInput: devices.filter(device => device.kind === 'videoinput')
61
-    };
62
-}

+ 5
- 5
react/features/base/util/uri.js Bestand weergeven

@@ -469,16 +469,16 @@ export function urlObjectToString(o: Object): ?string {
469 469
 
470 470
     let { hash } = url;
471 471
 
472
-    for (const configName of [ 'config', 'interfaceConfig' ]) {
472
+    for (const urlPrefix of [ 'config', 'interfaceConfig', 'devices' ]) {
473 473
         const urlParamsArray
474 474
             = _objectToURLParamsArray(
475
-                o[`${configName}Overwrite`]
476
-                    || o[configName]
477
-                    || o[`${configName}Override`]);
475
+                o[`${urlPrefix}Overwrite`]
476
+                    || o[urlPrefix]
477
+                    || o[`${urlPrefix}Override`]);
478 478
 
479 479
         if (urlParamsArray.length) {
480 480
             let urlParamsString
481
-                = `${configName}.${urlParamsArray.join(`&${configName}.`)}`;
481
+                = `${urlPrefix}.${urlParamsArray.join(`&${urlPrefix}.`)}`;
482 482
 
483 483
             if (hash.length) {
484 484
                 urlParamsString = `&${urlParamsString}`;

+ 11
- 3
react/features/device-selection/functions.js Bestand weergeven

@@ -1,6 +1,8 @@
1 1
 // @flow
2 2
 import {
3 3
     getAudioOutputDeviceId,
4
+    getAvailableDevices,
5
+    groupDevicesByKind,
4 6
     setAudioInputDevice,
5 7
     setAudioOutputDeviceId,
6 8
     setVideoInputDevice
@@ -46,7 +48,11 @@ export function getDeviceSelectionDialogProps(stateful: Object | Function) {
46 48
  * response.
47 49
  * @returns {boolean}
48 50
  */
49
-export function processRequest(dispatch: Dispatch<*>, getState: Function, request: Object, responseCallback: Function) { // eslint-disable-line max-len, max-params
51
+export function processRequest( // eslint-disable-line max-params
52
+        dispatch: Dispatch<*>,
53
+        getState: Function,
54
+        request: Object,
55
+        responseCallback: Function) {
50 56
     if (request.type === 'devices') {
51 57
         const state = getState();
52 58
         const settings = state['features/base/settings'];
@@ -71,7 +77,9 @@ export function processRequest(dispatch: Dispatch<*>, getState: Function, reques
71 77
             });
72 78
             break;
73 79
         case 'getAvailableDevices':
74
-            responseCallback(getState()['features/base/devices']);
80
+            dispatch(getAvailableDevices()).then(
81
+                devices => responseCallback(groupDevicesByKind(devices)));
82
+
75 83
             break;
76 84
         case 'setDevice': {
77 85
             const { device } = request;
@@ -87,7 +95,7 @@ export function processRequest(dispatch: Dispatch<*>, getState: Function, reques
87 95
                 dispatch(setVideoInputDevice(device.id));
88 96
                 break;
89 97
             default:
90
-
98
+                responseCallback(false);
91 99
             }
92 100
 
93 101
             responseCallback(true);

Laden…
Annuleren
Opslaan