|
@@ -26,7 +26,9 @@ var devices = {
|
26
|
26
|
|
27
|
27
|
var audioOuputDeviceId = ''; // default device
|
28
|
28
|
|
29
|
|
-var featureDetectionVideoEl = document.createElement('video');
|
|
29
|
+var featureDetectionAudioEl = document.createElement('audio');
|
|
30
|
+var isAudioOutputDeviceChangeAvailable =
|
|
31
|
+ typeof featureDetectionAudioEl.setSinkId !== 'undefined';
|
30
|
32
|
|
31
|
33
|
var rtcReady = false;
|
32
|
34
|
|
|
@@ -338,9 +340,12 @@ function enumerateDevicesThroughMediaStreamTrack (callback) {
|
338
|
340
|
return {
|
339
|
341
|
facing: source.facing || null,
|
340
|
342
|
label: source.label,
|
341
|
|
- // theoretically deprecated MediaStreamTrack.getSources should not return 'audiooutput' devices but
|
342
|
|
- // let's handle it in any case
|
343
|
|
- kind: kind ? (kind === 'audiooutput' ? kind : kind + 'input') : null,
|
|
343
|
+ // theoretically deprecated MediaStreamTrack.getSources should
|
|
344
|
+ // not return 'audiooutput' devices but let's handle it in any
|
|
345
|
+ // case
|
|
346
|
+ kind: kind
|
|
347
|
+ ? (kind === 'audiooutput' ? kind : kind + 'input')
|
|
348
|
+ : null,
|
344
|
349
|
deviceId: source.id,
|
345
|
350
|
groupId: source.groupId || null
|
346
|
351
|
};
|
|
@@ -462,10 +467,11 @@ function wrapAttachMediaStream(origAttachMediaStream) {
|
462
|
467
|
return function(element, stream) {
|
463
|
468
|
var res = origAttachMediaStream.apply(RTCUtils, arguments);
|
464
|
469
|
|
465
|
|
- if (RTCUtils.isAudioOutputDeviceChangeAvailable()) {
|
|
470
|
+ if (RTCUtils.isDeviceChangeAvailable('output') &&
|
|
471
|
+ stream.getAudioTracks && stream.getAudioTracks().length) {
|
466
|
472
|
element.setSinkId(RTCUtils.getAudioOutputDevice())
|
467
|
473
|
.catch(function (ex) {
|
468
|
|
- console.error('Failed to set audio output on element',
|
|
474
|
+ logger.error('Failed to set audio output on element',
|
469
|
475
|
element, ex);
|
470
|
476
|
});
|
471
|
477
|
}
|
|
@@ -847,21 +853,19 @@ var RTCUtils = {
|
847
|
853
|
return (MediaStreamTrack && MediaStreamTrack.getSources)? true : false;
|
848
|
854
|
},
|
849
|
855
|
/**
|
850
|
|
- * Returns true if changing the camera / microphone device is supported and
|
851
|
|
- * false if not.
|
852
|
|
- */
|
853
|
|
- isDeviceChangeAvailable: function () {
|
854
|
|
- return RTCBrowserType.isChrome() ||
|
855
|
|
- RTCBrowserType.isFirefox() ||
|
856
|
|
- RTCBrowserType.isOpera() ||
|
857
|
|
- RTCBrowserType.isTemasysPluginUsed();
|
858
|
|
- },
|
859
|
|
- /**
|
860
|
|
- * Returns true if changing the audio output of media elements is supported
|
861
|
|
- * and false if not.
|
|
856
|
+ * Returns true if changing the input (camera / microphone) or output
|
|
857
|
+ * (audio) device is supported and false if not.
|
|
858
|
+ * @params {string} [deviceType] - type of device to change. Default is
|
|
859
|
+ * undefined or 'input', 'output' - for audio output device change.
|
|
860
|
+ * @returns {boolean} true if available, false otherwise.
|
862
|
861
|
*/
|
863
|
|
- isAudioOutputDeviceChangeAvailable: function () {
|
864
|
|
- return typeof featureDetectionVideoEl.setSinkId !== 'undefined';
|
|
862
|
+ isDeviceChangeAvailable: function (deviceType) {
|
|
863
|
+ return deviceType === 'output' || deviceType === 'audiooutput'
|
|
864
|
+ ? isAudioOutputDeviceChangeAvailable
|
|
865
|
+ : RTCBrowserType.isChrome() ||
|
|
866
|
+ RTCBrowserType.isFirefox() ||
|
|
867
|
+ RTCBrowserType.isOpera() ||
|
|
868
|
+ RTCBrowserType.isTemasysPluginUsed();
|
865
|
869
|
},
|
866
|
870
|
/**
|
867
|
871
|
* A method to handle stopping of the stream.
|
|
@@ -896,20 +900,22 @@ var RTCUtils = {
|
896
|
900
|
/**
|
897
|
901
|
* Sets current audio output device.
|
898
|
902
|
* @param {string} deviceId - id of 'audiooutput' device from
|
899
|
|
- * navigator.mediaDevices.enumerateDevices()
|
|
903
|
+ * navigator.mediaDevices.enumerateDevices(), '' for default device
|
900
|
904
|
* @returns {Promise} - resolves when audio output is changed, is rejected
|
901
|
905
|
* otherwise
|
902
|
906
|
*/
|
903
|
907
|
setAudioOutputDevice: function (deviceId) {
|
904
|
|
- if (!this.isAudioOutputDeviceChangeAvailable()) {
|
|
908
|
+ if (!this.isDeviceChangeAvailable('output')) {
|
905
|
909
|
Promise.reject(
|
906
|
910
|
new Error('Audio output device change is not supported'));
|
907
|
911
|
}
|
908
|
|
-
|
909
|
|
- return featureDetectionVideoEl.setSinkId(deviceId)
|
|
912
|
+
|
|
913
|
+ return featureDetectionAudioEl.setSinkId(deviceId)
|
910
|
914
|
.then(function() {
|
911
|
915
|
audioOuputDeviceId = deviceId;
|
912
|
916
|
|
|
917
|
+ logger.log('Audio output device set to ' + deviceId);
|
|
918
|
+
|
913
|
919
|
eventEmitter.emit(RTCEvents.AUDIO_OUTPUT_DEVICE_CHANGED,
|
914
|
920
|
deviceId);
|
915
|
921
|
});
|