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;
}
#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 {
display: flex;
}
@ -111,6 +127,7 @@ h1 {
}
#input {
margin-left: 0.5em;
width: 100%;
border: none;
resize: none;

View File

@ -31,8 +31,22 @@
<div id="optionsdiv">
<label for="presenterbox">Present:</label>
<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>
<input id="sharebox" type="checkbox"/ disabled>
</div>
</div>

View File

@ -126,6 +126,16 @@ document.getElementById('presenterbox').onchange = function(e) {
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) {
e.preventDefault();
setShareMedia(this.checked);
@ -193,6 +203,71 @@ function displayStats(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;
async function setLocalMedia(setup) {
@ -209,32 +284,39 @@ async function setLocalMedia(setup) {
return;
}
if(!localMediaId) {
let constraints = {audio: true, video: true};
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 audio = mapMediaOption(document.getElementById('audioselect').value);
let video = mapMediaOption(document.getElementById('videoselect').value);
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);
setLocalMedia(false);
if(!audio && !video)
return;
let constraints = {audio: audio, video: video};
let stream = null;
try {
stream = await navigator.mediaDevices.getUserMedia(constraints);
} catch(e) {
console.error(e);
document.getElementById('presenterbox').checked = false;
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;