mirror of
https://github.com/AlexandreRouma/wiscast.git
synced 2026-04-18 07:42:44 +00:00
185 lines
5.1 KiB
JavaScript
185 lines
5.1 KiB
JavaScript
// Streaming objects
|
|
let sock = null;
|
|
let stream = null;
|
|
let conn = null;
|
|
|
|
// GUI Objects
|
|
let connForm = document.querySelector('#connForm');
|
|
let dispNameTb = document.querySelector('#dispName');
|
|
let connBtn = document.querySelector('#connect');
|
|
let pinValForm = document.querySelector('#pinValForm');
|
|
let dispPINTb = document.querySelector('#dispPIN');
|
|
let validateBtn = document.querySelector('#validate');
|
|
let streamForm = document.querySelector('#streamForm');
|
|
let locPlayback = document.querySelector('#localPlayback');
|
|
|
|
// Make sure the connect button cannot be pressed if there is no display name
|
|
function onDispNameChange() {
|
|
connBtn.disabled = !(dispNameTb.value.length > 0);
|
|
}
|
|
function onPINChange() {
|
|
validateBtn.disabled = !(dispPINTb.value.length === 6);
|
|
}
|
|
|
|
// Handle enter key pressed
|
|
dispNameTb.addEventListener('keyup', (event) => {
|
|
if (event.key === 'Enter' && !connBtn.disabled) {
|
|
connBtn.click();
|
|
}
|
|
})
|
|
dispPINTb.addEventListener('keyup', (event) => {
|
|
if (event.key === 'Enter' && !validateBtn.disabled) {
|
|
validateBtn.click();
|
|
}
|
|
})
|
|
|
|
// WebSocket message handler
|
|
async function onMessage(data) {
|
|
// Parse the message
|
|
console.log(data)
|
|
const msg = JSON.parse(data);
|
|
|
|
// Process depending on the type
|
|
switch (msg.type) {
|
|
case 'disp-ok':
|
|
// Switch to the PIN screen
|
|
connForm.hidden = true;
|
|
pinValForm.hidden = false;
|
|
dispPINTb.focus();
|
|
dispPINTb.select();
|
|
break;
|
|
|
|
case 'disp-error':
|
|
// Show the error
|
|
// TODO
|
|
console.log('ERROR: ' + msg.error)
|
|
break;
|
|
|
|
case 'auth-ok':
|
|
// Show the status update
|
|
validateBtn.textContent = 'Starting the Stream...';
|
|
await startStream();
|
|
break;
|
|
|
|
case 'answer':
|
|
console.log('Got answer')
|
|
// Pass on the offer to WebRTC
|
|
await conn.setRemoteDescription(new RTCSessionDescription(msg.answer));
|
|
break;
|
|
|
|
case 'ice-candidate':
|
|
console.log('Got ice candidate')
|
|
// Add the ice candidate to the WebRTC connection
|
|
await conn.addIceCandidate(msg.candidate);
|
|
break;
|
|
|
|
case 'disconnect':
|
|
// Reload the page
|
|
location.reload();
|
|
break;
|
|
|
|
default:
|
|
console.dir(msg)
|
|
break;
|
|
}
|
|
}
|
|
|
|
async function startStream() {
|
|
// Get the stream for the screen
|
|
stream = await navigator.mediaDevices.getDisplayMedia({ video: { cursor: 'always' } });
|
|
|
|
// Create the connection
|
|
conn = new RTCPeerConnection({'iceServers': [{'urls': 'stun:stun.l.google.com:19302'}]});
|
|
|
|
// Handle ice candidates
|
|
conn.addEventListener('icecandidate', async (event) => {
|
|
// If there is a new candidate, send it to the peer through websockets
|
|
if (event.candidate) {
|
|
await sock.send(JSON.stringify({
|
|
type: 'ice-candidate',
|
|
candidate: event.candidate
|
|
}))
|
|
}
|
|
});
|
|
|
|
// Handle connection and disconnection of peer
|
|
conn.addEventListener('connectionstatechange', (event) => {
|
|
switch (conn.connectionState) {
|
|
case 'connected':
|
|
// Switch to stream screen
|
|
pinValForm.hidden = true;
|
|
streamForm.hidden = false;
|
|
locPlayback.srcObject = stream;
|
|
|
|
console.log("Connected!")
|
|
|
|
break;
|
|
|
|
case 'disconnected':
|
|
console.log("Disconnected.")
|
|
// Reload the page to ensure the state is complete reset
|
|
location.reload();
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
});
|
|
|
|
// Start streaming the screen
|
|
stream.getTracks().forEach(track => {
|
|
conn.addTrack(track, stream);
|
|
});
|
|
|
|
// If the stream ends, reload the page
|
|
stream.getVideoTracks()[0].addEventListener('ended', (event) => {
|
|
location.reload();
|
|
})
|
|
|
|
// Create and send an offer
|
|
const offer = await conn.createOffer();
|
|
await conn.setLocalDescription(offer);
|
|
await sock.send(JSON.stringify({
|
|
type: 'offer',
|
|
offer: offer
|
|
}))
|
|
}
|
|
|
|
async function connect() {
|
|
// Disable the connect button and show status
|
|
dispNameTb.disabled = true;
|
|
connBtn.disabled = true;
|
|
connBtn.textContent = 'Connecting...';
|
|
|
|
// Send a connect command to the server
|
|
await sock.send(JSON.stringify({
|
|
type: 'connect',
|
|
dispID: dispNameTb.value
|
|
}));
|
|
}
|
|
|
|
async function validatePIN() {
|
|
// Disable the validate button and show status
|
|
dispPINTb.disabled = true;
|
|
validateBtn.disabled = true;
|
|
validateBtn.textContent = 'Checking the PIN...';
|
|
|
|
// Send the validate pin command to the server
|
|
await sock.send(JSON.stringify({
|
|
type: 'validate-pin',
|
|
pin: dispPINTb.value
|
|
}));
|
|
}
|
|
|
|
async function disconnect() {
|
|
// Just reload the page
|
|
location.reload();
|
|
}
|
|
|
|
// Connect to the server using WebSockets
|
|
console.log('Connecting to websocket...')
|
|
sock = new WebSocket(`ws://${location.host}/sig`);
|
|
sock.addEventListener('open', async (event) => {
|
|
console.log('Connected to websocket')
|
|
});
|
|
sock.addEventListener('message', (event) => { onMessage(event.data); }) |