1
Fork 0

Initial implementation of mike and camera selection.

We're closing and reopening the connection each time, we should be
renegotiating instead.
This commit is contained in:
Juliusz Chroboczek 2020-05-05 17:50:16 +02:00
parent 175b08bb08
commit f78030c482
3 changed files with 137 additions and 24 deletions

View File

@ -49,6 +49,22 @@ h1 {
display: none; display: none;
} }
#optionsdiv {
margin-bottom: 4px;
}
#videoselect {
width: 8em;
text-align-last: center;
margin-right: 0.4em;
}
#audioselect {
width: 8em;
text-align-last: center;
margin-right: 0.4em;
}
#main { #main {
display: flex; display: flex;
} }
@ -111,6 +127,7 @@ h1 {
} }
#input { #input {
margin-left: 0.5em;
width: 100%; width: 100%;
border: none; border: none;
resize: none; resize: none;

View File

@ -31,8 +31,22 @@
<div id="optionsdiv"> <div id="optionsdiv">
<label for="presenterbox">Present:</label> <label for="presenterbox">Present:</label>
<input id="presenterbox" type="checkbox"/ disabled> <input id="presenterbox" type="checkbox"/ disabled>
<label for="videoselect">Camera:</label>
<select id="videoselect">
<option>default</option>
<option>off</option>
</select>
<label for="audioselect">Microphone:</label>
<select id="audioselect">
<option>default</option>
<option>off</option>
</select>
<label for="sharebox">Share screen:</label> <label for="sharebox">Share screen:</label>
<input id="sharebox" type="checkbox"/ disabled> <input id="sharebox" type="checkbox"/ disabled>
</div> </div>
</div> </div>

View File

@ -126,6 +126,16 @@ document.getElementById('presenterbox').onchange = function(e) {
setLocalMedia(this.checked); setLocalMedia(this.checked);
} }
document.getElementById('audioselect').onchange = function(e) {
e.preventDefault();
setLocalMedia(document.getElementById('presenterbox').checked);
}
document.getElementById('videoselect').onchange = function(e) {
e.preventDefault();
setLocalMedia(document.getElementById('presenterbox').checked);
}
document.getElementById('sharebox').onchange = function(e) { document.getElementById('sharebox').onchange = function(e) {
e.preventDefault(); e.preventDefault();
setShareMedia(this.checked); setShareMedia(this.checked);
@ -193,6 +203,71 @@ function displayStats(id) {
setLabel(id); setLabel(id);
} }
function mapMediaOption(value) {
console.assert(typeof(value) === 'string');
switch(value) {
case 'default':
return true;
case 'off':
return false;
default:
return value;
}
}
function addSelectOption(select, label, value) {
if(!value)
value = label;
for(let i = 0; i < select.children.length; i++) {
if(select.children[i].value === value) {
return;
}
}
let option = document.createElement('option');
option.value = value;
option.textContent = label;
select.appendChild(option);
}
// media names might not be available before we call getDisplayMedia. So
// we call this lazily.
let mediaChoicesDone = false;
async function setMediaChoices() {
if(mediaChoicesDone)
return;
let devices = [];
try {
devices = await navigator.mediaDevices.enumerateDevices();
} catch(e) {
console.error(e);
return;
}
let cn = 1, mn = 1;
devices.forEach(d => {
let label = d.label;
if(d.kind === 'videoinput') {
if(!label)
label = `Camera ${cn}`;
addSelectOption(document.getElementById('videoselect'),
label, d.deviceId);
cn++;
} else if(d.kind === 'audioinput') {
if(!label)
label = `Microphone ${mn}`;
addSelectOption(document.getElementById('audioselect'),
label, d.deviceId);
mn++;
}
});
mediaChoicesDone = true;
}
let localMediaId = null; let localMediaId = null;
async function setLocalMedia(setup) { async function setLocalMedia(setup) {
@ -209,32 +284,39 @@ async function setLocalMedia(setup) {
return; return;
} }
if(!localMediaId) { let audio = mapMediaOption(document.getElementById('audioselect').value);
let constraints = {audio: true, video: true}; let video = mapMediaOption(document.getElementById('videoselect').value);
let stream = null;
try {
stream = await navigator.mediaDevices.getUserMedia(constraints);
} catch(e) {
console.error(e);
document.getElementById('presenterbox').checked = false;
await setLocalMedia(false);
return;
}
localMediaId = await newUpStream();
let c = up[localMediaId]; setLocalMedia(false);
c.stream = stream; if(!audio && !video)
stream.getTracks().forEach(t => { return;
let sender = c.pc.addTrack(t, stream);
c.setInterval(() => { let constraints = {audio: audio, video: video};
updateStats(c, sender); let stream = null;
}, 2000); try {
}); stream = await navigator.mediaDevices.getUserMedia(constraints);
c.setInterval(() => { } catch(e) {
displayStats(localMediaId); console.error(e);
}, 2500); document.getElementById('presenterbox').checked = false;
await setMedia(localMediaId); await setLocalMedia(false);
return;
} }
setMediaChoices();
localMediaId = await newUpStream();
let c = up[localMediaId];
c.stream = stream;
stream.getTracks().forEach(t => {
let sender = c.pc.addTrack(t, stream);
c.setInterval(() => {
updateStats(c, sender);
}, 2000);
});
c.setInterval(() => {
displayStats(localMediaId);
}, 2500);
await setMedia(localMediaId);
} }
let shareMediaId = null; let shareMediaId = null;