;(function () {
var logger = {
log: function (){},
warn: function (){},
error: function (){}
};
// normalize environment
var RTCPeerConnection = null;
var getUserMedia = null;
var attachMediaStream = null;
var reattachMediaStream = null;
var webrtcDetectedBrowser = null;
var webRTCSupport = true;
if (navigator.mozGetUserMedia) {
logger.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) {
element.mozSrcObject = stream;
element.play();
};
reattachMediaStream = function(to, from) {
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) {
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.autoplay = true;
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 {
webRTCSupport = false;
throw new Error("Browser does not appear to be WebRTC-capable");
}
// emitter that we use as a base
function WildEmitter() {
this.callbacks = {};
}
// Listen on the given `event` with `fn`. Store a group name if present.
WildEmitter.prototype.on = function (event, groupName, fn) {
var hasGroup = (arguments.length === 3),
group = hasGroup ? arguments[1] : undefined,
func = hasGroup ? arguments[2] : arguments[1];
func._groupName = group;
(this.callbacks[event] = this.callbacks[event] || []).push(func);
return this;
};
// Adds an `event` listener that will be invoked a single
// time then automatically removed.
WildEmitter.prototype.once = function (event, fn) {
var self = this;
function on() {
self.off(event, on);
fn.apply(this, arguments);
}
this.on(event, on);
return this;
};
// Unbinds an entire group
WildEmitter.prototype.releaseGroup = function (groupName) {
var item, i, len, handlers;
for (item in this.callbacks) {
handlers = this.callbacks[item];
for (i = 0, len = handlers.length; i < len; i++) {
if (handlers[i]._groupName === groupName) {
handlers.splice(i, 1);
i--;
len--;
}
}
}
return this;
};
// Remove the given callback for `event` or all
// registered callbacks.
WildEmitter.prototype.off = function (event, fn) {
var callbacks = this.callbacks[event],
i;
if (!callbacks) return this;
// remove all handlers
if (arguments.length === 1) {
delete this.callbacks[event];
return this;
}
// remove specific handler
i = callbacks.indexOf(fn);
callbacks.splice(i, 1);
return this;
};
// Emit `event` with the given args.
// also calls any `*` handlers
WildEmitter.prototype.emit = function (event) {
var args = [].slice.call(arguments, 1),
callbacks = this.callbacks[event],
specialCallbacks = this.getWildcardCallbacks(event),
i,
len,
item;
if (callbacks) {
for (i = 0, len = callbacks.length; i < len; ++i) {
callbacks[i].apply(this, args);
}
}
if (specialCallbacks) {
for (i = 0, len = specialCallbacks.length; i < len; ++i) {
specialCallbacks[i].apply(this, [event].concat(args));
}
}
return this;
};
// Helper for for finding special wildcard event handlers that match the event
WildEmitter.prototype.getWildcardCallbacks = function (eventName) {
var item,
split,
result = [];
for (item in this.callbacks) {
split = item.split('*');
if (item === '*' || (split.length === 2 && eventName.slice(0, split[1].length) === split[1])) {
result = result.concat(this.callbacks[item]);
}
}
return result;
};
function WebRTC(opts) {
var self = this,
options = opts || {},
config = this.config = {
url: 'http://tool.andyet.net:8888',
log: false,
localVideoEl: '',
remoteVideosEl: '',
autoRequestMedia: false
},
item,
connection;
// check for support
if (!webRTCSupport) {
console.error('Your browser doesn\'t seem to support WebRTC');
}
// set options
for (item in options) {
this.config[item] = options[item];
}
// log if configured to
if (this.config.log) logger = console;
// where we'll store our peer connections
this.pcs = {};
// our socket.io connection
connection = this.connection = io.connect(this.config.url);
connection.on('connect', function () {
self.emit('ready', connection.socket.sessionid);
self.sessionReady = true;
self.testReadiness();
});
connection.on('message', function (message) {
var existing = self.pcs[message.from];
if (existing) {
existing.handleMessage(message);
} else {
// create the conversation object
self.pcs[message.from] = new Conversation({
id: message.from,
parent: self,
initiator: false
});
self.pcs[message.from].handleMessage(message);
}
});
connection.on('joined', function (room) {
logger.log('got a joined', room);
if (!self.pcs[room.id]) {
self.startVideoCall(room.id);
}
});
connection.on('left', function (room) {
var conv = self.pcs[room.id];
if (conv) conv.handleStreamRemoved();
});
WildEmitter.call(this);
// log events
this.on('*', function (event, val1, val2) {
logger.log('event:', event, val1, val2);
});
// auto request if configured
if (this.config.autoRequestMedia) this.startLocalVideo();
}
WebRTC.prototype = Object.create(WildEmitter.prototype, {
constructor: {
value: WebRTC
}
});
WebRTC.prototype.getEl = function (idOrEl) {
if (typeof idOrEl == 'string') {
return document.getElementById(idOrEl);
} else {
return idOrEl;
}
};
// this accepts either element ID or element
// and either the video tag itself or a con
评论0