archive
This commit is contained in:
89
comms/webRTC-over-websockets/js/adapter.js
Normal file
89
comms/webRTC-over-websockets/js/adapter.js
Normal file
@@ -0,0 +1,89 @@
|
||||
var RTCPeerConnection = null;
|
||||
var getUserMedia = null;
|
||||
var attachMediaStream = null;
|
||||
var reattachMediaStream = null;
|
||||
var webrtcDetectedBrowser = null;
|
||||
|
||||
if (navigator.mozGetUserMedia) {
|
||||
console.log("This appears to be Firefox");
|
||||
|
||||
webrtcDetectedBrowser = "firefox";
|
||||
|
||||
// The RTCPeerConnection object.
|
||||
RTCPeerConnection = mozRTCPeerConnection;
|
||||
|
||||
// The RTCSessionDescription object.
|
||||
RTCSessionDescription = mozRTCSessionDescription;
|
||||
|
||||
// The RTCIceCandidate object.
|
||||
RTCIceCandidate = mozRTCIceCandidate;
|
||||
|
||||
// Get UserMedia (only difference is the prefix).
|
||||
// Code from Adam Barth.
|
||||
getUserMedia = navigator.mozGetUserMedia.bind(navigator);
|
||||
|
||||
// Attach a media stream to an element.
|
||||
attachMediaStream = function(element, stream) {
|
||||
console.log("Attaching media stream");
|
||||
element.mozSrcObject = stream;
|
||||
element.play();
|
||||
};
|
||||
|
||||
reattachMediaStream = function(to, from) {
|
||||
console.log("Reattaching media stream");
|
||||
to.mozSrcObject = from.mozSrcObject;
|
||||
to.play();
|
||||
};
|
||||
|
||||
// Fake get{Video,Audio}Tracks
|
||||
MediaStream.prototype.getVideoTracks = function() {
|
||||
return [];
|
||||
};
|
||||
|
||||
MediaStream.prototype.getAudioTracks = function() {
|
||||
return [];
|
||||
};
|
||||
} else if (navigator.webkitGetUserMedia) {
|
||||
console.log("This appears to be Chrome");
|
||||
|
||||
webrtcDetectedBrowser = "chrome";
|
||||
|
||||
// The RTCPeerConnection object.
|
||||
RTCPeerConnection = webkitRTCPeerConnection;
|
||||
|
||||
// Get UserMedia (only difference is the prefix).
|
||||
// Code from Adam Barth.
|
||||
getUserMedia = navigator.webkitGetUserMedia.bind(navigator);
|
||||
|
||||
// Attach a media stream to an element.
|
||||
attachMediaStream = function(element, stream) {
|
||||
element.src = webkitURL.createObjectURL(stream);
|
||||
};
|
||||
|
||||
reattachMediaStream = function(to, from) {
|
||||
to.src = from.src;
|
||||
};
|
||||
|
||||
// The representation of tracks in a stream is changed in M26.
|
||||
// Unify them for earlier Chrome versions in the coexisting period.
|
||||
if (!webkitMediaStream.prototype.getVideoTracks) {
|
||||
webkitMediaStream.prototype.getVideoTracks = function() {
|
||||
return this.videoTracks;
|
||||
};
|
||||
webkitMediaStream.prototype.getAudioTracks = function() {
|
||||
return this.audioTracks;
|
||||
};
|
||||
}
|
||||
|
||||
// New syntax of getXXXStreams method in M26.
|
||||
if (!webkitRTCPeerConnection.prototype.getLocalStreams) {
|
||||
webkitRTCPeerConnection.prototype.getLocalStreams = function() {
|
||||
return this.localStreams;
|
||||
};
|
||||
webkitRTCPeerConnection.prototype.getRemoteStreams = function() {
|
||||
return this.remoteStreams;
|
||||
};
|
||||
}
|
||||
} else {
|
||||
console.log("Browser does not appear to be WebRTC-capable");
|
||||
}
|
||||
36
comms/webRTC-over-websockets/js/bandwidth.js
Normal file
36
comms/webRTC-over-websockets/js/bandwidth.js
Normal file
@@ -0,0 +1,36 @@
|
||||
//http://stackoverflow.com/questions/4583395/calculate-speed-using-javascript
|
||||
/*
|
||||
this is only download estimation, obviously, in peer2peer default deployment, you will
|
||||
have full mesh, n*times both upstream and donwstream stream comming to you (which is bad,
|
||||
but unless you have a server in between this is what it is). Remark: simetrical upstream/downstream
|
||||
is not common in DSL deplyoment, where downstream bandwith is much higher.
|
||||
*/
|
||||
var BANDWITDH = (function(){
|
||||
var imageAddr;
|
||||
var size;
|
||||
var startTime, endTime;
|
||||
var downloadSize;
|
||||
var download = new Image();
|
||||
|
||||
return {
|
||||
/*
|
||||
don't forget to change the address every time you make a request to avoid browser caching.
|
||||
For a demo, I will be using the same as in the stackoverflow example
|
||||
*/
|
||||
init: function(callback, address, size){
|
||||
imageAddr = address !== undefined ? address : "http://www.tranquilmusic.ca/images/cats/Cat2.JPG" + "?n=" + Math.random();
|
||||
downloadSize = size !== undefined ? size : 5616998;
|
||||
startTime = (new Date()).getTime();
|
||||
download.src = imageAddr;
|
||||
download.onload = function() {
|
||||
endTime = (new Date()).getTime();
|
||||
var duration = (endTime - startTime) / 1000;
|
||||
var bitsLoaded = downloadSize * 8;
|
||||
var speedBps = (bitsLoaded / duration).toFixed(2);
|
||||
var speedKbps = (speedBps / 1024).toFixed(2);
|
||||
var speedMbps = (speedKbps / 1024).toFixed(2);
|
||||
callback(speedMbps);
|
||||
}
|
||||
},
|
||||
}
|
||||
})();
|
||||
1109
comms/webRTC-over-websockets/js/bootstrap/css/bootstrap-responsive.css
vendored
Normal file
1109
comms/webRTC-over-websockets/js/bootstrap/css/bootstrap-responsive.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
9
comms/webRTC-over-websockets/js/bootstrap/css/bootstrap-responsive.min.css
vendored
Normal file
9
comms/webRTC-over-websockets/js/bootstrap/css/bootstrap-responsive.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
6158
comms/webRTC-over-websockets/js/bootstrap/css/bootstrap.css
vendored
Normal file
6158
comms/webRTC-over-websockets/js/bootstrap/css/bootstrap.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
9
comms/webRTC-over-websockets/js/bootstrap/css/bootstrap.min.css
vendored
Normal file
9
comms/webRTC-over-websockets/js/bootstrap/css/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
Binary file not shown.
|
After Width: | Height: | Size: 8.6 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
2276
comms/webRTC-over-websockets/js/bootstrap/js/bootstrap.js
vendored
Normal file
2276
comms/webRTC-over-websockets/js/bootstrap/js/bootstrap.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
6
comms/webRTC-over-websockets/js/bootstrap/js/bootstrap.min.js
vendored
Normal file
6
comms/webRTC-over-websockets/js/bootstrap/js/bootstrap.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
4
comms/webRTC-over-websockets/js/jquery-1.7.2.min.js
vendored
Normal file
4
comms/webRTC-over-websockets/js/jquery-1.7.2.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
258
comms/webRTC-over-websockets/js/main.js
Normal file
258
comms/webRTC-over-websockets/js/main.js
Normal file
@@ -0,0 +1,258 @@
|
||||
var socketAddress = 'ws://localhost:1337/';
|
||||
|
||||
var RTCApp = {
|
||||
name: null,
|
||||
webRTC: null,
|
||||
commChannel: null,
|
||||
message: null
|
||||
};
|
||||
|
||||
RTCApp.commChannel = signaling({webSocketAddress : socketAddress, id: RTCApp.name });
|
||||
|
||||
RTCApp.commChannel.addCallback('presence' , presenceCallback);
|
||||
RTCApp.commChannel.addCallback('s-offer', accept);
|
||||
RTCApp.commChannel.addCallback('roster', roster);
|
||||
|
||||
|
||||
RTCApp.webRTC = webrtc({sourcevid : document.getElementById('sourceSmallvid'),
|
||||
stunServer : "stun.l.google.com:19302",
|
||||
commChannel : RTCApp.commChannel,
|
||||
onremote : remoteCallback,
|
||||
constrains : 'dynamic'
|
||||
});
|
||||
|
||||
RTCApp.webRTC.startVideo();
|
||||
|
||||
var users = {};
|
||||
var caller, newUser;
|
||||
var snd = new Audio("data/ringtone.wav");
|
||||
var newUsers = {};
|
||||
|
||||
$(document).ready(function() {
|
||||
//List of people and rooms is either retrived by uncommenting lines below,
|
||||
//or after first successfull login (when the socket server send it to the logged user)
|
||||
|
||||
//loadFromJSON("data/people.json", "ajax-modal", ".people-carousel", false);
|
||||
//loadFromJSON("data/rooms.json", "ajax-room-modal", ".rooms-carousel", true);
|
||||
|
||||
$('#people_content').hide();
|
||||
$('#room_content').hide();
|
||||
$('#people').fadeIn();
|
||||
$('[id^="myCarousel"]').carousel({interval: false});
|
||||
});
|
||||
|
||||
$("#form").submit(function(event) {
|
||||
event.preventDefault();
|
||||
RTCApp.name = $("#user").val();
|
||||
RTCApp.commChannel.sendPresence(RTCApp.name, 'on');
|
||||
|
||||
$('#user').attr('readonly', true);
|
||||
$("#submit").hide();
|
||||
});
|
||||
|
||||
$('#accept').bind('click', function() {
|
||||
RTCApp.commChannel.answer(caller, 'accept');
|
||||
$('#acceptModal').modal('hide');
|
||||
});
|
||||
|
||||
$('#reject').bind('click', function() {
|
||||
RTCApp.commChannel.answer(caller, 'reject');
|
||||
$('#acceptModal').modal('hide');
|
||||
});
|
||||
|
||||
function accept(message){
|
||||
if(message.from === RTCApp.name){
|
||||
console.log("can't call yourself ");
|
||||
return;
|
||||
}
|
||||
caller = message.from;
|
||||
snd.play();
|
||||
$('#callerTitle').text('Incoming call');
|
||||
$('#caller').text('Caller id '+ message.from);
|
||||
$('#acceptModal').modal('show');
|
||||
}
|
||||
|
||||
function talkFunction(flag){
|
||||
var callback = flag === true? "hide" : "show";
|
||||
$('#people_content')[callback]();
|
||||
$('#room_content')[callback]();
|
||||
}
|
||||
|
||||
function remoteCallback(from, added, stream){
|
||||
var resource = 'resource_'+ from;
|
||||
if(added){
|
||||
if (window.webkitURL) {
|
||||
$('.inner').append('<video class="span4" id=' + resource + ' src=' +
|
||||
window.webkitURL.createObjectURL(event.stream) + ' autoplay></video>');
|
||||
} else {
|
||||
$('.inner').append('<video class="span4" id=' + resource + ' mozSrcObject=' +
|
||||
event.stream + ' autoplay></video>');
|
||||
}
|
||||
} else {
|
||||
$('#'+resource).attr('src',"");
|
||||
$('#'+resource).remove();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$('#acceptNewUser').bind('click', function() {
|
||||
delete newUsers[newUser];
|
||||
addNewUser({
|
||||
"name" : newUser,
|
||||
"id": newUser,
|
||||
"img" : "images/person.jpg"
|
||||
}, "ajax-modal", ".people-carousel");
|
||||
$('#userModal').modal('hide');
|
||||
});
|
||||
|
||||
$('#rejectNewUser').bind('click', function() {
|
||||
newUsers[newUser] = false;
|
||||
$('#userModal').modal('hide');
|
||||
});
|
||||
|
||||
function presenceCallback(message){
|
||||
roomFlag = message.room !== undefined;
|
||||
var user_id, room_id;
|
||||
if(!roomFlag){
|
||||
$(".ajax-modal").each(function(){
|
||||
user_id = $(this).attr('user-id');
|
||||
if(user_id !== undefined && user_id === message.name){
|
||||
if(message.status === 'on'){
|
||||
$(this).find('img').attr('src', 'images/online-icon.png');
|
||||
} else {
|
||||
$(this).find('img').attr('src', 'images/offline-icon.png');
|
||||
}
|
||||
}
|
||||
});
|
||||
if(users[message.name] === undefined && message.status === 'on'){
|
||||
console.log('presence received from the person that is not in the address book ' + message.name);
|
||||
if(newUsers[message.name] === undefined){
|
||||
newUsers[message.name] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
$(".ajax-room-modal").each(function(){
|
||||
room_id = $(this).attr('user-id');
|
||||
if(room_id !== undefined && room_id === message.name){
|
||||
if(message.status === 'on'){
|
||||
$(this).find('img').attr('src', 'images/online-icon.png');
|
||||
}else {
|
||||
$(this).find('img').attr('src', 'images/offline-icon.png');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$('#main').delegate('a.ajax-modal', 'click', function() {
|
||||
event.preventDefault();
|
||||
var user_id = $(this).attr('user-id');
|
||||
if(user_id !== undefined && user_id !== RTCApp.name)
|
||||
RTCApp.commChannel.callOtherParty(user_id);
|
||||
});
|
||||
|
||||
$('#main').delegate('a.ajax-room-modal', 'click', function() {
|
||||
event.preventDefault();
|
||||
var room = $(this).attr('user-id');
|
||||
RTCApp.commChannel.joinRoom(room);
|
||||
});
|
||||
|
||||
$.ajaxSetup({
|
||||
'beforeSend' : function(xhr) {
|
||||
xhr.overrideMimeType('text/html; charset=ISO-8859-1');
|
||||
},
|
||||
});
|
||||
|
||||
window.onbeforeunload = function() {
|
||||
if(RTCApp.commChannel !== null)
|
||||
RTCApp.commChannel.sendPresence(RTCApp.name, 'off');
|
||||
}
|
||||
|
||||
function addNewUser(jsonData, class_name, class_div){
|
||||
users[jsonData.id] = jsonData;
|
||||
$('.people-carousel').empty();
|
||||
var array = $.map(users, function (value, key) { return value; });
|
||||
addDataToDiv(array, class_name, class_div, false);
|
||||
}
|
||||
|
||||
function loadFromJSON(file, class_name, class_div, roomFlag){
|
||||
$.getJSON(file, function(data) {
|
||||
addDataToDiv(data, class_name, class_div, roomFlag);
|
||||
});
|
||||
}
|
||||
|
||||
function roster(message){
|
||||
addDataToDiv(message.people, "ajax-modal", ".people-carousel", false);
|
||||
addDataToDiv(message.rooms, "ajax-room-modal", ".rooms-carousel", true);
|
||||
|
||||
if(message.people.length > 0)
|
||||
$('#people_content').show();
|
||||
if(message.rooms.length > 0)
|
||||
$('#room_content').show();
|
||||
|
||||
if(users[RTCApp.name] === undefined){
|
||||
console.log('user not known by the system, create an avatar');
|
||||
addNewUser({
|
||||
"name" : RTCApp.name,
|
||||
"id": RTCApp.name,
|
||||
"img" : "images/person.jpg"
|
||||
}, "ajax-modal", ".people-carousel");
|
||||
}
|
||||
if(users[RTCApp.name].room !== undefined){
|
||||
for(var i=0; i < users[RTCApp.name].room.length; i ++)
|
||||
RTCApp.commChannel.joinRoom(users[RTCApp.name].room[i]);
|
||||
}
|
||||
}
|
||||
|
||||
function addDataToDiv(data, class_name, class_div, roomFlag){
|
||||
var items = [];
|
||||
var i = 0;
|
||||
var groupIndex = 12;
|
||||
|
||||
$.each(data, function(key, value) {
|
||||
var name = this.name;
|
||||
var image = this.img;
|
||||
var id = this.id;
|
||||
if(!roomFlag)
|
||||
users[id] = value;
|
||||
|
||||
if(i % groupIndex === 0){
|
||||
if(i === 0)
|
||||
items.push('<div class="item active">');
|
||||
else
|
||||
items.push('<div class="item">');
|
||||
items.push('<ul class="thumbnails">');
|
||||
}
|
||||
|
||||
items.push('<li class="span1"><div class="thumbnail"><img src="' + image
|
||||
+' " alt=""></a> <h4>' + name + '</h4><p><a href="#" class="btn btn-primary ' +
|
||||
class_name + ' " user-id="' + id +
|
||||
'" >Talk<img src="images/offline-icon.png" width="24" height="24" align="left" alt=""> </a></p></div></li>');
|
||||
|
||||
if( (i % groupIndex) === (groupIndex - 1) ){
|
||||
items.push('</ul>');
|
||||
items.push('</div>');
|
||||
}
|
||||
i++;
|
||||
});
|
||||
|
||||
if(items.lenght > 0 && items[items.lenght - 1].indexOf('div') < 0 ){
|
||||
items.push('</ul>');
|
||||
items.push('</div>');
|
||||
}
|
||||
|
||||
$(items.join('')).appendTo(class_div);
|
||||
}
|
||||
|
||||
|
||||
setInterval(function(){
|
||||
for(newUser in newUsers){
|
||||
if(newUsers[newUser]){
|
||||
$('#userTitle').text('Accept a new user?');
|
||||
$('#callerUser').text('User id '+ newUser);
|
||||
$('#userModal').modal('show');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}, 10000);
|
||||
76
comms/webRTC-over-websockets/js/signaling.js
Normal file
76
comms/webRTC-over-websockets/js/signaling.js
Normal file
@@ -0,0 +1,76 @@
|
||||
var signaling = function(options){
|
||||
|
||||
var socket = new WebSocket(options.webSocketAddress);
|
||||
var logg = function(s) { console.log(s); };
|
||||
|
||||
var myId = options.id;
|
||||
|
||||
var that = {};
|
||||
var callbacks = {};
|
||||
|
||||
function getCallback(type){
|
||||
return callbacks[type] !== undefined ? callbacks[type] : function(){
|
||||
console.log("Callback of type " + type + " not found");
|
||||
};
|
||||
}
|
||||
|
||||
that.addCallback = function(type, f){
|
||||
callbacks[type] = f;
|
||||
}
|
||||
|
||||
that.sendMessage = function(message, to) {
|
||||
sendMsg(message, to);
|
||||
}
|
||||
|
||||
that.sendPresence = function(_name, stat){
|
||||
_status = stat || 'on';
|
||||
myId = _name;
|
||||
sendMsg({type: 'presence', name: _name, status: _status});
|
||||
}
|
||||
|
||||
that.joinRoom = function(room){
|
||||
sendMsg({type: 'room'}, room);
|
||||
}
|
||||
|
||||
that.callOtherParty = function(to){
|
||||
sendMsg({type: 's-offer'}, to);
|
||||
};
|
||||
|
||||
that.answer = function(to, _answer){
|
||||
sendMsg({type: 's-answer', answer: _answer}, to);
|
||||
};
|
||||
|
||||
function sendMsg(message, to){
|
||||
message.from = myId;
|
||||
if(to !== undefined)
|
||||
message.to = to;
|
||||
var mymsg = JSON.stringify(message);
|
||||
logg("SOCKET Send: " + mymsg);
|
||||
socket.send(mymsg);
|
||||
}
|
||||
|
||||
socket.addEventListener("message", onMessage, false);
|
||||
|
||||
socket.addEventListener("error", function(event) {
|
||||
logg("SOCKET Error: " + event);
|
||||
});
|
||||
|
||||
socket.addEventListener("close", function(event) {
|
||||
logg("SOCKET Close: " + event);
|
||||
});
|
||||
|
||||
function onMessage(evt) {
|
||||
logg("RECEIVED: " + evt.data);
|
||||
processSignalingMessage(evt.data);
|
||||
}
|
||||
|
||||
//message comes as a JSON from the websocket server
|
||||
function processSignalingMessage(message) {
|
||||
var msg = JSON.parse(message);
|
||||
logg("processSignalingMessage type(" + msg.type + ")= " + message);
|
||||
getCallback(msg.type)(msg);
|
||||
}
|
||||
|
||||
return that;
|
||||
|
||||
}
|
||||
210
comms/webRTC-over-websockets/js/webrtc.js
Normal file
210
comms/webRTC-over-websockets/js/webrtc.js
Normal file
@@ -0,0 +1,210 @@
|
||||
var webrtc = function(options) {
|
||||
var my = {};
|
||||
|
||||
var commChannel = options.commChannel,
|
||||
stunServer = options.stunServer,
|
||||
sourcevid = options.sourcevid,
|
||||
remoteCallback = options.onremote;
|
||||
|
||||
var localStream;
|
||||
var peerConn = {};
|
||||
|
||||
var mediaConstraints = {'mandatory': {'OfferToReceiveAudio':true, 'OfferToReceiveVideo':true }};
|
||||
|
||||
if(options.constrains === 'dynamic'){
|
||||
BANDWITDH.init(function(bandwitdh){
|
||||
console.log('calculate bandwitdh');
|
||||
if(!isNaN(bandwitdh) && bandwitdh < 0.5){
|
||||
mediaConstraints = {'mandatory': {
|
||||
'OfferToReceiveAudio':true,
|
||||
'OfferToReceiveVideo':false }};
|
||||
}
|
||||
console.log('bandwitdh is ' + bandwitdh + ' [Mbps]');
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
//callback to start p2p connection between two parties
|
||||
commChannel.addCallback('s-answer', call);
|
||||
|
||||
commChannel.addCallback('offer', processSignalingMessage);
|
||||
commChannel.addCallback('answer', processSignalingMessage);
|
||||
commChannel.addCallback('candidate', processSignalingMessage);
|
||||
commChannel.addCallback('bye', processSignalingMessage);
|
||||
|
||||
function RTCPeer(pc_config, name) {
|
||||
this.from = name;
|
||||
this.rtc = new RTCPeerConnection(pc_config);
|
||||
that = this;
|
||||
|
||||
this.rtc.onaddstream = function(event){
|
||||
logg("Added remote stream");
|
||||
remoteCallback(that.from, true, event.stream);
|
||||
};
|
||||
this.rtc.onremovestream = function(event) {
|
||||
logg("Remove remote stream");
|
||||
remoteCallback(that.from, false);
|
||||
};
|
||||
this.rtc.onicecandidate = function(event) {
|
||||
logg("send on Icecandidate");
|
||||
if (event.candidate) {
|
||||
commChannel.sendMessage({type: 'candidate',
|
||||
label: event.candidate.sdpMLineIndex,
|
||||
id: event.candidate.sdpMid,
|
||||
candidate: event.candidate.candidate}, that.from);
|
||||
} else {
|
||||
logg("End of candidates.");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function setLocalDescriptionAndMessage(sessionDescription){
|
||||
logg("setLocalDescriptionAndMessage");
|
||||
this.rtc.setLocalDescription(sessionDescription);
|
||||
commChannel.sendMessage(sessionDescription, this.from);
|
||||
}
|
||||
|
||||
RTCPeer.prototype.createOffer = function(callback){
|
||||
logg("createOffer to " + this.from);
|
||||
that = this;
|
||||
this.rtc.createOffer(function(sessionDescription){
|
||||
callback.call(that, sessionDescription);
|
||||
}, null, mediaConstraints);
|
||||
}
|
||||
|
||||
RTCPeer.prototype.createAnswer = function(callback){
|
||||
logg("createAnswer to " + this.from);
|
||||
that = this;
|
||||
this.rtc.createAnswer(function(sessionDescription){
|
||||
callback.call(that, sessionDescription);
|
||||
}, null, mediaConstraints);
|
||||
}
|
||||
|
||||
RTCPeer.prototype.getRTC = function(){
|
||||
return this.rtc;
|
||||
}
|
||||
|
||||
RTCPeer.prototype.getFrom = function(){
|
||||
return this.from;
|
||||
}
|
||||
|
||||
var logg = function(s) { console.log(s); };
|
||||
|
||||
my.startVideo = function() {
|
||||
try {
|
||||
getUserMedia({audio: true, video: true}, successCallback, errorCallback);
|
||||
} catch (e) {
|
||||
getUserMedia("video,audio", successCallback, errorCallback);
|
||||
}
|
||||
function successCallback(stream) {
|
||||
attachMediaStream(sourcevid, stream);
|
||||
localStream = stream;
|
||||
logg('local stream started');
|
||||
}
|
||||
function errorCallback(error) {
|
||||
logg('An error occurred: [CODE ' + error.code + ']');
|
||||
}
|
||||
}
|
||||
|
||||
my.stopVideo = function() {
|
||||
sourcevid.src = "";
|
||||
}
|
||||
|
||||
my.onHangUp = function() {
|
||||
logg("Hang up.");
|
||||
closeSession();
|
||||
}
|
||||
|
||||
// start the connection upon user request
|
||||
function call(msg) {
|
||||
if(msg.answer !== 'accept') {
|
||||
console.log('call not accepted');
|
||||
return;
|
||||
}
|
||||
|
||||
if (peerConn[msg.from] === undefined && localStream) {
|
||||
logg("Creating PeerConnection with "+ msg.from);
|
||||
createPeerConnection(msg.from);
|
||||
} else if (!localStream){
|
||||
alert("Please start the video first");
|
||||
logg("localStream not started");
|
||||
return;
|
||||
} else {
|
||||
logg("peer SDP offer already made");
|
||||
}
|
||||
logg("create offer");
|
||||
peerConn[msg.from].createOffer(setLocalDescriptionAndMessage);
|
||||
}
|
||||
|
||||
|
||||
function createPeerConnection(from) {
|
||||
try {
|
||||
logg("Creating peer connection with " + from);
|
||||
var servers = [];
|
||||
servers.push({'url':'stun:' + stunServer});
|
||||
var pc_config = {'iceServers':servers};
|
||||
peerConn[from] = new RTCPeer(pc_config, from);
|
||||
logg("Connected using stun server "+ stunServer);
|
||||
} catch (e) {
|
||||
alert("Failed to create PeerConnection, exception: " + e.message);
|
||||
return;
|
||||
}
|
||||
logg('Adding local stream...');
|
||||
peerConn[from].getRTC().addStream(localStream);
|
||||
}
|
||||
|
||||
|
||||
function processSignalingMessage(msg) {
|
||||
logg("processSignalingMessage type(" + msg.type + ")= " + msg);
|
||||
|
||||
if (msg.type === 'offer') {
|
||||
if(peerConn[msg.from] === undefined && localStream) {
|
||||
createPeerConnection(msg.from);
|
||||
//set remote description
|
||||
peerConn[msg.from].getRTC().setRemoteDescription(new RTCSessionDescription(msg));
|
||||
//create answer
|
||||
logg("Sending answer to peer.");
|
||||
peerConn[msg.from].createAnswer(setLocalDescriptionAndMessage);
|
||||
} else {
|
||||
logg('peerConnection has already been started');
|
||||
}
|
||||
} else if (msg.type === 'answer' && peerConn[msg.from] !== undefined) {
|
||||
logg("setRemoteDescription...");
|
||||
peerConn[msg.from].getRTC().setRemoteDescription(new RTCSessionDescription(msg));
|
||||
} else if (msg.type === 'candidate' && peerConn[msg.from] !== undefined) {
|
||||
var candidate = new RTCIceCandidate({sdpMLineIndex:msg.label, candidate:msg.candidate});
|
||||
peerConn[msg.from].getRTC().addIceCandidate(candidate);
|
||||
} else if (msg.type === 'bye' && peerConn[msg.from] !== undefined) {
|
||||
onRemoteHangUp(msg.from);
|
||||
} else {
|
||||
logg("message unknown:" + msg);
|
||||
}
|
||||
}
|
||||
|
||||
function onRemoteHangUp(from) {
|
||||
logg("Remote(" + from + ") Hang up ");
|
||||
remoteCallback(from, false);
|
||||
peerConn[from].getRTC().close();
|
||||
delete peerConn[from];
|
||||
}
|
||||
|
||||
function closeSession() {
|
||||
for(var index in peerConn){
|
||||
remoteCallback(peerConn[index].getFrom(), false);
|
||||
peerConn[index].getRTC().close();
|
||||
delete peerConn[index];
|
||||
}
|
||||
commChannel.sendMessage({type: 'bye'});
|
||||
}
|
||||
|
||||
window.onbeforeunload = function() {
|
||||
if (Object.keys(peerConn).length > 0) {
|
||||
closeSession();
|
||||
}
|
||||
}
|
||||
|
||||
return my;
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user