Browse Source

Merge pull request #793 from saghul/refactor-devices-poll

feat(RTC): refactor logic for polling for device changes
tags/v0.0.2
Saúl Ibarra Corretgé 7 years ago
parent
commit
3b489998e2
No account linked to committer's email address
2 changed files with 48 additions and 83 deletions
  1. 40
    83
      modules/RTC/RTCUtils.js
  2. 8
    0
      modules/browser/BrowserCapabilities.js

+ 40
- 83
modules/RTC/RTCUtils.js View File

107
     = typeof featureDetectionAudioEl.setSinkId !== 'undefined';
107
     = typeof featureDetectionAudioEl.setSinkId !== 'undefined';
108
 
108
 
109
 let availableDevices;
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
  * @param constraints
136
  * @param constraints
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
  * Sends analytics event with the passed device list.
541
  * Sends analytics event with the passed device list.
583
  *
542
  *
899
             logger.info(`Disable HPF: ${disableHPF}`);
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
         if (browser.usesNewGumFlow()) {
867
         if (browser.usesNewGumFlow()) {
906
             this.RTCPeerConnectionType = window.RTCPeerConnection;
868
             this.RTCPeerConnectionType = window.RTCPeerConnection;
919
                             return Promise.reject(err);
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
             this.attachMediaStream
884
             this.attachMediaStream
938
                 = wrapAttachMediaStream((element, stream) => {
885
                 = wrapAttachMediaStream((element, stream) => {
939
                     if (element) {
886
                     if (element) {
955
 
902
 
956
             this.getUserMedia = wrapGetUserMedia(getUserMedia);
903
             this.getUserMedia = wrapGetUserMedia(getUserMedia);
957
 
904
 
958
-            this.enumerateDevices = rawEnumerateDevicesWithCallback;
959
-
960
             this.attachMediaStream
905
             this.attachMediaStream
961
                 = wrapAttachMediaStream((element, stream) => {
906
                 = wrapAttachMediaStream((element, stream) => {
962
                     defaultSetVideoSrc(element, stream);
907
                     defaultSetVideoSrc(element, stream);
995
                     navigator.mediaDevices.getUserMedia.bind(
940
                     navigator.mediaDevices.getUserMedia.bind(
996
                         navigator.mediaDevices),
941
                         navigator.mediaDevices),
997
                     true);
942
                     true);
998
-            this.enumerateDevices = rawEnumerateDevicesWithCallback;
999
             this.attachMediaStream
943
             this.attachMediaStream
1000
                 = wrapAttachMediaStream((element, stream) => {
944
                 = wrapAttachMediaStream((element, stream) => {
1001
                     defaultSetVideoSrc(element, stream);
945
                     defaultSetVideoSrc(element, stream);
1030
             options,
974
             options,
1031
             this.getUserMediaWithConstraints.bind(this));
975
             this.getUserMediaWithConstraints.bind(this));
1032
 
976
 
1033
-        if (this.isDeviceListAvailable() && rawEnumerateDevicesWithCallback) {
1034
-            rawEnumerateDevicesWithCallback(ds => {
977
+        if (this.isDeviceListAvailable()) {
978
+            this.enumerateDevices(ds => {
1035
                 availableDevices = ds.splice(0);
979
                 availableDevices = ds.splice(0);
1036
 
980
 
1037
                 logger.debug('Available devices: ', availableDevices);
981
                 logger.debug('Available devices: ', availableDevices);
1041
                     RTCEvents.DEVICE_LIST_AVAILABLE,
985
                     RTCEvents.DEVICE_LIST_AVAILABLE,
1042
                     availableDevices);
986
                     availableDevices);
1043
 
987
 
1044
-                if (isDeviceChangeEventSupported) {
988
+                if (browser.supportsDeviceChangeEvent()) {
1045
                     navigator.mediaDevices.addEventListener(
989
                     navigator.mediaDevices.addEventListener(
1046
                         'devicechange',
990
                         'devicechange',
1047
                         () => this.enumerateDevices(onMediaDevicesListChanged));
991
                         () => this.enumerateDevices(onMediaDevicesListChanged));
1048
                 } else {
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 View File

105
         return !this.isEdge();
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
      * Checks if the current browser supports the MediaStream constructor as
118
      * Checks if the current browser supports the MediaStream constructor as

Loading…
Cancel
Save