Moves duplicated methods to peer connection adapter.
This commit is contained in:
parent
100422dafc
commit
8b96d134e3
4
app.js
4
app.js
|
@ -725,8 +725,8 @@ function toggleVideo() {
|
||||||
if (!sess) {
|
if (!sess) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sess.pendingop = ismuted ? 'unmute' : 'mute';
|
sess.peerconnection.pendingop = ismuted ? 'unmute' : 'mute';
|
||||||
sess.modifySources();
|
sess.peerconnection.modifySources();
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleAudio() {
|
function toggleAudio() {
|
||||||
|
|
|
@ -40,7 +40,10 @@ function ColibriFocus(connection, bridgejid) {
|
||||||
this.peers = [];
|
this.peers = [];
|
||||||
this.confid = null;
|
this.confid = null;
|
||||||
|
|
||||||
this.peerconnection = null;
|
this.peerconnection
|
||||||
|
= new TraceablePeerConnection(
|
||||||
|
this.connection.jingle.ice_config,
|
||||||
|
this.connection.jingle.pc_constraints);
|
||||||
|
|
||||||
// media types of the conference
|
// media types of the conference
|
||||||
this.media = ['audio', 'video'];
|
this.media = ['audio', 'video'];
|
||||||
|
@ -51,13 +54,6 @@ function ColibriFocus(connection, bridgejid) {
|
||||||
this.channels = [];
|
this.channels = [];
|
||||||
this.remotessrc = {};
|
this.remotessrc = {};
|
||||||
|
|
||||||
// ssrc lines to be added on next update
|
|
||||||
this.addssrc = [];
|
|
||||||
// ssrc lines to be removed on next update
|
|
||||||
this.removessrc = [];
|
|
||||||
// pending mute/unmute video op that modify local description
|
|
||||||
this.pendingop = null;
|
|
||||||
|
|
||||||
// container for candidates from the focus
|
// container for candidates from the focus
|
||||||
// gathered before confid is known
|
// gathered before confid is known
|
||||||
this.drip_container = [];
|
this.drip_container = [];
|
||||||
|
@ -81,7 +77,6 @@ ColibriFocus.prototype.makeConference = function (peers) {
|
||||||
self.channels.push([]);
|
self.channels.push([]);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.peerconnection = new TraceablePeerConnection(this.connection.jingle.ice_config, this.connection.jingle.pc_constraints);
|
|
||||||
this.peerconnection.addStream(this.connection.jingle.localStream);
|
this.peerconnection.addStream(this.connection.jingle.localStream);
|
||||||
this.peerconnection.oniceconnectionstatechange = function (event) {
|
this.peerconnection.oniceconnectionstatechange = function (event) {
|
||||||
console.warn('ice connection state changed to', self.peerconnection.iceConnectionState);
|
console.warn('ice connection state changed to', self.peerconnection.iceConnectionState);
|
||||||
|
@ -651,9 +646,11 @@ ColibriFocus.prototype.setRemoteDescription = function (session, elem, desctype)
|
||||||
// ACT 4: add new a=ssrc lines to local remotedescription
|
// ACT 4: add new a=ssrc lines to local remotedescription
|
||||||
for (channel = 0; channel < this.channels[participant].length; channel++) {
|
for (channel = 0; channel < this.channels[participant].length; channel++) {
|
||||||
//if (channel == 0) continue; FIXME: does not work as intended
|
//if (channel == 0) continue; FIXME: does not work as intended
|
||||||
if (!this.addssrc[channel]) this.addssrc[channel] = '';
|
|
||||||
if (SDPUtil.find_lines(remoteSDP.media[channel], 'a=ssrc:').length) {
|
if (SDPUtil.find_lines(remoteSDP.media[channel], 'a=ssrc:').length) {
|
||||||
this.addssrc[channel] += SDPUtil.find_lines(remoteSDP.media[channel], 'a=ssrc:').join('\r\n') + '\r\n';
|
this.peerconnection.enqueueAddSsrc(
|
||||||
|
channel,
|
||||||
|
SDPUtil.find_lines(remoteSDP.media[channel], 'a=ssrc:').join('\r\n') + '\r\n'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.modifySources();
|
this.modifySources();
|
||||||
|
@ -764,8 +761,7 @@ ColibriFocus.prototype.terminate = function (session, reason) {
|
||||||
}
|
}
|
||||||
var ssrcs = this.remotessrc[session.peerjid];
|
var ssrcs = this.remotessrc[session.peerjid];
|
||||||
for (var i = 0; i < ssrcs.length; i++) {
|
for (var i = 0; i < ssrcs.length; i++) {
|
||||||
if (!this.removessrc[i]) this.removessrc[i] = '';
|
this.peerconnection.enqueueRemoveSsrc(i, ssrcs[i]);
|
||||||
this.removessrc[i] += ssrcs[i];
|
|
||||||
}
|
}
|
||||||
// remove from this.peers
|
// remove from this.peers
|
||||||
this.peers.splice(participant, 1);
|
this.peers.splice(participant, 1);
|
||||||
|
@ -796,7 +792,7 @@ ColibriFocus.prototype.terminate = function (session, reason) {
|
||||||
for (var j = 0; j < ssrcs.length; j++) {
|
for (var j = 0; j < ssrcs.length; j++) {
|
||||||
sdp.media[j] = 'a=mid:' + contents[j] + '\r\n';
|
sdp.media[j] = 'a=mid:' + contents[j] + '\r\n';
|
||||||
sdp.media[j] += ssrcs[j];
|
sdp.media[j] += ssrcs[j];
|
||||||
this.removessrc[j] += ssrcs[j];
|
this.peerconnection.enqueueRemoveSsrc(j, ssrcs[j]);
|
||||||
}
|
}
|
||||||
this.sendSSRCUpdate(sdp, session.peerjid, false);
|
this.sendSSRCUpdate(sdp, session.peerjid, false);
|
||||||
|
|
||||||
|
@ -806,126 +802,14 @@ ColibriFocus.prototype.terminate = function (session, reason) {
|
||||||
|
|
||||||
ColibriFocus.prototype.modifySources = function () {
|
ColibriFocus.prototype.modifySources = function () {
|
||||||
var self = this;
|
var self = this;
|
||||||
if (this.peerconnection.signalingState == 'closed') return;
|
this.peerconnection.modifySources(function(){
|
||||||
if (!(this.addssrc.length || this.removessrc.length || this.pendingop !== null)) return;
|
|
||||||
|
|
||||||
// FIXME: this is a big hack
|
|
||||||
// https://code.google.com/p/webrtc/issues/detail?id=2688
|
|
||||||
if (!(this.peerconnection.signalingState == 'stable' && this.peerconnection.iceConnectionState == 'connected')) {
|
|
||||||
console.warn('modifySources not yet', this.peerconnection.signalingState, this.peerconnection.iceConnectionState);
|
|
||||||
window.setTimeout(function () { self.modifySources(); }, 250);
|
|
||||||
this.wait = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (this.wait) {
|
|
||||||
window.setTimeout(function () { self.modifySources(); }, 2500);
|
|
||||||
this.wait = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var sdp = new SDP(this.peerconnection.remoteDescription.sdp);
|
|
||||||
|
|
||||||
// add sources
|
|
||||||
this.addssrc.forEach(function (lines, idx) {
|
|
||||||
sdp.media[idx] += lines;
|
|
||||||
});
|
|
||||||
this.addssrc = [];
|
|
||||||
|
|
||||||
// remove sources
|
|
||||||
this.removessrc.forEach(function (lines, idx) {
|
|
||||||
lines = lines.split('\r\n');
|
|
||||||
lines.pop(); // remove empty last element;
|
|
||||||
lines.forEach(function (line) {
|
|
||||||
sdp.media[idx] = sdp.media[idx].replace(line + '\r\n', '');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
this.removessrc = [];
|
|
||||||
|
|
||||||
sdp.raw = sdp.session + sdp.media.join('');
|
|
||||||
this.peerconnection.setRemoteDescription(
|
|
||||||
new RTCSessionDescription({type: 'offer', sdp: sdp.raw }),
|
|
||||||
function () {
|
|
||||||
console.log('setModifiedRemoteDescription ok');
|
|
||||||
self.peerconnection.createAnswer(
|
|
||||||
function (modifiedAnswer) {
|
|
||||||
console.log('modifiedAnswer created');
|
|
||||||
|
|
||||||
// change video direction, see https://github.com/jitsi/jitmeet/issues/41
|
|
||||||
if (self.pendingop !== null) {
|
|
||||||
var sdp = new SDP(modifiedAnswer.sdp);
|
|
||||||
if (sdp.media.length > 1) {
|
|
||||||
switch(self.pendingop) {
|
|
||||||
case 'mute':
|
|
||||||
sdp.media[1] = sdp.media[1].replace('a=sendrecv', 'a=recvonly');
|
|
||||||
break;
|
|
||||||
case 'unmute':
|
|
||||||
sdp.media[1] = sdp.media[1].replace('a=recvonly', 'a=sendrecv');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
sdp.raw = sdp.session + sdp.media.join('');
|
|
||||||
modifiedAnswer.sdp = sdp.raw;
|
|
||||||
}
|
|
||||||
self.pendingop = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: pushing down an answer while ice connection state
|
|
||||||
// is still checking is bad...
|
|
||||||
//console.log(self.peerconnection.iceConnectionState);
|
|
||||||
|
|
||||||
// trying to work around another chrome bug
|
|
||||||
//modifiedAnswer.sdp = modifiedAnswer.sdp.replace(/a=setup:active/g, 'a=setup:actpass');
|
|
||||||
self.peerconnection.setLocalDescription(modifiedAnswer,
|
|
||||||
function () {
|
|
||||||
console.log('setModifiedLocalDescription ok');
|
|
||||||
$(document).trigger('setLocalDescription.jingle', [self.sid]);
|
$(document).trigger('setLocalDescription.jingle', [self.sid]);
|
||||||
},
|
});
|
||||||
function (error) {
|
|
||||||
console.log('setModifiedLocalDescription failed', error);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
},
|
|
||||||
function (error) {
|
|
||||||
console.log('createModifiedAnswer failed', error);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
},
|
|
||||||
function (error) {
|
|
||||||
console.log('setModifiedRemoteDescription failed', error);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
/*
|
|
||||||
* now that we have a passive focus, this way is bad again! :-)
|
|
||||||
this.peerconnection.createOffer(
|
|
||||||
function (modifiedOffer) {
|
|
||||||
console.log('created (un)modified offer');
|
|
||||||
self.peerconnection.setLocalDescription(modifiedOffer,
|
|
||||||
function () {
|
|
||||||
console.log('setModifiedLocalDescription ok');
|
|
||||||
self.peerconnection.setRemoteDescription(
|
|
||||||
new RTCSessionDescription({type: 'answer', sdp: sdp.raw }),
|
|
||||||
function () {
|
|
||||||
console.log('setModifiedRemoteDescription ok');
|
|
||||||
},
|
|
||||||
function (error) {
|
|
||||||
console.log('setModifiedRemoteDescription failed');
|
|
||||||
}
|
|
||||||
);
|
|
||||||
$(document).trigger('setLocalDescription.jingle', [self.sid]);
|
|
||||||
},
|
|
||||||
function (error) {
|
|
||||||
console.log('setModifiedLocalDescription failed');
|
|
||||||
}
|
|
||||||
);
|
|
||||||
},
|
|
||||||
function (error) {
|
|
||||||
console.log('creating (un)modified offerfailed');
|
|
||||||
}
|
|
||||||
);
|
|
||||||
*/
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ColibriFocus.prototype.hardMuteVideo = function (muted) {
|
ColibriFocus.prototype.hardMuteVideo = function (muted) {
|
||||||
this.pendingop = muted ? 'mute' : 'unmute';
|
|
||||||
this.modifySources();
|
this.peerconnection.hardMuteVideo(muted);
|
||||||
|
|
||||||
this.connection.jingle.localStream.getVideoTracks().forEach(function (track) {
|
this.connection.jingle.localStream.getVideoTracks().forEach(function (track) {
|
||||||
track.enabled = !muted;
|
track.enabled = !muted;
|
||||||
|
|
|
@ -7,6 +7,24 @@ function TraceablePeerConnection(ice_config, constraints) {
|
||||||
this.statsinterval = null;
|
this.statsinterval = null;
|
||||||
this.maxstats = 300; // limit to 300 values, i.e. 5 minutes; set to 0 to disable
|
this.maxstats = 300; // limit to 300 values, i.e. 5 minutes; set to 0 to disable
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Array of ssrcs that will be added on next modifySources call.
|
||||||
|
* @type {Array}
|
||||||
|
*/
|
||||||
|
this.addssrc = [];
|
||||||
|
/**
|
||||||
|
* Array of ssrcs that will be added on next modifySources call.
|
||||||
|
* @type {Array}
|
||||||
|
*/
|
||||||
|
this.removessrc = [];
|
||||||
|
/**
|
||||||
|
* Pending operation that will be done during modifySources call.
|
||||||
|
* Currently 'mute'/'unmute' operations are supported.
|
||||||
|
*
|
||||||
|
* @type {String}
|
||||||
|
*/
|
||||||
|
this.pendingop = null;
|
||||||
|
|
||||||
// override as desired
|
// override as desired
|
||||||
this.trace = function(what, info) {
|
this.trace = function(what, info) {
|
||||||
//console.warn('WTRACE', what, info);
|
//console.warn('WTRACE', what, info);
|
||||||
|
@ -163,6 +181,173 @@ TraceablePeerConnection.prototype.setRemoteDescription = function (description,
|
||||||
*/
|
*/
|
||||||
};
|
};
|
||||||
|
|
||||||
|
TraceablePeerConnection.prototype.hardMuteVideo = function (muted) {
|
||||||
|
this.pendingop = muted ? 'mute' : 'unmute';
|
||||||
|
this.modifySources();
|
||||||
|
};
|
||||||
|
|
||||||
|
TraceablePeerConnection.prototype.enqueueAddSsrc = function(channel, ssrcLines) {
|
||||||
|
if (!this.addssrc[channel]) {
|
||||||
|
this.addssrc[channel] = '';
|
||||||
|
}
|
||||||
|
this.addssrc[channel] += ssrcLines;
|
||||||
|
}
|
||||||
|
|
||||||
|
TraceablePeerConnection.prototype.addSource = function (elem) {
|
||||||
|
console.log('addssrc', new Date().getTime());
|
||||||
|
console.log('ice', this.iceConnectionState);
|
||||||
|
var sdp = new SDP(this.remoteDescription.sdp);
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
$(elem).each(function (idx, content) {
|
||||||
|
var name = $(content).attr('name');
|
||||||
|
var lines = '';
|
||||||
|
tmp = $(content).find('>source[xmlns="urn:xmpp:jingle:apps:rtp:ssma:0"]');
|
||||||
|
tmp.each(function () {
|
||||||
|
var ssrc = $(this).attr('ssrc');
|
||||||
|
$(this).find('>parameter').each(function () {
|
||||||
|
lines += 'a=ssrc:' + ssrc + ' ' + $(this).attr('name');
|
||||||
|
if ($(this).attr('value') && $(this).attr('value').length)
|
||||||
|
lines += ':' + $(this).attr('value');
|
||||||
|
lines += '\r\n';
|
||||||
|
});
|
||||||
|
});
|
||||||
|
sdp.media.forEach(function(media, idx) {
|
||||||
|
if (!SDPUtil.find_line(media, 'a=mid:' + name))
|
||||||
|
return;
|
||||||
|
sdp.media[idx] += lines;
|
||||||
|
self.enqueueAddSsrc(idx, lines);
|
||||||
|
});
|
||||||
|
sdp.raw = sdp.session + sdp.media.join('');
|
||||||
|
});
|
||||||
|
this.modifySources();
|
||||||
|
};
|
||||||
|
|
||||||
|
TraceablePeerConnection.prototype.enqueueRemoveSsrc = function(channel, ssrcLines) {
|
||||||
|
if (!this.removessrc[channel]){
|
||||||
|
this.removessrc[channel] = '';
|
||||||
|
}
|
||||||
|
this.removessrc[channel] += ssrcLines;
|
||||||
|
}
|
||||||
|
|
||||||
|
TraceablePeerConnection.prototype.removeSource = function (elem) {
|
||||||
|
console.log('removessrc', new Date().getTime());
|
||||||
|
console.log('ice', this.iceConnectionState);
|
||||||
|
var sdp = new SDP(this.remoteDescription.sdp);
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
$(elem).each(function (idx, content) {
|
||||||
|
var name = $(content).attr('name');
|
||||||
|
var lines = '';
|
||||||
|
tmp = $(content).find('>source[xmlns="urn:xmpp:jingle:apps:rtp:ssma:0"]');
|
||||||
|
tmp.each(function () {
|
||||||
|
var ssrc = $(this).attr('ssrc');
|
||||||
|
$(this).find('>parameter').each(function () {
|
||||||
|
lines += 'a=ssrc:' + ssrc + ' ' + $(this).attr('name');
|
||||||
|
if ($(this).attr('value') && $(this).attr('value').length)
|
||||||
|
lines += ':' + $(this).attr('value');
|
||||||
|
lines += '\r\n';
|
||||||
|
});
|
||||||
|
});
|
||||||
|
sdp.media.forEach(function(media, idx) {
|
||||||
|
if (!SDPUtil.find_line(media, 'a=mid:' + name))
|
||||||
|
return;
|
||||||
|
sdp.media[idx] += lines;
|
||||||
|
self.enqueueRemoveSsrc(idx, lines);
|
||||||
|
});
|
||||||
|
sdp.raw = sdp.session + sdp.media.join('');
|
||||||
|
});
|
||||||
|
this.modifySources();
|
||||||
|
};
|
||||||
|
|
||||||
|
TraceablePeerConnection.prototype.modifySources = function(successCallback) {
|
||||||
|
var self = this;
|
||||||
|
if (this.signalingState == 'closed') return;
|
||||||
|
if (!(this.addssrc.length || this.removessrc.length || this.pendingop !== null)){
|
||||||
|
if(successCallback){
|
||||||
|
successCallback();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: this is a big hack
|
||||||
|
// https://code.google.com/p/webrtc/issues/detail?id=2688
|
||||||
|
if (!(this.signalingState == 'stable' && this.iceConnectionState == 'connected')) {
|
||||||
|
console.warn('modifySources not yet', this.signalingState, this.iceConnectionState);
|
||||||
|
this.wait = true;
|
||||||
|
window.setTimeout(function() { self.modifySources(); }, 250);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.wait) {
|
||||||
|
window.setTimeout(function() { self.modifySources(); }, 2500);
|
||||||
|
this.wait = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var sdp = new SDP(this.remoteDescription.sdp);
|
||||||
|
|
||||||
|
// add sources
|
||||||
|
this.addssrc.forEach(function(lines, idx) {
|
||||||
|
sdp.media[idx] += lines;
|
||||||
|
});
|
||||||
|
this.addssrc = [];
|
||||||
|
|
||||||
|
// remove sources
|
||||||
|
this.removessrc.forEach(function(lines, idx) {
|
||||||
|
lines = lines.split('\r\n');
|
||||||
|
lines.pop(); // remove empty last element;
|
||||||
|
lines.forEach(function(line) {
|
||||||
|
sdp.media[idx] = sdp.media[idx].replace(line + '\r\n', '');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
this.removessrc = [];
|
||||||
|
|
||||||
|
sdp.raw = sdp.session + sdp.media.join('');
|
||||||
|
this.setRemoteDescription(new RTCSessionDescription({type: 'offer', sdp: sdp.raw}),
|
||||||
|
function() {
|
||||||
|
self.createAnswer(
|
||||||
|
function(modifiedAnswer) {
|
||||||
|
// change video direction, see https://github.com/jitsi/jitmeet/issues/41
|
||||||
|
if (self.pendingop !== null) {
|
||||||
|
var sdp = new SDP(modifiedAnswer.sdp);
|
||||||
|
if (sdp.media.length > 1) {
|
||||||
|
switch(self.pendingop) {
|
||||||
|
case 'mute':
|
||||||
|
sdp.media[1] = sdp.media[1].replace('a=sendrecv', 'a=recvonly');
|
||||||
|
break;
|
||||||
|
case 'unmute':
|
||||||
|
sdp.media[1] = sdp.media[1].replace('a=recvonly', 'a=sendrecv');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
sdp.raw = sdp.session + sdp.media.join('');
|
||||||
|
modifiedAnswer.sdp = sdp.raw;
|
||||||
|
}
|
||||||
|
self.pendingop = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.setLocalDescription(modifiedAnswer,
|
||||||
|
function() {
|
||||||
|
//console.log('modified setLocalDescription ok');
|
||||||
|
if(successCallback){
|
||||||
|
successCallback();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
function(error) {
|
||||||
|
console.error('modified setLocalDescription failed', error);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
function(error) {
|
||||||
|
console.error('modified answer failed', error);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
function(error) {
|
||||||
|
console.error('modify failed', error);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
TraceablePeerConnection.prototype.close = function () {
|
TraceablePeerConnection.prototype.close = function () {
|
||||||
this.trace('stop');
|
this.trace('stop');
|
||||||
if (this.statsinterval !== null) {
|
if (this.statsinterval !== null) {
|
||||||
|
|
|
@ -9,7 +9,19 @@ function JingleSession(me, sid, connection) {
|
||||||
this.isInitiator = null;
|
this.isInitiator = null;
|
||||||
this.peerjid = null;
|
this.peerjid = null;
|
||||||
this.state = null;
|
this.state = null;
|
||||||
|
/**
|
||||||
|
* Peer connection instance.
|
||||||
|
* @type {TraceablePeerConnection}
|
||||||
|
*/
|
||||||
this.peerconnection = null;
|
this.peerconnection = null;
|
||||||
|
//console.log('create PeerConnection ' + JSON.stringify(this.ice_config));
|
||||||
|
try {
|
||||||
|
this.peerconnection = new RTCPeerconnection(this.ice_config, this.pc_constraints);
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Failed to create PeerConnection, exception: ', e.message);
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
|
||||||
this.remoteStream = null;
|
this.remoteStream = null;
|
||||||
this.localSDP = null;
|
this.localSDP = null;
|
||||||
this.remoteSDP = null;
|
this.remoteSDP = null;
|
||||||
|
@ -35,10 +47,6 @@ function JingleSession(me, sid, connection) {
|
||||||
|
|
||||||
this.reason = null;
|
this.reason = null;
|
||||||
|
|
||||||
this.addssrc = [];
|
|
||||||
this.removessrc = [];
|
|
||||||
this.pendingop = null;
|
|
||||||
|
|
||||||
this.wait = true;
|
this.wait = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,16 +62,6 @@ JingleSession.prototype.initiate = function (peerjid, isInitiator) {
|
||||||
this.initiator = isInitiator ? this.me : peerjid;
|
this.initiator = isInitiator ? this.me : peerjid;
|
||||||
this.responder = !isInitiator ? this.me : peerjid;
|
this.responder = !isInitiator ? this.me : peerjid;
|
||||||
this.peerjid = peerjid;
|
this.peerjid = peerjid;
|
||||||
//console.log('create PeerConnection ' + JSON.stringify(this.ice_config));
|
|
||||||
try {
|
|
||||||
this.peerconnection = new RTCPeerconnection(this.ice_config,
|
|
||||||
this.pc_constraints);
|
|
||||||
} catch (e) {
|
|
||||||
console.error('Failed to create PeerConnection, exception: ',
|
|
||||||
e.message);
|
|
||||||
console.error(e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.hadstuncandidate = false;
|
this.hadstuncandidate = false;
|
||||||
this.hadturncandidate = false;
|
this.hadturncandidate = false;
|
||||||
this.lasticecandidate = false;
|
this.lasticecandidate = false;
|
||||||
|
@ -635,150 +633,27 @@ JingleSession.prototype.sendTerminate = function (reason, text) {
|
||||||
|
|
||||||
|
|
||||||
JingleSession.prototype.addSource = function (elem) {
|
JingleSession.prototype.addSource = function (elem) {
|
||||||
console.log('addssrc', new Date().getTime());
|
|
||||||
console.log('ice', this.peerconnection.iceConnectionState);
|
|
||||||
var sdp = new SDP(this.peerconnection.remoteDescription.sdp);
|
|
||||||
|
|
||||||
var self = this;
|
this.peerconnection.addSource(elem);
|
||||||
$(elem).each(function (idx, content) {
|
|
||||||
var name = $(content).attr('name');
|
|
||||||
var lines = '';
|
|
||||||
tmp = $(content).find('>source[xmlns="urn:xmpp:jingle:apps:rtp:ssma:0"]');
|
|
||||||
tmp.each(function () {
|
|
||||||
var ssrc = $(this).attr('ssrc');
|
|
||||||
$(this).find('>parameter').each(function () {
|
|
||||||
lines += 'a=ssrc:' + ssrc + ' ' + $(this).attr('name');
|
|
||||||
if ($(this).attr('value') && $(this).attr('value').length)
|
|
||||||
lines += ':' + $(this).attr('value');
|
|
||||||
lines += '\r\n';
|
|
||||||
});
|
|
||||||
});
|
|
||||||
sdp.media.forEach(function(media, idx) {
|
|
||||||
if (!SDPUtil.find_line(media, 'a=mid:' + name))
|
|
||||||
return;
|
|
||||||
sdp.media[idx] += lines;
|
|
||||||
if (!self.addssrc[idx]) self.addssrc[idx] = '';
|
|
||||||
self.addssrc[idx] += lines;
|
|
||||||
});
|
|
||||||
sdp.raw = sdp.session + sdp.media.join('');
|
|
||||||
});
|
|
||||||
this.modifySources();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
JingleSession.prototype.removeSource = function (elem) {
|
JingleSession.prototype.removeSource = function (elem) {
|
||||||
console.log('removessrc', new Date().getTime());
|
|
||||||
console.log('ice', this.peerconnection.iceConnectionState);
|
|
||||||
var sdp = new SDP(this.peerconnection.remoteDescription.sdp);
|
|
||||||
|
|
||||||
var self = this;
|
this.peerconnection.removeSource(elem);
|
||||||
$(elem).each(function (idx, content) {
|
|
||||||
var name = $(content).attr('name');
|
|
||||||
var lines = '';
|
|
||||||
tmp = $(content).find('>source[xmlns="urn:xmpp:jingle:apps:rtp:ssma:0"]');
|
|
||||||
tmp.each(function () {
|
|
||||||
var ssrc = $(this).attr('ssrc');
|
|
||||||
$(this).find('>parameter').each(function () {
|
|
||||||
lines += 'a=ssrc:' + ssrc + ' ' + $(this).attr('name');
|
|
||||||
if ($(this).attr('value') && $(this).attr('value').length)
|
|
||||||
lines += ':' + $(this).attr('value');
|
|
||||||
lines += '\r\n';
|
|
||||||
});
|
|
||||||
});
|
|
||||||
sdp.media.forEach(function(media, idx) {
|
|
||||||
if (!SDPUtil.find_line(media, 'a=mid:' + name))
|
|
||||||
return;
|
|
||||||
sdp.media[idx] += lines;
|
|
||||||
if (!self.removessrc[idx]) self.removessrc[idx] = '';
|
|
||||||
self.removessrc[idx] += lines;
|
|
||||||
});
|
|
||||||
sdp.raw = sdp.session + sdp.media.join('');
|
|
||||||
});
|
|
||||||
this.modifySources();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
JingleSession.prototype.modifySources = function() {
|
JingleSession.prototype.modifySources = function() {
|
||||||
var self = this;
|
var self = this;
|
||||||
if (this.peerconnection.signalingState == 'closed') return;
|
this.peerconnection.modifySources(function(){
|
||||||
if (!(this.addssrc.length || this.removessrc.length || this.pendingop !== null)) return;
|
|
||||||
if (!(this.peerconnection.signalingState == 'stable' && this.peerconnection.iceConnectionState == 'connected')) {
|
|
||||||
console.warn('modifySources not yet', this.peerconnection.signalingState, this.peerconnection.iceConnectionState);
|
|
||||||
this.wait = true;
|
|
||||||
window.setTimeout(function() { self.modifySources(); }, 250);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (this.wait) {
|
|
||||||
window.setTimeout(function() { self.modifySources(); }, 2500);
|
|
||||||
this.wait = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var sdp = new SDP(this.peerconnection.remoteDescription.sdp);
|
|
||||||
|
|
||||||
// add sources
|
|
||||||
this.addssrc.forEach(function(lines, idx) {
|
|
||||||
sdp.media[idx] += lines;
|
|
||||||
});
|
|
||||||
this.addssrc = [];
|
|
||||||
|
|
||||||
// remove sources
|
|
||||||
this.removessrc.forEach(function(lines, idx) {
|
|
||||||
lines = lines.split('\r\n');
|
|
||||||
lines.pop(); // remove empty last element;
|
|
||||||
lines.forEach(function(line) {
|
|
||||||
sdp.media[idx] = sdp.media[idx].replace(line + '\r\n', '');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
this.removessrc = [];
|
|
||||||
|
|
||||||
sdp.raw = sdp.session + sdp.media.join('');
|
|
||||||
this.peerconnection.setRemoteDescription(new RTCSessionDescription({type: 'offer', sdp: sdp.raw}),
|
|
||||||
function() {
|
|
||||||
self.peerconnection.createAnswer(
|
|
||||||
function(modifiedAnswer) {
|
|
||||||
// change video direction, see https://github.com/jitsi/jitmeet/issues/41
|
|
||||||
if (self.pendingop !== null) {
|
|
||||||
var sdp = new SDP(modifiedAnswer.sdp);
|
|
||||||
if (sdp.media.length > 1) {
|
|
||||||
switch(self.pendingop) {
|
|
||||||
case 'mute':
|
|
||||||
sdp.media[1] = sdp.media[1].replace('a=sendrecv', 'a=recvonly');
|
|
||||||
break;
|
|
||||||
case 'unmute':
|
|
||||||
sdp.media[1] = sdp.media[1].replace('a=recvonly', 'a=sendrecv');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
sdp.raw = sdp.session + sdp.media.join('');
|
|
||||||
modifiedAnswer.sdp = sdp.raw;
|
|
||||||
}
|
|
||||||
self.pendingop = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.peerconnection.setLocalDescription(modifiedAnswer,
|
|
||||||
function() {
|
|
||||||
//console.log('modified setLocalDescription ok');
|
|
||||||
$(document).trigger('setLocalDescription.jingle', [self.sid]);
|
$(document).trigger('setLocalDescription.jingle', [self.sid]);
|
||||||
},
|
});
|
||||||
function(error) {
|
|
||||||
console.log('modified setLocalDescription failed');
|
|
||||||
}
|
|
||||||
);
|
|
||||||
},
|
|
||||||
function(error) {
|
|
||||||
console.log('modified answer failed');
|
|
||||||
}
|
|
||||||
);
|
|
||||||
},
|
|
||||||
function(error) {
|
|
||||||
console.log('modify failed');
|
|
||||||
}
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// SDP-based mute by going recvonly/sendrecv
|
// SDP-based mute by going recvonly/sendrecv
|
||||||
// FIXME: should probably black out the screen as well
|
// FIXME: should probably black out the screen as well
|
||||||
JingleSession.prototype.hardMuteVideo = function (muted) {
|
JingleSession.prototype.hardMuteVideo = function (muted) {
|
||||||
this.pendingop = muted ? 'mute' : 'unmute';
|
|
||||||
this.modifySources();
|
this.peerconnection.hardMuteVideo(muted);
|
||||||
|
|
||||||
this.connection.jingle.localStream.getVideoTracks().forEach(function (track) {
|
this.connection.jingle.localStream.getVideoTracks().forEach(function (track) {
|
||||||
track.enabled = !muted;
|
track.enabled = !muted;
|
||||||
|
|
Loading…
Reference in New Issue