Преглед изворни кода

fix(device-selection): Add a workaround for a chrome bug with default mic

Pass the real deviceId to gUM instead of 'default' for Chrome to return the correct media stream
j8
Jaya Allamsetty пре 4 година
родитељ
комит
f4bcad02d8
2 измењених фајлова са 62 додато и 14 уклоњено
  1. 33
    2
      conference.js
  2. 29
    12
      react/features/base/devices/functions.js

+ 33
- 2
conference.js Прегледај датотеку

@@ -48,6 +48,7 @@ import {
48 48
 import {
49 49
     checkAndNotifyForNewDevice,
50 50
     getAvailableDevices,
51
+    getDefaultDeviceId,
51 52
     notifyCameraError,
52 53
     notifyMicError,
53 54
     setAudioOutputDeviceId,
@@ -2434,11 +2435,20 @@ export default {
2434 2435
             micDeviceId => {
2435 2436
                 const audioWasMuted = this.isLocalAudioMuted();
2436 2437
 
2438
+                // When the 'default' mic needs to be selected, we need to
2439
+                // pass the real device id to gUM instead of 'default' in order
2440
+                // to get the correct MediaStreamTrack from chrome because of the
2441
+                // following bug.
2442
+                // https://bugs.chromium.org/p/chromium/issues/detail?id=997689
2443
+                const hasDefaultMicChanged = micDeviceId === 'default';
2444
+
2437 2445
                 sendAnalytics(createDeviceChangedEvent('audio', 'input'));
2438 2446
                 createLocalTracksF({
2439 2447
                     devices: [ 'audio' ],
2440 2448
                     cameraDeviceId: null,
2441
-                    micDeviceId
2449
+                    micDeviceId: hasDefaultMicChanged
2450
+                        ? getDefaultDeviceId(APP.store.getState(), 'audioInput')
2451
+                        : micDeviceId
2442 2452
                 })
2443 2453
                 .then(([ stream ]) => {
2444 2454
                     // if audio was muted before changing the device, mute
@@ -2462,6 +2472,12 @@ export default {
2462 2472
                     return this.useAudioStream(stream);
2463 2473
                 })
2464 2474
                 .then(() => {
2475
+                    if (hasDefaultMicChanged) {
2476
+                        // workaround for the default device to be shown as selected in the
2477
+                        // settings even when the real device id was passed to gUM because of the
2478
+                        // above mentioned chrome bug.
2479
+                        this.localAudio._realDeviceId = this.localAudio.deviceId = 'default';
2480
+                    }
2465 2481
                     logger.log(`switched local audio device: ${this.localAudio?.getDeviceId()}`);
2466 2482
 
2467 2483
                     this._updateAudioDeviceId();
@@ -2763,11 +2779,20 @@ export default {
2763 2779
                 checkAndNotifyForNewDevice(newAvailDevices.videoInput, oldDevices.videoInput));
2764 2780
         }
2765 2781
 
2782
+        // When the 'default' mic needs to be selected, we need to
2783
+        // pass the real device id to gUM instead of 'default' in order
2784
+        // to get the correct MediaStreamTrack from chrome because of the
2785
+        // following bug.
2786
+        // https://bugs.chromium.org/p/chromium/issues/detail?id=997689
2787
+        const hasDefaultMicChanged = newDevices.audioinput === 'default';
2788
+
2766 2789
         promises.push(
2767 2790
             mediaDeviceHelper.createLocalTracksAfterDeviceListChanged(
2768 2791
                     createLocalTracksF,
2769 2792
                     newDevices.videoinput,
2770
-                    newDevices.audioinput)
2793
+                    hasDefaultMicChanged
2794
+                        ? getDefaultDeviceId(APP.store.getState(), 'audioInput')
2795
+                        : newDevices.audioinput)
2771 2796
                 .then(tracks => {
2772 2797
                     // If audio or video muted before, or we unplugged current
2773 2798
                     // device and selected new one, then mute new track.
@@ -2792,6 +2817,12 @@ export default {
2792 2817
                                     // Use the new stream or null if we failed to obtain it.
2793 2818
                                     return useStream(tracks.find(track => track.getType() === mediaType) || null)
2794 2819
                                         .then(() => {
2820
+                                            if (hasDefaultMicChanged) {
2821
+                                                // workaround for the default device to be shown as selected in the
2822
+                                                // settings even when the real device id was passed to gUM because of
2823
+                                                // the above mentioned chrome bug.
2824
+                                                this.localAudio._realDeviceId = this.localAudio.deviceId = 'default';
2825
+                                            }
2795 2826
                                             mediaType === 'audio'
2796 2827
                                                 ? this._updateAudioDeviceId()
2797 2828
                                                 : this._updateVideoDeviceId();

+ 29
- 12
react/features/base/devices/functions.js Прегледај датотеку

@@ -8,6 +8,12 @@ import logger from './logger';
8 8
 
9 9
 declare var APP: Object;
10 10
 
11
+const webrtcKindToJitsiKindTranslator = {
12
+    audioinput: 'audioInput',
13
+    audiooutput: 'audioOutput',
14
+    videoinput: 'videoInput'
15
+};
16
+
11 17
 /**
12 18
  * Detects the use case when the labels are not available if the A/V permissions
13 19
  * are not yet granted.
@@ -41,6 +47,29 @@ export function getAudioOutputDeviceId() {
41 47
     return JitsiMeetJS.mediaDevices.getAudioOutputDevice();
42 48
 }
43 49
 
50
+/**
51
+ * Finds the real device id of the default device of the given type.
52
+ *
53
+ * @param {Object} state - The redux state.
54
+ * @param {*} kind - The type of the device. One of "audioInput",
55
+ * "audioOutput", and "videoInput". Also supported is all lowercase versions
56
+ * of the preceding types.
57
+ * @returns {string|undefined}
58
+ */
59
+export function getDefaultDeviceId(state: Object, kind: string) {
60
+    const kindToSearch = webrtcKindToJitsiKindTranslator[kind] || kind;
61
+    const defaultDevice = (state['features/base/devices'].availableDevices[kindToSearch] || [])
62
+        .find(d => d.deviceId === 'default');
63
+
64
+    // Find the device with a matching group id.
65
+    const matchingDevice = (state['features/base/devices'].availableDevices[kindToSearch] || [])
66
+        .find(d => d.deviceId !== 'default' && d.groupId === defaultDevice.groupId);
67
+
68
+    if (matchingDevice) {
69
+        return matchingDevice.deviceId;
70
+    }
71
+}
72
+
44 73
 /**
45 74
  * Finds a device with a label that matches the passed label and returns its id.
46 75
  *
@@ -52,12 +81,6 @@ export function getAudioOutputDeviceId() {
52 81
  * @returns {string|undefined}
53 82
  */
54 83
 export function getDeviceIdByLabel(state: Object, label: string, kind: string) {
55
-    const webrtcKindToJitsiKindTranslator = {
56
-        audioinput: 'audioInput',
57
-        audiooutput: 'audioOutput',
58
-        videoinput: 'videoInput'
59
-    };
60
-
61 84
     const kindToSearch = webrtcKindToJitsiKindTranslator[kind] || kind;
62 85
 
63 86
     const device
@@ -80,12 +103,6 @@ export function getDeviceIdByLabel(state: Object, label: string, kind: string) {
80 103
  * @returns {string|undefined}
81 104
  */
82 105
 export function getDeviceLabelById(state: Object, id: string, kind: string) {
83
-    const webrtcKindToJitsiKindTranslator = {
84
-        audioinput: 'audioInput',
85
-        audiooutput: 'audioOutput',
86
-        videoinput: 'videoInput'
87
-    };
88
-
89 106
     const kindToSearch = webrtcKindToJitsiKindTranslator[kind] || kind;
90 107
 
91 108
     const device

Loading…
Откажи
Сачувај