mirror of
https://github.com/jech/galene.git
synced 2024-12-22 15:25:48 +01:00
Rework the up connection state machine.
It is now more similar to the down connection, using the onclose callback for resource management.
This commit is contained in:
parent
10ebe0e433
commit
8168c2a9e6
3 changed files with 63 additions and 70 deletions
|
@ -40,11 +40,10 @@ serverConnection.ondownstream = ...;
|
|||
```
|
||||
|
||||
The `onconnected` callback is called when we connect to the server. The
|
||||
`onclose` callback is called when the socket is closed; you should use it
|
||||
to close all your up streams (down streams will be closed by the server).
|
||||
The `onusermessage` callback indicates an application-specific message,
|
||||
either from another user or from the server; the field `kind` indicates
|
||||
the kind of message.
|
||||
`onclose` callback is called when the socket is closed; all streams will
|
||||
have been closed by the time it is called. The `onusermessage` callback
|
||||
indicates an application-specific message, either from another user or
|
||||
from the server; the field `kind` indicates the kind of message.
|
||||
|
||||
Once you have joined a group (see below), the remaining callbacks may
|
||||
trigger. The `onuser` callback is used to indicate that a user has joined
|
||||
|
@ -126,8 +125,8 @@ a change in the status of the stream; states `connected` and `complete`
|
|||
indicate a functioning stream; other states indicate that the stream is
|
||||
not working right now but might recover in the future.
|
||||
|
||||
The `onclose` callback is called when the stream is destroyed by the
|
||||
server.
|
||||
The `onclose` callback is called when the stream is destroyed, either by
|
||||
the server or in response to a call to the `close` method.
|
||||
|
||||
## Pushing outgoing video streams
|
||||
|
||||
|
|
|
@ -309,7 +309,6 @@ function gotConnected() {
|
|||
* @param {string} reason
|
||||
*/
|
||||
function gotClose(code, reason) {
|
||||
delUpMediaKind(null);
|
||||
setConnected(false);
|
||||
if(code != 1000) {
|
||||
console.warn('Socket close', code, reason);
|
||||
|
@ -374,7 +373,7 @@ getButtonElement('presentbutton').onclick = async function(e) {
|
|||
|
||||
getButtonElement('unpresentbutton').onclick = function(e) {
|
||||
e.preventDefault();
|
||||
delUpMediaKind('local');
|
||||
closeUpMediaKind('local');
|
||||
resizePeers();
|
||||
};
|
||||
|
||||
|
@ -482,13 +481,13 @@ document.getElementById('sharebutton').onclick = function(e) {
|
|||
|
||||
document.getElementById('unsharebutton').onclick = function(e) {
|
||||
e.preventDefault();
|
||||
delUpMediaKind('screenshare');
|
||||
closeUpMediaKind('screenshare');
|
||||
resizePeers();
|
||||
};
|
||||
|
||||
document.getElementById('stopvideobutton').onclick = function(e) {
|
||||
e.preventDefault();
|
||||
delUpMediaKind('video');
|
||||
closeUpMediaKind('video');
|
||||
resizePeers();
|
||||
};
|
||||
|
||||
|
@ -757,10 +756,6 @@ function newUpStream(id) {
|
|||
c.onerror = function(e) {
|
||||
console.error(e);
|
||||
displayError(e);
|
||||
delUpMedia(c);
|
||||
};
|
||||
c.onabort = function() {
|
||||
delUpMedia(c);
|
||||
};
|
||||
c.onnegotiationcompleted = function() {
|
||||
setMaxVideoThroughput(c, getMaxVideoThroughput());
|
||||
|
@ -928,23 +923,16 @@ function setFilter(c, f) {
|
|||
c.userdata.filter.stop();
|
||||
c.userdata.filter = null;
|
||||
}
|
||||
if(!c.onclose) {
|
||||
console.warn("onclose not set, this shouldn't happen");
|
||||
c.onclose = null;
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if(c.userdata.filter)
|
||||
setFilter(c, null);
|
||||
|
||||
if(c.onclose)
|
||||
throw new Error('onclose already taken');
|
||||
if(f.inputStream != c.stream)
|
||||
throw new Error('Setting filter for wrong stream');
|
||||
c.stream = f.outputStream;
|
||||
c.userdata.filter = f;
|
||||
c.onclose = () => setFilter(c, null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1028,13 +1016,10 @@ async function addLocalMedia(id) {
|
|||
|
||||
if(!audio && !video) {
|
||||
if(old)
|
||||
delUpMedia(old);
|
||||
old.close();
|
||||
return;
|
||||
}
|
||||
|
||||
if(old)
|
||||
stopUpMedia(old);
|
||||
|
||||
let constraints = {audio: audio, video: video};
|
||||
/** @type {MediaStream} */
|
||||
let stream = null;
|
||||
|
@ -1043,7 +1028,7 @@ async function addLocalMedia(id) {
|
|||
} catch(e) {
|
||||
displayError(e);
|
||||
if(old)
|
||||
delUpMedia(old);
|
||||
old.close();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1058,8 +1043,22 @@ async function addLocalMedia(id) {
|
|||
try {
|
||||
let f = new Filter(stream, filter);
|
||||
setFilter(c, f);
|
||||
c.onclose = () => {
|
||||
stopStream(stream);
|
||||
setFilter(c, null);
|
||||
delMedia(c.id);
|
||||
}
|
||||
} catch(e) {
|
||||
displayWarning(e);
|
||||
c.onclose = () => {
|
||||
stopStream(c.stream);
|
||||
delMedia(c.id);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
c.onclose = () => {
|
||||
stopStream(c.stream);
|
||||
delMedia(c.id);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1110,11 +1109,13 @@ async function addShareMedia() {
|
|||
let c = newUpStream();
|
||||
c.kind = 'screenshare';
|
||||
c.stream = stream;
|
||||
c.onclose = () => {
|
||||
stopStream(stream);
|
||||
delMedia(c.id);
|
||||
}
|
||||
stream.getTracks().forEach(t => {
|
||||
c.pc.addTrack(t, stream);
|
||||
t.onended = e => {
|
||||
delUpMedia(c);
|
||||
};
|
||||
t.onended = e => c.close();
|
||||
c.labels[t.id] = 'screenshare';
|
||||
});
|
||||
c.onstats = gotUpStats;
|
||||
|
@ -1144,12 +1145,14 @@ async function addFileMedia(file) {
|
|||
c.kind = 'video';
|
||||
c.stream = stream;
|
||||
c.onclose = function() {
|
||||
stopStream(c.stream);
|
||||
let media = /** @type{HTMLVideoElement} */
|
||||
(document.getElementById('media-' + this.id));
|
||||
if(media && media.src) {
|
||||
URL.revokeObjectURL(media.src);
|
||||
media.src = null;
|
||||
}
|
||||
delMedia(c.id);
|
||||
}
|
||||
|
||||
stream.onaddtrack = function(e) {
|
||||
|
@ -1186,7 +1189,7 @@ async function addFileMedia(file) {
|
|||
if(Object.keys(c.labels).length === 0) {
|
||||
stream.onaddtrack = null;
|
||||
stream.onremovetrack = null;
|
||||
delUpMedia(c);
|
||||
c.close();
|
||||
}
|
||||
};
|
||||
await setMedia(c, true, false, video);
|
||||
|
@ -1195,13 +1198,10 @@ async function addFileMedia(file) {
|
|||
}
|
||||
|
||||
/**
|
||||
* @param {Stream} c
|
||||
* @param {MediaStream} s
|
||||
*/
|
||||
function stopUpMedia(c) {
|
||||
setFilter(c, null);
|
||||
if(!c.stream)
|
||||
return;
|
||||
c.stream.getTracks().forEach(t => {
|
||||
function stopStream(s) {
|
||||
s.getTracks().forEach(t => {
|
||||
try {
|
||||
t.stop();
|
||||
} catch(e) {
|
||||
|
@ -1211,31 +1211,18 @@ function stopUpMedia(c) {
|
|||
}
|
||||
|
||||
/**
|
||||
* @param {Stream} c
|
||||
*/
|
||||
function delUpMedia(c) {
|
||||
stopUpMedia(c);
|
||||
c.close();
|
||||
delMedia(c.id);
|
||||
delete(serverConnection.up[c.id]);
|
||||
setButtonsVisibility();
|
||||
}
|
||||
|
||||
/**
|
||||
* delUpMediaKind reoves all up media of the given kind. If kind is
|
||||
* falseish, it removes all up media.
|
||||
* closeUpMediaKind closes all up connections that correspond to a given
|
||||
* kind of media. If kind is null, it closes all up connections.
|
||||
*
|
||||
* @param {string} kind
|
||||
*/
|
||||
function delUpMediaKind(kind) {
|
||||
function closeUpMediaKind(kind) {
|
||||
for(let id in serverConnection.up) {
|
||||
let c = serverConnection.up[id];
|
||||
if(kind && c.kind != kind)
|
||||
continue
|
||||
delUpMedia(c);
|
||||
c.close();
|
||||
}
|
||||
|
||||
setButtonsVisibility();
|
||||
hideVideo();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1501,6 +1488,7 @@ function delMedia(id) {
|
|||
media.srcObject = null;
|
||||
mediadiv.removeChild(peer);
|
||||
|
||||
setButtonsVisibility();
|
||||
resizePeers();
|
||||
hideVideo();
|
||||
}
|
||||
|
|
|
@ -238,12 +238,10 @@ ServerConnection.prototype.connect = async function(url) {
|
|||
sc.permissions = {};
|
||||
for(let id in sc.up) {
|
||||
let c = sc.up[id];
|
||||
delete(sc.up[id]);
|
||||
c.close();
|
||||
}
|
||||
for(let id in sc.down) {
|
||||
let c = sc.down[id];
|
||||
delete(sc.down[id]);
|
||||
c.close();
|
||||
}
|
||||
if(sc.group && sc.onjoined)
|
||||
|
@ -408,9 +406,9 @@ ServerConnection.prototype.newUpStream = function(id) {
|
|||
let pc = new RTCPeerConnection(sc.rtcConfiguration);
|
||||
if(!pc)
|
||||
throw new Error("Couldn't create peer connection");
|
||||
if(sc.up[id]) {
|
||||
if(sc.up[id])
|
||||
sc.up[id].close();
|
||||
}
|
||||
|
||||
let c = new Stream(this, id, pc, true);
|
||||
sc.up[id] = c;
|
||||
|
||||
|
@ -530,7 +528,6 @@ ServerConnection.prototype.gotOffer = async function(id, labels, source, usernam
|
|||
// SDP is rather inflexible as to what can be renegotiated.
|
||||
// Unless the server indicates that this is a renegotiation with
|
||||
// all parameters unchanged, tear down the existing connection.
|
||||
delete(sc.down[id]);
|
||||
c.close(true);
|
||||
c = null;
|
||||
}
|
||||
|
@ -669,7 +666,6 @@ ServerConnection.prototype.gotClose = function(id) {
|
|||
let c = this.down[id];
|
||||
if(!c)
|
||||
throw new Error('unknown down stream');
|
||||
delete(this.down[id]);
|
||||
c.close();
|
||||
};
|
||||
|
||||
|
@ -888,19 +884,17 @@ function Stream(sc, id, pc, up) {
|
|||
*/
|
||||
Stream.prototype.close = function(nocallback) {
|
||||
let c = this;
|
||||
|
||||
if(!c.sc) {
|
||||
console.warn('Closing closed stream');
|
||||
return;
|
||||
}
|
||||
|
||||
if(c.statsHandler) {
|
||||
clearInterval(c.statsHandler);
|
||||
c.statsHandler = null;
|
||||
}
|
||||
|
||||
if(c.stream) {
|
||||
c.stream.getTracks().forEach(t => {
|
||||
try {
|
||||
t.stop();
|
||||
} catch(e) {
|
||||
}
|
||||
});
|
||||
}
|
||||
c.pc.close();
|
||||
|
||||
if(c.up && c.localDescriptionSent) {
|
||||
|
@ -913,9 +907,21 @@ Stream.prototype.close = function(nocallback) {
|
|||
}
|
||||
}
|
||||
|
||||
if(c.up) {
|
||||
if(c.sc.up[c.id] === c)
|
||||
delete(c.sc.up[c.id]);
|
||||
else
|
||||
console.warn('Closing unknown stream');
|
||||
} else {
|
||||
if(c.sc.down[c.id] === c)
|
||||
delete(c.sc.down[c.id]);
|
||||
else
|
||||
console.warn('Closing unknown stream');
|
||||
}
|
||||
c.sc = null;
|
||||
|
||||
if(!nocallback && c.onclose)
|
||||
c.onclose.call(c);
|
||||
c.sc = null;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in a new issue