1
Fork 0
mirror of https://github.com/jech/galene.git synced 2024-11-26 02:25:58 +01:00

Add receive support to example client.

This commit is contained in:
Juliusz Chroboczek 2024-06-10 15:49:08 +02:00
parent 6a55139c94
commit e7af7cbed4
2 changed files with 69 additions and 10 deletions

View file

@ -7,12 +7,14 @@
</head> </head>
<body> <body>
<p id="status">Disconnected</p> <div><button id="start">Start</button></p>
<p id="status"></p>
<p id="error"></p> <p id="error"></p>
<div><button id="show" disabled>Show/hide yourself</button></div> <div><button id="show" disabled>Show/hide yourself</button></div>
<video id="video"></video> <div id="videos"></div>
<div id="chat"></div> <div id="chat"></div>

View file

@ -1,4 +1,4 @@
/* Galene client example. Send-only for now. */ /* Galene client example. */
/** /**
* The main function. * The main function.
@ -59,11 +59,7 @@ async function serverConnect(status, token) {
}; };
conn.onchat = onChat; conn.onchat = onChat;
conn.onusermessage = onUserMessage; conn.onusermessage = onUserMessage;
conn.ondownstream = function(s) { conn.ondownstream = onDownStream;
// This should not happen, since we didn't ask to receive streams.
console.warn('Received unexpected stream from server');
s.abort();
}
conn.onclose = function() { conn.onclose = function() {
displayStatus('Disconnected'); displayStatus('Disconnected');
} }
@ -183,6 +179,8 @@ async function onJoined(kind, group, perms, status, data, error, message) {
case 'change': case 'change':
displayStatus(`Connected as ${this.username} in group ${this.group}.`); displayStatus(`Connected as ${this.username} in group ${this.group}.`);
enableShow(this, true); enableShow(this, true);
// request videos from the server
this.request({'': ['audio', 'video']});
break; break;
default: default:
displayError(`Unexpected state ${kind}.`); displayError(`Unexpected state ${kind}.`);
@ -191,22 +189,50 @@ async function onJoined(kind, group, perms, status, data, error, message) {
} }
} }
/**
* Create a video element. We encode the stream's id in the element's id
* in order to avoid having a global hash table that maps ids to video
* elements.
*
* @parm {string} id
* @returns {HTMLVideoElement}
*/
function makeVideoElement(id) {
let v = document.createElement('video');
v.id = 'video-' + id;
let container = document.getElementById('videos');
container.appendChild(v);
return v;
}
/**
* Find the video element that shows a given id.
*
* @parm {string} id
* @returns {HTMLVideoElement}
*/
function getVideoElement(id) {
let v = document.getElementById('video-' + id);
return /** @type{HTMLVideoElement} */(v);
}
/** /**
* Enable the camera and broadcast yourself to the group. * Enable the camera and broadcast yourself to the group.
* *
* @parm {ServerConnection} conn * @parm {ServerConnection} conn
*/ */
async function showCamera(conn) { async function showCamera(conn) {
let v = /** @type HTMLVideoElement */(document.getElementById('video'));
let ms = await navigator.mediaDevices.getUserMedia({audio: true, video: true}); let ms = await navigator.mediaDevices.getUserMedia({audio: true, video: true});
/* Send the new stream to the server */ /* Send the new stream to the server */
let s = conn.newUpStream(); let s = conn.newUpStream();
s.label = 'camera'; s.label = 'camera';
s.setStream(ms); s.setStream(ms);
let v = makeVideoElement(s.localId);
s.onclose = function(replace) { s.onclose = function(replace) {
s.stream.getTracks().forEach(t => t.stop()); s.stream.getTracks().forEach(t => t.stop());
v.srcObject = null; v.srcObject = null;
v.parentNode.removeChild(v);
} }
function addTrack(t) { function addTrack(t) {
@ -245,6 +271,29 @@ async function hide(conn, s) {
s.close(); s.close();
} }
/**
* Called when the server pushes a stream.
*
* @this {ServerConnection}
* @parm {Stream} c
*/
function onDownStream(s) {
s.onclose = function(replace) {
let v = getVideoElement(s.localId);
v.srcObject = null;
v.parentNode.removeChild(v);
}
s.ondowntrack = function(track, transceiver, stream) {
let v = getVideoElement(s.localId);
if(v.srcObject !== stream)
v.srcObject = stream;
}
let v = makeVideoElement(s.localId);
v.srcObject = s.stream;
v.play();
}
/** /**
* Display an error message. * Display an error message.
* *
@ -254,4 +303,12 @@ function displayError(message) {
document.getElementById('error').textContent = message; document.getElementById('error').textContent = message;
} }
start("/group/public/").catch(e => displayError(e)); document.getElementById('start').onclick = async function(e) {
let button = /** @type{HTMLButtonElement} */(this);
button.hidden = true;
try {
await start("/group/public/");
} catch(e) {
displayError(e);
};
}