Skip to content

Commit 86ba3f1

Browse files
authored
Merge pull request #1689 from markafoltz/add-devicechange
Add ondevicechange event support to demo
2 parents 45187d9 + a5a78cb commit 86ba3f1

File tree

1 file changed

+53
-11
lines changed
  • src/content/devices/input-output/js

1 file changed

+53
-11
lines changed

src/content/devices/input-output/js/main.js

Lines changed: 53 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,23 @@ const audioInputSelect = document.querySelector('select#audioSource');
1313
const audioOutputSelect = document.querySelector('select#audioOutput');
1414
const videoSelect = document.querySelector('select#videoSource');
1515
const selectors = [audioInputSelect, audioOutputSelect, videoSelect];
16+
let hasMic = false;
17+
let hasCamera = false;
18+
let openMic = undefined;
19+
let openCamera = undefined;
20+
let hasPermission = false;
1621

1722
audioOutputSelect.disabled = !('sinkId' in HTMLMediaElement.prototype);
1823

24+
function getDevices() {
25+
navigator.mediaDevices.enumerateDevices().then(gotDevices).catch(handleError);
26+
}
27+
1928
function gotDevices(deviceInfos) {
29+
console.log('gotDevices', deviceInfos);
30+
hasMic = false;
31+
hasCamera = false;
32+
hasPermission = false;
2033
// Handles being called several times to update labels. Preserve values.
2134
const values = selectors.map(select => select.value);
2235
selectors.forEach(select => {
@@ -26,15 +39,23 @@ function gotDevices(deviceInfos) {
2639
});
2740
for (let i = 0; i !== deviceInfos.length; ++i) {
2841
const deviceInfo = deviceInfos[i];
42+
if (deviceInfo.deviceId == '') {
43+
continue;
44+
}
45+
// If we get at least one deviceId, that means user has granted user
46+
// media permissions.
47+
hasPermission = true;
2948
const option = document.createElement('option');
3049
option.value = deviceInfo.deviceId;
3150
if (deviceInfo.kind === 'audioinput') {
51+
hasMic = true;
3252
option.text = deviceInfo.label || `microphone ${audioInputSelect.length + 1}`;
3353
audioInputSelect.appendChild(option);
3454
} else if (deviceInfo.kind === 'audiooutput') {
3555
option.text = deviceInfo.label || `speaker ${audioOutputSelect.length + 1}`;
3656
audioOutputSelect.appendChild(option);
3757
} else if (deviceInfo.kind === 'videoinput') {
58+
hasCamera = true;
3859
option.text = deviceInfo.label || `camera ${videoSelect.length + 1}`;
3960
videoSelect.appendChild(option);
4061
} else {
@@ -46,10 +67,9 @@ function gotDevices(deviceInfos) {
4667
select.value = values[selectorIndex];
4768
}
4869
});
70+
start();
4971
}
5072

51-
navigator.mediaDevices.enumerateDevices().then(gotDevices).catch(handleError);
52-
5373
// Attach audio output device to video element using device/sink ID.
5474
function attachSinkId(element, sinkId) {
5575
if (typeof element.sinkId !== 'undefined') {
@@ -79,32 +99,54 @@ function changeAudioDestination() {
7999
function gotStream(stream) {
80100
window.stream = stream; // make stream available to console
81101
videoElement.srcObject = stream;
82-
// Refresh button list in case labels have become available
83-
return navigator.mediaDevices.enumerateDevices();
102+
if (stream.getVideoTracks()[0]) {
103+
openCamera = stream.getVideoTracks()[0].getSettings().deviceId;
104+
}
105+
if (stream.getAudioTracks()[0]) {
106+
openMic = stream.getAudioTracks()[0].getSettings().deviceId;
107+
}
108+
// Refresh list in case labels have become available
109+
return getDevices();
84110
}
85111

86112
function handleError(error) {
87113
console.log('navigator.MediaDevices.getUserMedia error: ', error.message, error.name);
88114
}
89115

90116
function start() {
117+
const audioSource = audioInputSelect.value || undefined;
118+
const videoSource = videoSelect.value || undefined;
119+
// Don't open the same devices again.
120+
if (hasPermission && openMic == audioSource && openCamera == videoSource) {
121+
return;
122+
}
123+
// Close existng streams.
91124
if (window.stream) {
92125
window.stream.getTracks().forEach(track => {
93126
track.stop();
94127
});
128+
openCamera = undefined;
129+
openMic = undefined;
95130
}
96-
const audioSource = audioInputSelect.value;
97-
const videoSource = videoSelect.value;
98131
const constraints = {
99-
audio: {deviceId: audioSource ? {exact: audioSource} : undefined},
100-
video: {deviceId: videoSource ? {exact: videoSource} : undefined}
132+
audio: true,
133+
video: true
101134
};
102-
navigator.mediaDevices.getUserMedia(constraints).then(gotStream).then(gotDevices).catch(handleError);
135+
if (hasMic) {
136+
constraints['audio'] = {deviceId: audioSource ? {exact: audioSource} : undefined};
137+
}
138+
if (hasCamera) {
139+
constraints['video'] = {deviceId: videoSource ? {exact: videoSource} : undefined};
140+
}
141+
console.log('start', constraints);
142+
if (!hasPermission || hasCamera || hasMic) {
143+
navigator.mediaDevices.getUserMedia(constraints).then(gotStream).catch(handleError);
144+
}
103145
}
104146

105147
audioInputSelect.onchange = start;
106148
audioOutputSelect.onchange = changeAudioDestination;
107-
108149
videoSelect.onchange = start;
150+
navigator.mediaDevices.ondevicechange = getDevices;
109151

110-
start();
152+
getDevices();

0 commit comments

Comments
 (0)