diff --git a/static/galene.js b/static/galene.js index 5b6dc9e..1566597 100644 --- a/static/galene.js +++ b/static/galene.js @@ -320,8 +320,9 @@ function gotClose(code, reason) { * @param {Stream} c */ function gotDownStream(c) { - c.onclose = function() { - delMedia(c.id); + c.onclose = function(replace) { + if(!replace) + delMedia(c.id); }; c.onerror = function(e) { console.error(e); @@ -1013,11 +1014,16 @@ async function addLocalMedia(id) { } let old = id && serverConnection.up[id]; - if(old) - old.close(); - - if(!audio && !video) + if(!audio && !video) { + if(old) + old.close(); return; + } + + if(old && old.onclose) { + // make sure that the camera is released before we try to reopen it + old.onclose.call(old, true); + } let constraints = {audio: audio, video: video}; /** @type {MediaStream} */ @@ -1040,22 +1046,25 @@ async function addLocalMedia(id) { try { let f = new Filter(stream, filter); setFilter(c, f); - c.onclose = () => { + c.onclose = replace => { stopStream(stream); setFilter(c, null); - delMedia(c.id); + if(!replace) + delMedia(c.id); } } catch(e) { displayWarning(e); - c.onclose = () => { + c.onclose = replace => { stopStream(c.stream); - delMedia(c.id); + if(!replace) + delMedia(c.id); } } } else { - c.onclose = () => { + c.onclose = replace => { stopStream(c.stream); - delMedia(c.id); + if(!replace) + delMedia(c.id); } } @@ -1106,9 +1115,10 @@ async function addShareMedia() { let c = newUpStream(); c.kind = 'screenshare'; c.stream = stream; - c.onclose = () => { + c.onclose = replace => { stopStream(stream); - delMedia(c.id); + if(!replace) + delMedia(c.id); } stream.getTracks().forEach(t => { c.pc.addTrack(t, stream); @@ -1141,7 +1151,7 @@ async function addFileMedia(file) { let c = newUpStream(); c.kind = 'video'; c.stream = stream; - c.onclose = function() { + c.onclose = function(replace) { stopStream(c.stream); let media = /** @type{HTMLVideoElement} */ (document.getElementById('media-' + this.id)); @@ -1149,8 +1159,9 @@ async function addFileMedia(file) { URL.revokeObjectURL(media.src); media.src = null; } - delMedia(c.id); - } + if(!replace) + delMedia(c.id); + }; stream.onaddtrack = function(e) { let t = e.track; diff --git a/static/protocol.js b/static/protocol.js index 19b914c..5849c48 100644 --- a/static/protocol.js +++ b/static/protocol.js @@ -634,7 +634,7 @@ ServerConnection.prototype.gotAnswer = async function(id, sdp) { if(c.onerror) c.onerror.call(c, e); } finally { - c.close(true); + c.close(); } return; } @@ -825,9 +825,10 @@ function Stream(sc, id, pc, up) { /* Callbacks */ /** - * onclose is called when the stream is closed. + * onclose is called when the stream is closed. Replace will be true + * if the stream is being replaced by another one with the same id. * - * @type{(this: Stream) => void} + * @type{(this: Stream, replace: boolean) => void} */ this.onclose = null; /** @@ -880,9 +881,10 @@ function Stream(sc, id, pc, up) { * streams in the down direction, this will be called automatically when * the server signals that it is closing a stream. * - * @param {boolean} [nocallback] + * @param {boolean} [replace] + * - true if the stream is being replaced by another one with the same id */ -Stream.prototype.close = function(nocallback) { +Stream.prototype.close = function(replace) { let c = this; if(!c.sc) { @@ -920,8 +922,8 @@ Stream.prototype.close = function(nocallback) { } c.sc = null; - if(!nocallback && c.onclose) - c.onclose.call(c); + if(c.onclose) + c.onclose.call(c, replace); }; /**