|
|
@ -37,6 +37,18 @@ form {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
form label {
|
|
|
|
form label {
|
|
|
|
display: table-row;
|
|
|
|
display: table-row;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#status {
|
|
|
|
|
|
|
|
display: table;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#status .log-entry {
|
|
|
|
|
|
|
|
display: block;
|
|
|
|
|
|
|
|
background: lightblue;
|
|
|
|
|
|
|
|
border: solid black 2px;
|
|
|
|
|
|
|
|
margin: 2px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#status .log-entry:nth-child(odd) {
|
|
|
|
|
|
|
|
background: lightyellow;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
</style>
|
|
|
|
</style>
|
|
|
|
</head>
|
|
|
|
</head>
|
|
|
@ -90,7 +102,21 @@ form label {
|
|
|
|
const unmute = document.getElementById("unmute");
|
|
|
|
const unmute = document.getElementById("unmute");
|
|
|
|
const form = document.forms["settings"];
|
|
|
|
const form = document.forms["settings"];
|
|
|
|
|
|
|
|
|
|
|
|
out.innerText += "Loading...\n";
|
|
|
|
function _log(str, tag) {
|
|
|
|
|
|
|
|
const logEntry = document.createElement(tag);
|
|
|
|
|
|
|
|
logEntry.innerText = str;
|
|
|
|
|
|
|
|
logEntry.classList.add('log-entry');
|
|
|
|
|
|
|
|
out.appendChild(logEntry);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
function log(str) {
|
|
|
|
|
|
|
|
_log(str, 'span');
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function logPre(str) {
|
|
|
|
|
|
|
|
_log(str.split('\\r\\n').join('\r\n'), 'pre');
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
log("Loading...");
|
|
|
|
|
|
|
|
|
|
|
|
unmute.addEventListener("click", _ => {
|
|
|
|
unmute.addEventListener("click", _ => {
|
|
|
|
remoteView.muted = false;
|
|
|
|
remoteView.muted = false;
|
|
|
@ -125,7 +151,8 @@ form label {
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
try {
|
|
|
|
const hash = decodeURI(window.location.hash);
|
|
|
|
const hash = decodeURI(window.location.hash);
|
|
|
|
out.innerText += "Reading settings from hash: " + hash + "\n";
|
|
|
|
log("Reading settings from hash:");
|
|
|
|
|
|
|
|
logPre(hash);
|
|
|
|
settings = JSON.parse(hash.substring(1));
|
|
|
|
settings = JSON.parse(hash.substring(1));
|
|
|
|
for (const name in settings) {
|
|
|
|
for (const name in settings) {
|
|
|
|
const el = form.elements[name];
|
|
|
|
const el = form.elements[name];
|
|
|
@ -137,7 +164,7 @@ form label {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (error) {
|
|
|
|
} catch (error) {
|
|
|
|
out.innerText += "Failed to read settings from hash: " + error + "\n";
|
|
|
|
log("Failed to read settings from hash: " + error);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (isHost) {
|
|
|
|
if (isHost) {
|
|
|
@ -162,28 +189,27 @@ form label {
|
|
|
|
form.style.display = 'none';
|
|
|
|
form.style.display = 'none';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
out.innerText += "Room: " + roomName + "\n";
|
|
|
|
log("Room: " + roomName);
|
|
|
|
|
|
|
|
|
|
|
|
var webSocket = undefined;
|
|
|
|
var webSocket = undefined;
|
|
|
|
|
|
|
|
|
|
|
|
function sendJson(data) {
|
|
|
|
function sendJson(data) {
|
|
|
|
const toSend = JSON.stringify(data);
|
|
|
|
const toSend = JSON.stringify(data);
|
|
|
|
out.innerText += "Sending message...\n";
|
|
|
|
log("Sending message...");
|
|
|
|
create(out, 'pre').innerText = toSend.split('\\r\\n').join('\r\n');
|
|
|
|
logPre(toSend);
|
|
|
|
create(out, 'br');
|
|
|
|
|
|
|
|
webSocket.send(toSend);
|
|
|
|
webSocket.send(toSend);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var pc = undefined;
|
|
|
|
var pc = undefined;
|
|
|
|
function createRTCPeerConnection() {
|
|
|
|
function createRTCPeerConnection() {
|
|
|
|
const pc = new RTCPeerConnection();
|
|
|
|
const pc = new RTCPeerConnection();
|
|
|
|
out.innerText += "Created RTCPeerConnection.\n";
|
|
|
|
log("Created RTCPeerConnection.");
|
|
|
|
|
|
|
|
|
|
|
|
pc.onicecandidate = ({candidate}) => sendJson({candidate});
|
|
|
|
pc.onicecandidate = ({candidate}) => sendJson({candidate});
|
|
|
|
|
|
|
|
|
|
|
|
// let the "negotiationneeded" event trigger offer generation
|
|
|
|
// let the "negotiationneeded" event trigger offer generation
|
|
|
|
pc.onnegotiationneeded = async function () {
|
|
|
|
pc.onnegotiationneeded = async function () {
|
|
|
|
out.innerText += "In pc.onnegotiationneeded...\n";
|
|
|
|
log("In pc.onnegotiationneeded...");
|
|
|
|
await pc.setLocalDescription(await pc.createOffer());
|
|
|
|
await pc.setLocalDescription(await pc.createOffer());
|
|
|
|
sendJson({
|
|
|
|
sendJson({
|
|
|
|
description: pc.localDescription
|
|
|
|
description: pc.localDescription
|
|
|
@ -191,10 +217,10 @@ form label {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pc.ontrack = ({streams: [stream]}) => {
|
|
|
|
pc.ontrack = ({streams: [stream]}) => {
|
|
|
|
out.innerText += "In pc.ontrack...\n";
|
|
|
|
log("In pc.ontrack...");
|
|
|
|
|
|
|
|
|
|
|
|
remoteView.srcObject = stream;
|
|
|
|
remoteView.srcObject = stream;
|
|
|
|
remoteView.style.display = '';
|
|
|
|
log("Set srcObject");
|
|
|
|
remoteView.play();
|
|
|
|
remoteView.play();
|
|
|
|
out.innerText += "Set srcObject\n";
|
|
|
|
out.innerText += "Set srcObject\n";
|
|
|
|
out.style.display = 'none';
|
|
|
|
out.style.display = 'none';
|
|
|
@ -218,11 +244,11 @@ form label {
|
|
|
|
const videoSettings = isHost
|
|
|
|
const videoSettings = isHost
|
|
|
|
? settings['host-video']
|
|
|
|
? settings['host-video']
|
|
|
|
: settings['client-video'];
|
|
|
|
: settings['client-video'];
|
|
|
|
out.innerText += "videoSettings=" + videoSettings + "\n";
|
|
|
|
log("videoSettings=" + videoSettings);
|
|
|
|
const audioSettings = isHost
|
|
|
|
const audioSettings = isHost
|
|
|
|
? settings['host-audio']
|
|
|
|
? settings['host-audio']
|
|
|
|
: settings['client-audio'];
|
|
|
|
: settings['client-audio'];
|
|
|
|
out.innerText += "audioSettings=" + audioSettings + "\n";
|
|
|
|
log("audioSettings=" + audioSettings);
|
|
|
|
|
|
|
|
|
|
|
|
if (videoSettings == 'screen' && !fromButton) {
|
|
|
|
if (videoSettings == 'screen' && !fromButton) {
|
|
|
|
start.style.display = '';
|
|
|
|
start.style.display = '';
|
|
|
@ -244,7 +270,7 @@ form label {
|
|
|
|
: videoSettings == 'true'
|
|
|
|
: videoSettings == 'true'
|
|
|
|
? true
|
|
|
|
? true
|
|
|
|
: { advanced: [{facingMode: videoSettings}] };
|
|
|
|
: { advanced: [{facingMode: videoSettings}] };
|
|
|
|
out.innerText += "Created videoConstraints.\n";
|
|
|
|
log("Created videoConstraints.");
|
|
|
|
if (!videoConstraints && !audioSettings) return;
|
|
|
|
if (!videoConstraints && !audioSettings) return;
|
|
|
|
|
|
|
|
|
|
|
|
const stream = videoSettings == 'screen'
|
|
|
|
const stream = videoSettings == 'screen'
|
|
|
@ -256,23 +282,23 @@ form label {
|
|
|
|
audio: audioSettings,
|
|
|
|
audio: audioSettings,
|
|
|
|
video: videoConstraints
|
|
|
|
video: videoConstraints
|
|
|
|
});
|
|
|
|
});
|
|
|
|
out.innerText += "Created stream.\n";
|
|
|
|
log("Created stream.");
|
|
|
|
if (videoConstraints) {
|
|
|
|
if (videoConstraints) {
|
|
|
|
selfView.srcObject = stream;
|
|
|
|
selfView.srcObject = stream;
|
|
|
|
selfView.style.display = '';
|
|
|
|
selfView.style.display = '';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (const track of stream.getTracks()) {
|
|
|
|
for (const track of stream.getTracks()) {
|
|
|
|
out.innerText += "Added track.\n";
|
|
|
|
log("Added track.");
|
|
|
|
pc.addTrack(track, stream);
|
|
|
|
pc.addTrack(track, stream);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
function startStartingWithErorrHandling(fromButton) {
|
|
|
|
function startStartingWithErorrHandling(fromButton) {
|
|
|
|
startStreaming(fromButton)
|
|
|
|
startStreaming(fromButton)
|
|
|
|
.then(() => {
|
|
|
|
.then(() => {
|
|
|
|
out.innerText += "startStreaming() finished.\n";
|
|
|
|
log("startStreaming() finished.");
|
|
|
|
})
|
|
|
|
})
|
|
|
|
.catch(e => {
|
|
|
|
.catch(e => {
|
|
|
|
out.innerText += "startStreaming() errored: " + e.message + "\n";
|
|
|
|
log("startStreaming() errored: " + e.message);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -282,9 +308,8 @@ form label {
|
|
|
|
|
|
|
|
|
|
|
|
async function receiveMessage(e) {
|
|
|
|
async function receiveMessage(e) {
|
|
|
|
qrcode.style.display = 'none';
|
|
|
|
qrcode.style.display = 'none';
|
|
|
|
out.innerText += "In webSocket.onmessage...\n";
|
|
|
|
log("In webSocket.onmessage...");
|
|
|
|
create(out, 'pre').innerText = e.data.split('\\r\\n').join('\r\n');
|
|
|
|
logPre(e.data);
|
|
|
|
create(out, 'br');
|
|
|
|
|
|
|
|
const data = JSON.parse(e.data);
|
|
|
|
const data = JSON.parse(e.data);
|
|
|
|
if (data.requestSettings) {
|
|
|
|
if (data.requestSettings) {
|
|
|
|
settings = readSettingsForm(true);
|
|
|
|
settings = readSettingsForm(true);
|
|
|
@ -295,14 +320,14 @@ form label {
|
|
|
|
} else if (data.description) {
|
|
|
|
} else if (data.description) {
|
|
|
|
await pc.setRemoteDescription(data.description);
|
|
|
|
await pc.setRemoteDescription(data.description);
|
|
|
|
if (data.description.type == "offer") {
|
|
|
|
if (data.description.type == "offer") {
|
|
|
|
out.innerText += "Got an offer...\n";
|
|
|
|
log("Got an offer...");
|
|
|
|
await pc.setLocalDescription(await pc.createAnswer());
|
|
|
|
await pc.setLocalDescription(await pc.createAnswer());
|
|
|
|
sendJson({
|
|
|
|
sendJson({
|
|
|
|
description: pc.localDescription
|
|
|
|
description: pc.localDescription
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (data.candidate) {
|
|
|
|
} else if (data.candidate) {
|
|
|
|
out.innerText += "Adding ice candidate...\n";
|
|
|
|
log("Adding ice candidate...");
|
|
|
|
await pc.addIceCandidate(data.candidate);
|
|
|
|
await pc.addIceCandidate(data.candidate);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
@ -315,13 +340,13 @@ form label {
|
|
|
|
+ roomName
|
|
|
|
+ roomName
|
|
|
|
+ '/'
|
|
|
|
+ '/'
|
|
|
|
);
|
|
|
|
);
|
|
|
|
out.innerText += "Created WebSocket.\n";
|
|
|
|
log("Created WebSocket.");
|
|
|
|
|
|
|
|
|
|
|
|
webSocket.onclose = function(e) {
|
|
|
|
webSocket.onclose = function(e) {
|
|
|
|
out.innerText += 'WebSocket closed unexpectedly: ' + e + '\n';
|
|
|
|
log('WebSocket closed unexpectedly: ' + e);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
webSocket.onerror = function(e) {
|
|
|
|
webSocket.onerror = function(e) {
|
|
|
|
out.innerText += 'WebSocket error: ' + e + '\n';
|
|
|
|
log('WebSocket error: ' + e);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
webSocket.onmessage = receiveMessage;
|
|
|
|
webSocket.onmessage = receiveMessage;
|
|
|
@ -335,7 +360,7 @@ form label {
|
|
|
|
webSocket.onopen = _ => sendJson({requestSettings: true});
|
|
|
|
webSocket.onopen = _ => sendJson({requestSettings: true});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
out.innerText += "Finished <script> block.\n";
|
|
|
|
log("Finished <script> block.");
|
|
|
|
</script>
|
|
|
|
</script>
|
|
|
|
</body>
|
|
|
|
</body>
|
|
|
|
</html>
|
|
|
|
</html>
|
|
|
|