|
@@ -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
|
}
|