浏览代码

feat(RTC): refactor logic for polling for device changes

- Don't use it on supported browsers
- Make sure no stray timers are left
dev1
Saúl Ibarra Corretgé 7 年前
父节点
当前提交
a4f58e6042
共有 2 个文件被更改,包括 48 次插入83 次删除
  1. 40
    83
      modules/RTC/RTCUtils.js
  2. 8
    0
      modules/browser/BrowserCapabilities.js

+ 40
- 83
modules/RTC/RTCUtils.js 查看文件

@@ -107,45 +107,30 @@ const isAudioOutputDeviceChangeAvailable
107 107
     = typeof featureDetectionAudioEl.setSinkId !== 'undefined';
108 108
 
109 109
 let availableDevices;
110
+let availableDevicesPollTimer;
110 111
 
111 112
 /**
112
- * "rawEnumerateDevicesWithCallback" will be initialized only after WebRTC is
113
- * ready. Otherwise it is too early to assume that the devices listing is not
114
- * supported.
115
- */
116
-let rawEnumerateDevicesWithCallback;
117
-
118
-/**
119
- * Initialize {@link rawEnumerateDevicesWithCallback}.
113
+ * Initialize wrapper function for enumerating devices.
114
+ *
115
+ * @returns {?Function}
120 116
  */
