|
|
|
@ -109,6 +109,20 @@ ColibriFocus.prototype.makeConference = function (peers) { |
|
|
|
|
}); |
|
|
|
|
$(document).trigger('remotestreamadded.jingle', [event, self.sid]); |
|
|
|
|
}; |
|
|
|
|
this.peerconnection.onicecandidate = function (event) { |
|
|
|
|
//console.log('focus onicecandidate', self.confid, new Date().getTime(), event.candidate);
|
|
|
|
|
if (!event.candidate) { |
|
|
|
|
console.log('end of candidates'); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
if (self.confid === 0) { |
|
|
|
|
self.drip_container.push(event.candidate); |
|
|
|
|
} else { |
|
|
|
|
self.sendIceCandidate(event.candidate); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
this._makeConference(); |
|
|
|
|
/* |
|
|
|
|
this.peerconnection.createOffer( |
|
|
|
|
function (offer) { |
|
|
|
|
self.peerconnection.setLocalDescription( |
|
|
|
@ -128,18 +142,7 @@ ColibriFocus.prototype.makeConference = function (peers) { |
|
|
|
|
console.warn(error); |
|
|
|
|
} |
|
|
|
|
); |
|
|
|
|
this.peerconnection.onicecandidate = function (event) { |
|
|
|
|
//console.log('focus onicecandidate', self.confid, new Date().getTime(), event.candidate);
|
|
|
|
|
if (!event.candidate) { |
|
|
|
|
console.log('end of candidates'); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
if (self.confid === 0) { |
|
|
|
|
self.drip_container.push(event.candidate); |
|
|
|
|
} else { |
|
|
|
|
self.sendIceCandidate(candidate); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
*/ |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
ColibriFocus.prototype._makeConference = function () { |
|
|
|
@ -147,6 +150,23 @@ ColibriFocus.prototype._makeConference = function () { |
|
|
|
|
var elem = $iq({to: this.bridgejid, type: 'get'}); |
|
|
|
|
elem.c('conference', {xmlns: 'http://jitsi.org/protocol/colibri'}); |
|
|
|
|
|
|
|
|
|
var stream = this.connection.jingle.localStream; |
|
|
|
|
var types = []; |
|
|
|
|
if (connection.jingle.localStream.getAudioTracks().length > 0) { |
|
|
|
|
types.push('audio'); |
|
|
|
|
} |
|
|
|
|
if (connection.jingle.localStream.getVideoTracks().length > 0) { |
|
|
|
|
types.push('video'); |
|
|
|
|
} |
|
|
|
|
types.forEach(function (name) { |
|
|
|
|
elem.c('content', {name: name}); |
|
|
|
|
elem.c('channel', {initiator: 'true', expire: '15'}).up(); |
|
|
|
|
for (var j = 0; j < self.peers.length; j++) { |
|
|
|
|
elem.c('channel', {initiator: 'true', expire:'15' }).up(); |
|
|
|
|
} |
|
|
|
|
elem.up(); // end of content
|
|
|
|
|
}); |
|
|
|
|
/* |
|
|
|
|
var localSDP = new SDP(this.peerconnection.localDescription.sdp); |
|
|
|
|
localSDP.media.forEach(function (media, channel) { |
|
|
|
|
var name = SDPUtil.parse_mline(media.split('\r\n')[0]).media;
|
|
|
|
@ -169,6 +189,7 @@ ColibriFocus.prototype._makeConference = function () { |
|
|
|
|
} |
|
|
|
|
elem.up(); // end of content
|
|
|
|
|
}); |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
this.connection.sendIQ(elem, |
|
|
|
|
function (result) { |
|
|
|
@ -200,25 +221,13 @@ ColibriFocus.prototype.createdConference = function (result) { |
|
|
|
|
this.channels[j].push(tmp[j]); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
console.log('remote channels', this.channels); |
|
|
|
|
var localSDP = new SDP(this.peerconnection.localDescription.sdp); |
|
|
|
|
localSDP.removeSessionLines('a=group:'); |
|
|
|
|
localSDP.removeSessionLines('a=msid-semantic:'); |
|
|
|
|
|
|
|
|
|
if (this.drip_container.length) { |
|
|
|
|
this.sendIceCandidates(this.drip_container); |
|
|
|
|
this.drip_container = []; |
|
|
|
|
} |
|
|
|
|
console.log('remote channels', this.channels); |
|
|
|
|
|
|
|
|
|
// establish our channel with the bridge
|
|
|
|
|
// static answer taken from chrome M31, should be replaced by a
|
|
|
|
|
// dynamic one that is based on our offer FIXME
|
|
|
|
|
var bridgeSDP = new SDP(""); |
|
|
|
|
// var bridgeSDP = new SDP('v=0\r\no=- 5151055458874951233 2 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\nm=audio 1 RTP/SAVPF 111 103 104 0 8 106 105 13 126\r\nc=IN IP4 0.0.0.0\r\na=rtcp:1 IN IP4 0.0.0.0\r\na=mid:audio\r\na=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\na=sendrecv\r\na=rtpmap:111 opus/48000/2\r\na=fmtp:111 minptime=10\r\na=rtpmap:103 ISAC/16000\r\na=rtpmap:104 ISAC/32000\r\na=rtpmap:0 PCMU/8000\r\na=rtpmap:8 PCMA/8000\r\na=rtpmap:106 CN/32000\r\na=rtpmap:105 CN/16000\r\na=rtpmap:13 CN/8000\r\na=rtpmap:126 telephone-event/8000\r\na=maxptime:60\r\nm=video 1 RTP/SAVPF 100 116 117\r\nc=IN IP4 0.0.0.0\r\na=rtcp:1 IN IP4 0.0.0.0\r\na=mid:video\r\na=extmap:2 urn:ietf:params:rtp-hdrext:toffset\r\na=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\r\na=sendrecv\r\na=rtpmap:100 VP8/90000\r\na=rtcp-fb:100 ccm fir\r\na=rtcp-fb:100 nack\r\na=rtcp-fb:100 goog-remb\r\na=rtpmap:116 red/90000\r\na=rtpmap:117 ulpfec/90000\r\n');
|
|
|
|
|
// only do what's in the offer
|
|
|
|
|
bridgeSDP.session = localSDP.session; |
|
|
|
|
bridgeSDP.media.length = localSDP.media.length; |
|
|
|
|
var bridgeSDP = new SDP('v=0\r\no=- 5151055458874951233 2 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\nm=audio 1 RTP/SAVPF 111 103 104 0 8 106 105 13 126\r\nc=IN IP4 0.0.0.0\r\na=rtcp:1 IN IP4 0.0.0.0\r\na=mid:audio\r\na=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\na=sendrecv\r\na=rtpmap:111 opus/48000/2\r\na=fmtp:111 minptime=10\r\na=rtpmap:103 ISAC/16000\r\na=rtpmap:104 ISAC/32000\r\na=rtpmap:0 PCMU/8000\r\na=rtpmap:8 PCMA/8000\r\na=rtpmap:106 CN/32000\r\na=rtpmap:105 CN/16000\r\na=rtpmap:13 CN/8000\r\na=rtpmap:126 telephone-event/8000\r\na=maxptime:60\r\nm=video 1 RTP/SAVPF 100 116 117\r\nc=IN IP4 0.0.0.0\r\na=rtcp:1 IN IP4 0.0.0.0\r\na=mid:video\r\na=extmap:2 urn:ietf:params:rtp-hdrext:toffset\r\na=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\r\na=sendrecv\r\na=rtpmap:100 VP8/90000\r\na=rtcp-fb:100 ccm fir\r\na=rtcp-fb:100 nack\r\na=rtcp-fb:100 goog-remb\r\na=rtpmap:116 red/90000\r\na=rtpmap:117 ulpfec/90000\r\n'); |
|
|
|
|
bridgeSDP.media.length = this.mychannel.length; |
|
|
|
|
var channel; |
|
|
|
|
/* |
|
|
|
|
for (channel = 0; channel < bridgeSDP.media.length; channel++) { |
|
|
|
|
bridgeSDP.media[channel] = ''; |
|
|
|
|
// unchanged lines
|
|
|
|
@ -249,8 +258,9 @@ ColibriFocus.prototype.createdConference = function (result) { |
|
|
|
|
} |
|
|
|
|
// FIXME: changed lines -- a=sendrecv direction, a=setup direction
|
|
|
|
|
} |
|
|
|
|
// get the mixed ssrc
|
|
|
|
|
*/ |
|
|
|
|
for (channel = 0; channel < bridgeSDP.media.length; channel++) { |
|
|
|
|
// get the mixed ssrc
|
|
|
|
|
tmp = $(this.mychannel[channel]).find('>source[xmlns="urn:xmpp:jingle:apps:rtp:ssma:0"]'); |
|
|
|
|
// FIXME: check rtp-level-relay-type
|
|
|
|
|
if (tmp.length) { |
|
|
|
@ -278,26 +288,83 @@ ColibriFocus.prototype.createdConference = function (result) { |
|
|
|
|
tmp = tmp.find('>fingerprint'); |
|
|
|
|
if (tmp.length) { |
|
|
|
|
bridgeSDP.media[channel] += 'a=fingerprint:' + tmp.attr('hash') + ' ' + tmp.text() + '\r\n'; |
|
|
|
|
if (tmp.attr('setup')) { |
|
|
|
|
bridgeSDP.media[channel] += 'a=setup:' + tmp.attr('setup') + '\r\n'; |
|
|
|
|
} else { |
|
|
|
|
bridgeSDP.media[channel] += 'a=setup:active\r\n'; |
|
|
|
|
} |
|
|
|
|
bridgeSDP.media[channel] += 'a=setup:actpass\r\n'; // offer so always actpass
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
bridgeSDP.raw = bridgeSDP.session + bridgeSDP.media.join(''); |
|
|
|
|
|
|
|
|
|
this.peerconnection.setRemoteDescription( |
|
|
|
|
new RTCSessionDescription({type: 'answer', sdp: bridgeSDP.raw}), |
|
|
|
|
new RTCSessionDescription({type: 'offer', sdp: bridgeSDP.raw}), |
|
|
|
|
function () { |
|
|
|
|
console.log('setRemoteDescription success'); |
|
|
|
|
self.peerconnection.createAnswer( |
|
|
|
|
function (answer) { |
|
|
|
|
self.peerconnection.setLocalDescription(answer, |
|
|
|
|
function () { |
|
|
|
|
console.log('setLocalDescription succeded.'); |
|
|
|
|
// make sure our presence is updated
|
|
|
|
|
$(document).trigger('setLocalDescription.jingle', [self.sid]); |
|
|
|
|
var elem = $iq({to: self.bridgejid, type: 'get'}); |
|
|
|
|
elem.c('conference', {xmlns: 'http://jitsi.org/protocol/colibri', id: self.confid}); |
|
|
|
|
var localSDP = new SDP(self.peerconnection.localDescription.sdp); |
|
|
|
|
localSDP.media.forEach(function (media, channel) { |
|
|
|
|
var name = SDPUtil.parse_mline(media.split('\r\n')[0]).media;
|
|
|
|
|
elem.c('content', {name: name}); |
|
|
|
|
elem.c('channel', { |
|
|
|
|
initiator: 'true',
|
|
|
|
|
expire: '15', |
|
|
|
|
id: self.mychannel[channel].attr('id') |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
// FIXME: should reuse code from .toJingle
|
|
|
|
|
var mline = SDPUtil.parse_mline(media.split('\r\n')[0]); |
|
|
|
|
for (var j = 0; j < mline.fmt.length; j++) { |
|
|
|
|
var rtpmap = SDPUtil.find_line(media, 'a=rtpmap:' + mline.fmt[j]); |
|
|
|
|
elem.c('payload-type', SDPUtil.parse_rtpmap(rtpmap)); |
|
|
|
|
elem.up(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
localSDP.TransportToJingle(channel, elem); |
|
|
|
|
|
|
|
|
|
elem.up(); // end of channel
|
|
|
|
|
for (j = 0; j < self.peers.length; j++) { |
|
|
|
|
elem.c('channel', {initiator: 'true', expire:'15' }).up(); |
|
|
|
|
} |
|
|
|
|
elem.up(); // end of content
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
self.connection.sendIQ(elem, |
|
|
|
|
function (result) { |
|
|
|
|
// ...
|
|
|
|
|
}, |
|
|
|
|
function (error) { |
|
|
|
|
console.warn(error); |
|
|
|
|
} |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
// now initiate sessions
|
|
|
|
|
for (var i = 0; i < numparticipants; i++) { |
|
|
|
|
self.initiate(self.peers[i], true); |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
function (error) { |
|
|
|
|
console.warn('setLocalDescription failed.', error); |
|
|
|
|
} |
|
|
|
|
); |
|
|
|
|
}, |
|
|
|
|
function (error) { |
|
|
|
|
console.warn('createAnswer failed.', error); |
|
|
|
|
} |
|
|
|
|
); |
|
|
|
|
/* |
|
|
|
|
for (var i = 0; i < numparticipants; i++) { |
|
|
|
|
self.initiate(self.peers[i], true); |
|
|
|
|
} |
|
|
|
|
*/ |
|
|
|
|
}, |
|
|
|
|
function (error) { |
|
|
|
|
console.log('setRemoteDescription failed'); |
|
|
|
|
console.log('setRemoteDescription failed.', error); |
|
|
|
|
} |
|
|
|
|
); |
|
|
|
|
|
|
|
|
@ -674,6 +741,7 @@ ColibriFocus.prototype.sendIceCandidates = function (candidates) { |
|
|
|
|
mycands.up(); // content
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
console.log('send cands', candidates); |
|
|
|
|
this.connection.sendIQ(mycands, |
|
|
|
|
function (res) { |
|
|
|
|
console.log('got result'); |
|
|
|
@ -769,8 +837,6 @@ ColibriFocus.prototype.modifySources = function () { |
|
|
|
|
this.removessrc = []; |
|
|
|
|
|
|
|
|
|
sdp.raw = sdp.session + sdp.media.join(''); |
|
|
|
|
/* |
|
|
|
|
* this seems to create a number of problems... |
|
|
|
|
this.peerconnection.setRemoteDescription( |
|
|
|
|
new RTCSessionDescription({type: 'offer', sdp: sdp.raw }), |
|
|
|
|
function () { |
|
|
|
@ -803,7 +869,8 @@ ColibriFocus.prototype.modifySources = function () { |
|
|
|
|
console.log('setModifiedRemoteDescription failed'); |
|
|
|
|
} |
|
|
|
|
); |
|
|
|
|
*/ |
|
|
|
|
/* |
|
|
|
|
* now that we have a passive focus, this way is bad again! :-) |
|
|
|
|
this.peerconnection.createOffer( |
|
|
|
|
function (modifiedOffer) { |
|
|
|
|
console.log('created (un)modified offer'); |
|
|
|
@ -830,6 +897,7 @@ ColibriFocus.prototype.modifySources = function () { |
|
|
|
|
console.log('creating (un)modified offerfailed'); |
|
|
|
|
} |
|
|
|
|
); |
|
|
|
|
*/ |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|