|
@@ -7,107 +7,90 @@ |
|
|
* @augments JsSIP |
|
|
* @class PeerConnection helper Class. |
|
|
* @param {JsSIP.Session} session |
|
|
* @param {HTMLVideoElement} selfView |
|
|
* @param {HTMLVideoElement} remoteView |
|
|
*/ |
|
|
JsSIP.MediaSession = function(session, selfView, remoteView) { |
|
|
JsSIP.MediaSession = function(session, RTCConstraints) { |
|
|
RTCConstraints = RTCConstraints || {}; |
|
|
|
|
|
this.session = session; |
|
|
this.selfView = selfView || null; |
|
|
this.remoteView = remoteView || null; |
|
|
this.localMedia = null; |
|
|
this.peerConnection = null; |
|
|
|
|
|
this.init(RTCConstraints); |
|
|
}; |
|
|
|
|
|
JsSIP.MediaSession.prototype = { |
|
|
/** |
|
|
* Establish peerConnection for Caller. |
|
|
* <br> - Prompt the user for permission to use the Web cam or other video or audio input. |
|
|
* <br> -- If the user consents, create a peerConnection. |
|
|
* <br> -- If the user doesn't consent, fire onFailure callback. |
|
|
* |
|
|
* @param {Object} mediaTypes {audio:true/false, video:true/false} |
|
|
* @param {Function} onSuccess |
|
|
* @param {Function} onFailure |
|
|
*/ |
|
|
startCaller: function(mediaTypes, onSuccess, onFailure) { |
|
|
var self = this; |
|
|
|
|
|
/** @private */ |
|
|
function onGetUserMediaSuccess(stream) { |
|
|
// Start peerConnection |
|
|
self.start(onSuccess); |
|
|
createOffer: function(onSuccess, onFailure, constraints) { |
|
|
var |
|
|
self = this, |
|
|
sent = false; |
|
|
|
|
|
// add stream to peerConnection |
|
|
self.peerConnection.addStream(stream); |
|
|
this.onIceCompleted = function() { |
|
|
if (!sent) { |
|
|
sent = true; |
|
|
onSuccess(self.peerConnection.localDescription.sdp); |
|
|
} |
|
|
}; |
|
|
|
|
|
// Set local description and start Ice. |
|
|
self.peerConnection.createOffer(function(sessionDescription){ |
|
|
self.peerConnection.setLocalDescription(sessionDescription); |
|
|
}); |
|
|
} |
|
|
this.peerConnection.createOffer( |
|
|
function(sessionDescription){ |
|
|
self.peerConnection.setLocalDescription( |
|
|
sessionDescription, |
|
|
null, |
|
|
onFailure |
|
|
); |
|
|
}, |
|
|
onFailure, |
|
|
constraints.offerConstraints |
|
|
); |
|
|
}, |
|
|
|
|
|
/** @private */ |
|
|
function onGetUserMediaFailure(e) { |
|
|
onFailure(e); |
|
|
} |
|
|
createAnswer: function(onSuccess, onFailure, constraints) { |
|
|
var |
|
|
self = this, |
|
|
sent = false; |
|
|
|
|
|
this.getUserMedia(mediaTypes, onGetUserMediaSuccess, onGetUserMediaFailure); |
|
|
this.onIceCompleted = function() { |
|
|
if (!sent) { |
|
|
sent = true; |
|
|
onSuccess(self.peerConnection.localDescription.sdp); |
|
|
} |
|
|
}; |
|
|
|
|
|
this.peerConnection.createAnswer( |
|
|
function(sessionDescription){ |
|
|
self.peerConnection.setLocalDescription( |
|
|
sessionDescription, |
|
|
null, |
|
|
onFailure |
|
|
); |
|
|
}, |
|
|
onFailure, |
|
|
constraints.answerConstraints |
|
|
); |
|
|
}, |
|
|
|
|
|
/** |
|
|
* Establish peerConnection for Callee. |
|
|
* <br> - Prompt the user for permission to use the Web cam or other video or audio input. |
|
|
* <br> -- If the user consents, create a peerConnection. |
|
|
* <br> -- If the user doesn't consent, fire onMediaFailure callback. |
|
|
* <br> |
|
|
* <br> - Set the received SDP offer to the just created peerConnection. |
|
|
* <br> -- If the SDP offer is not valid, fire onSdpFailure callback. |
|
|
* <br> -- If the SDP offer is valid, fire onSuccess callback |
|
|
* |
|
|
* @param {Function} onSuccess |
|
|
* @param {Function} onMediaFailure |
|
|
* @param {Function} onSdpFailure |
|
|
* @param {String} sdp |
|
|
*/ |
|
|
startCallee: function(onSuccess, onMediaFailure, onSdpFailure, sdp) { |
|
|
addStream: function(onSuccess, onFailure, constraints) { |
|
|
var self = this; |
|
|
|
|
|
function onGetUserMediaSuccess(stream) { |
|
|
// Start peerConnection |
|
|
self.start(onSuccess); |
|
|
|
|
|
// add stream to peerConnection |
|
|
self.peerConnection.addStream(stream); |
|
|
|
|
|
self.peerConnection.setRemoteDescription( |
|
|
new JsSIP.WebRTC.RTCSessionDescription({type:'offer', sdp:sdp}), |
|
|
function() { |
|
|
self.peerConnection.createAnswer( |
|
|
function(sessionDescription){ |
|
|
self.peerConnection.setLocalDescription(sessionDescription); |
|
|
}, |
|
|
onSdpFailure |
|
|
); |
|
|
}, |
|
|
onSdpFailure |
|
|
); |
|
|
} |
|
|
|
|
|
function onGetUserMediaFailure(e) { |
|
|
onMediaFailure(e); |
|
|
} |
|
|
|
|
|
self.getUserMedia({'audio':true, 'video':true}, onGetUserMediaSuccess, onGetUserMediaFailure); |
|
|
}, |
|
|
this.getUserMedia(constraints.userMediaConstraints, |
|
|
function(stream) { |
|
|
self.peerConnection.addStream(stream, constraints.streamConstraints); |
|
|
onSuccess(); |
|
|
}, |
|
|
function(e) { |
|
|
onFailure(e); |
|
|
} |
|
|
); |
|
|
}, |
|
|
|
|
|
/** |
|
|
* peerConnection creation. |
|
|
* @param {Function} onSuccess Fired when there are no more ICE candidates |
|
|
*/ |
|
|
start: function(onSuccess) { |
|
|
init: function(RTCConstraints) { |
|
|
var idx, server, scheme, url, |
|
|
session = this, |
|
|
sent = false, |
|
|
self = this, |
|
|
servers = []; |
|
|
|
|
|
for (idx in this.session.ua.configuration.stun_servers) { |
|
@@ -125,41 +108,40 @@ JsSIP.MediaSession.prototype = { |
|
|
}); |
|
|
} |
|
|
|
|
|
this.peerConnection = new JsSIP.WebRTC.RTCPeerConnection({'iceServers': servers}); |
|
|
|
|
|
this.peerConnection.onicecandidate = function(event) { |
|
|
if (event.candidate) { |
|
|
console.log(JsSIP.C.LOG_MEDIA_SESSION + 'ICE candidate received: '+ event.candidate.candidate); |
|
|
} else { |
|
|
console.log(JsSIP.C.LOG_MEDIA_SESSION + 'no more ICE candidates'); |
|
|
console.log(JsSIP.C.LOG_MEDIA_SESSION + 'PeerConnection state: '+ this.readyState); |
|
|
console.log(JsSIP.C.LOG_MEDIA_SESSION + 'ICE state: '+ this.iceState); |
|
|
if (!sent) { // Execute onSuccess just once. |
|
|
sent = true; |
|
|
onSuccess(); |
|
|
} |
|
|
} |
|
|
}; |
|
|
this.peerConnection = new JsSIP.WebRTC.RTCPeerConnection({'iceServers': servers}, RTCConstraints); |
|
|
|
|
|
this.peerConnection.mediaSession = self; |
|
|
|
|
|
this.peerConnection.onopen = function() { |
|
|
console.log(JsSIP.C.LOG_MEDIA_SESSION +'media session opened'); |
|
|
}; |
|
|
|
|
|
this.peerConnection.onaddstream = function(mediaStreamEvent) { |
|
|
console.log(JsSIP.C.LOG_MEDIA_SESSION +'stream added'); |
|
|
this.peerConnection.onaddstream = function(e) { |
|
|
console.log(JsSIP.C.LOG_MEDIA_SESSION +'stream added: '+ e.stream.id); |
|
|
}; |
|
|
|
|
|
this.peerConnection.onremovestream = function(e) { |
|
|
console.log(JsSIP.C.LOG_MEDIA_SESSION +'stream removed: '+ e.stream.id); |
|
|
}; |
|
|
|
|
|
this.peerConnection.onicecandidate = function(e) { |
|
|
if (e.candidate) { |
|
|
console.log(JsSIP.C.LOG_MEDIA_SESSION + 'ICE candidate received: '+ e.candidate.candidate); |
|
|
} |
|
|
}; |
|
|
|
|
|
if (session.remoteView && this.getRemoteStreams().length > 0) { |
|
|
session.remoteView.src = window.URL.createObjectURL(mediaStreamEvent.stream); |
|
|
this.peerConnection.ongatheringchange = function(e) { |
|
|
if (e.currentTarget.iceGatheringState === 'complete' && this.iceConnectionState !== 'closed') { |
|
|
this.mediaSession.onIceCompleted(); |
|
|
} |
|
|
}; |
|
|
|
|
|
this.peerConnection.onremovestream = function(stream) { |
|
|
console.log(JsSIP.C.LOG_MEDIA_SESSION +'stream removed: '+ stream); |
|
|
this.peerConnection.onicechange = function() { |
|
|
console.log(JsSIP.C.LOG_MEDIA_SESSION + 'ICE connection state changed to "'+ this.iceConnectionState +'"'); |
|
|
}; |
|
|
|
|
|
this.peerConnection.onstatechange = function() { |
|
|
console.log(JsSIP.C.LOG_MEDIA_SESSION + 'PeerConnection state changed to '+ this.readyState); |
|
|
console.log(JsSIP.C.LOG_MEDIA_SESSION + 'ICE state: '+ this.iceState); |
|
|
console.log(JsSIP.C.LOG_MEDIA_SESSION + 'PeerConnection state changed to "'+ this.readyState +'"'); |
|
|
}; |
|
|
}, |
|
|
|
|
@@ -175,50 +157,39 @@ JsSIP.MediaSession.prototype = { |
|
|
}, |
|
|
|
|
|
/** |
|
|
* @param {Object} mediaTypes |
|
|
* @param {Object} mediaConstraints |
|
|
* @param {Function} onSuccess |
|
|
* @param {Function} onFailure |
|
|
*/ |
|
|
getUserMedia: function(mediaTypes, onSuccess, onFailure) { |
|
|
getUserMedia: function(mediaConstraints, onSuccess, onFailure) { |
|
|
var self = this; |
|
|
|
|
|
function getSuccess(stream) { |
|
|
console.log(JsSIP.C.LOG_MEDIA_SESSION + 'got stream: ' + stream); |
|
|
|
|
|
//Save the localMedia in order to revoke access to devices later. |
|
|
self.localMedia = stream; |
|
|
|
|
|
// Attach the stream to the view if it exists. |
|
|
if (self.selfView){ |
|
|
self.selfView.src = window.URL.createObjectURL(stream); |
|
|
} |
|
|
|
|
|
onSuccess(stream); |
|
|
} |
|
|
|
|
|
function getFailure(e) { |
|
|
onFailure(e); |
|
|
} |
|
|
|
|
|
// Get User Media |
|
|
console.log(JsSIP.C.LOG_MEDIA_SESSION + 'requesting access to local media'); |
|
|
JsSIP.WebRTC.getUserMedia(mediaTypes, getSuccess, getFailure); |
|
|
|
|
|
JsSIP.WebRTC.getUserMedia(mediaConstraints, |
|
|
function(stream) { |
|
|
console.log(JsSIP.C.LOG_MEDIA_SESSION + 'got stream'); |
|
|
self.localMedia = stream; |
|
|
onSuccess(stream); |
|
|
}, |
|
|
function(e) { |
|
|
onFailure(e); |
|
|
} |
|
|
); |
|
|
}, |
|
|
|
|
|
/** |
|
|
* Message reception once PeerConnection is active. |
|
|
* Message reception. |
|
|
* @param {String} type |
|
|
* @param {String} sdp |
|
|
* @param {Function} onSuccess |
|
|
* @param {Function} onFailure |
|
|
*/ |
|
|
onMessage: function(type, sdp, onSuccess, onFailure) { |
|
|
if (type === 'offer') { |
|
|
console.log(JsSIP.C.LOG_MEDIA_SESSION +'new SDP offer received'); |
|
|
} else if (type === 'answer') { |
|
|
this.peerConnection.setRemoteDescription( |
|
|
new JsSIP.WebRTC.RTCSessionDescription({type:'answer', sdp:sdp}), onSuccess, onFailure); |
|
|
} |
|
|
onMessage: function(type, body, onSuccess, onFailure) { |
|
|
this.peerConnection.setRemoteDescription( |
|
|
new JsSIP.WebRTC.RTCSessionDescription({type: type, sdp:body}), |
|
|
onSuccess, |
|
|
onFailure |
|
|
); |
|
|
} |
|
|
};
|
This comment has been minimized.
saghul repliedFeb 19, 2013
What. The. Fuck.
This comment has been minimized.
rvulpescu repliedFeb 19, 2013
A much better rewrite, great job!
This comment has been minimized.
saghul repliedFeb 19, 2013
Don't get too attached to it, this was prematurely committed and API will change a bit.