121
-function initRawEnumerateDevicesWithCallback() {
122
-    rawEnumerateDevicesWithCallback
123
-        = navigator.mediaDevices && navigator.mediaDevices.enumerateDevices
124
-            ? function(callback) {
125
-                navigator.mediaDevices.enumerateDevices().then(
126
-                    callback,
127
-                    () => callback([]));
128
-            }
117
+function initEnumerateDevicesWithCallback() {
118
+    if (navigator.mediaDevices && navigator.mediaDevices.enumerateDevices) {
119
+        return callback => {
120
+            navigator.mediaDevices.enumerateDevices()
121
+                .then(callback, () => callback([]));
122
+        };
123
+    }
129 124
 
130
-            // react-native-webrtc
131
-            : function(callback) {
132
-                MediaStreamTrack.getSources(
133
-                    sources =>
134
-                        callback(sources.map(convertMediaStreamTrackSource)));
135
-            };
125
+    if (MediaStreamTrack.getSources) { // react-native-webrtc
126
+        return callback => {
127
+            MediaStreamTrack.getSources(
128
+                sources =>
129
+                    callback(sources.map(convertMediaStreamTrackSource)));
130
+        };
131
+    }
136 132
 }
137 133
 
138
-// TODO: currently no browser supports 'devicechange' event even in nightly
139
-// builds so no feature/browser detection is used at all. However in future this
140
-// should be changed to some expression. Progress on 'devicechange' event
141
-// implementation for Chrome/Opera/NWJS can be tracked at
142
-// https://bugs.chromium.org/p/chromium/issues/detail?id=388648, for Firefox -
143
-// at https://bugzilla.mozilla.org/show_bug.cgi?id=1152383. More information on
144
-// 'devicechange' event can be found in spec -
145
-// http://w3c.github.io/mediacapture-main/#event-mediadevices-devicechange
146
-// TODO: check MS Edge
147
-const isDeviceChangeEventSupported = false;
148
-
149 134
 /**
150 135
  *
151 136
  * @param constraints
@@ -552,32 +537,6 @@ function compareAvailableMediaDevices(newDevices) {
552 537
     }
553 538
 }
554 539
 
555
-/**
556
- * Periodically polls enumerateDevices() method to check if list of media
557
- * devices has changed. This is temporary workaround until 'devicechange' event
558
- * will be supported by browsers.
559
- */
560
-function pollForAvailableMediaDevices() {
561
-    // Here we use plain navigator.mediaDevices.enumerateDevices instead of
562
-    // wrapped because we just need to know the fact the devices changed, labels
563
-    // do not matter. This fixes situation when we have no devices initially,
564
-    // and then plug in a new one.
565
-    if (rawEnumerateDevicesWithCallback) {
566
-        rawEnumerateDevicesWithCallback(ds => {
567
-            // We don't fire RTCEvents.DEVICE_LIST_CHANGED for the first time
568
-            // we call enumerateDevices(). This is the initial step.
569
-            if (typeof availableDevices === 'undefined') {
570
-                availableDevices = ds.slice(0);
571
-            } else if (compareAvailableMediaDevices(ds)) {
572
-                onMediaDevicesListChanged(ds);
573
-            }
574
-
575
-            window.setTimeout(pollForAvailableMediaDevices,
576
-                AVAILABLE_DEVICES_POLL_INTERVAL_TIME);
577
-        });
578
-    }
579
-}
580
-
581 540
 /**
582 541
  * Sends analytics event with the passed device list.
583 542
  *
@@ -899,8 +858,11 @@ class RTCUtils extends Listenable {
899 858
             logger.info(`Disable HPF: ${disableHPF}`);
900 859
         }
901 860
 
902
-        // Initialize rawEnumerateDevicesWithCallback
903
-        initRawEnumerateDevicesWithCallback();
861
+        availableDevices = undefined;
862
+        window.clearInterval(availableDevicesPollTimer);
863
+        availableDevicesPollTimer = undefined;
864
+
865
+        this.enumerateDevices = initEnumerateDevicesWithCallback();
904 866
 
905 867
         if (browser.usesNewGumFlow()) {
906 868
             this.RTCPeerConnectionType = window.RTCPeerConnection;
@@ -919,21 +881,6 @@ class RTCUtils extends Listenable {
919 881
                             return Promise.reject(err);
920 882
                         });
921 883
 
922
-            this.enumerateDevices = callback =>
923
-                window.navigator.mediaDevices.enumerateDevices()
924
-                    .then(foundDevices => {
925
-                        callback(foundDevices);
926
-
927
-                        return foundDevices;
928
-                    })
929
-                    .catch(err => {
930
-                        logger.error(`Error enumerating devices: ${err}`);
931
-
932
-                        callback([]);
933
-
934
-                        return [];
935
-                    });
936
-
937 884
             this.attachMediaStream
938 885
                 = wrapAttachMediaStream((element, stream) => {
939 886
                     if (element) {
@@ -955,8 +902,6 @@ class RTCUtils extends Listenable {
955 902
 
956 903
             this.getUserMedia = wrapGetUserMedia(getUserMedia);
957 904
 
958
-            this.enumerateDevices = rawEnumerateDevicesWithCallback;
959
-
960 905
             this.attachMediaStream
961 906
                 = wrapAttachMediaStream((element, stream) => {
962 907
                     defaultSetVideoSrc(element, stream);
@@ -995,7 +940,6 @@ class RTCUtils extends Listenable {
995 940
                     navigator.mediaDevices.getUserMedia.bind(
996 941
                         navigator.mediaDevices),
997 942
                     true);
998
-            this.enumerateDevices = rawEnumerateDevicesWithCallback;
999 943
             this.attachMediaStream
1000 944
                 = wrapAttachMediaStream((element, stream) => {
1001 945
                     defaultSetVideoSrc(element, stream);
@@ -1030,8 +974,8 @@ class RTCUtils extends Listenable {
1030 974
             options,
1031 975
             this.getUserMediaWithConstraints.bind(this));
1032 976
 
1033
-        if (this.isDeviceListAvailable() && rawEnumerateDevicesWithCallback) {
1034
-            rawEnumerateDevicesWithCallback(ds => {
977
+        if (this.isDeviceListAvailable()) {
978
+            this.enumerateDevices(ds => {
1035 979
                 availableDevices = ds.splice(0);
1036 980
 
1037 981
                 logger.debug('Available devices: ', availableDevices);
@@ -1041,12 +985,25 @@ class RTCUtils extends Listenable {
1041 985
                     RTCEvents.DEVICE_LIST_AVAILABLE,
1042 986
                     availableDevices);
1043 987
 
1044
-                if (isDeviceChangeEventSupported) {
988
+                if (browser.supportsDeviceChangeEvent()) {
1045 989
                     navigator.mediaDevices.addEventListener(
1046 990
                         'devicechange',
1047 991
                         () => this.enumerateDevices(onMediaDevicesListChanged));
1048 992
                 } else {
1049
-                    pollForAvailableMediaDevices();
993
+                    // Periodically poll enumerateDevices() method to check if
994
+                    // list of media devices has changed.
995
+                    availableDevicesPollTimer = window.setInterval(() => {
996
+                        this.enumerateDevices(pds => {
997
+                            // We don't fire RTCEvents.DEVICE_LIST_CHANGED for
998
+                            // the first time we call enumerateDevices().
999
+                            // This is the initial step.
1000
+                            if (typeof availableDevices === 'undefined') {
1001
+                                availableDevices = pds.slice(0);
1002
+                            } else if (compareAvailableMediaDevices(pds)) {
1003
+                                onMediaDevicesListChanged(pds);
1004
+                            }
1005
+                        });
1006
+                    }, AVAILABLE_DEVICES_POLL_INTERVAL_TIME);
1050 1007
                 }
1051 1008
             });
1052 1009
         }

+ 8
- 0
modules/browser/BrowserCapabilities.js 查看文件

@@ -105,6 +105,14 @@ export default class BrowserCapabilities extends BrowserDetection {
105 105
         return !this.isEdge();
106 106
     }
107 107
 
108
+    /**
109
+     * Checks if the current browser support the device change event.
110
+     * @return {boolean}
111
+     */
112
+    supportsDeviceChangeEvent() {
113
+        return navigator.mediaDevices
114
+            && typeof navigator.mediaDevices.ondevicechange !== 'undefined';
115
+    }
108 116
 
109 117
     /**
110 118
      * Checks if the current browser supports the MediaStream constructor as

正在加载...
取消
保存