From 59b77c5458f75d54566158aa5f4072980d04255e Mon Sep 17 00:00:00 2001 From: Daniel Berteaud Date: Mon, 14 Apr 2014 23:00:28 +0200 Subject: [PATCH] Update SimpleWebRTC to 1.7.3 --- public/js/simplewebrtc.bundle.js | 1302 ++++++++++++++++++++------------------ 1 file changed, 697 insertions(+), 605 deletions(-) diff --git a/public/js/simplewebrtc.bundle.js b/public/js/simplewebrtc.bundle.js index 39f6af4..ca2e346 100644 --- a/public/js/simplewebrtc.bundle.js +++ b/public/js/simplewebrtc.bundle.js @@ -304,6 +304,7 @@ SimpleWebRTC.prototype.stopLocalVideo = function () { SimpleWebRTC.prototype.getLocalVideoContainer = function () { var el = this.getEl(this.config.localVideoEl); if (el && el.tagName === 'VIDEO') { + el.oncontextmenu = function () { return false; }; return el; } else if (el) { var video = document.createElement('video'); @@ -422,45 +423,7 @@ SimpleWebRTC.prototype.sendFile = function () { module.exports = SimpleWebRTC; -},{"attachmediastream":5,"getscreenmedia":6,"mockconsole":7,"socket.io-client":8,"webrtc":2,"webrtcsupport":4,"wildemitter":3}],4:[function(require,module,exports){ -// created by @HenrikJoreteg -var prefix; -var isChrome = false; -var isFirefox = false; -var ua = navigator.userAgent.toLowerCase(); - -// basic sniffing -if (ua.indexOf('firefox') !== -1) { - prefix = 'moz'; - isFirefox = true; -} else if (ua.indexOf('chrome') !== -1) { - prefix = 'webkit'; - isChrome = true; -} - -var PC = window.mozRTCPeerConnection || window.webkitRTCPeerConnection; -var IceCandidate = window.mozRTCIceCandidate || window.RTCIceCandidate; -var SessionDescription = window.mozRTCSessionDescription || window.RTCSessionDescription; -var MediaStream = window.webkitMediaStream || window.MediaStream; -var screenSharing = navigator.userAgent.match('Chrome') && parseInt(navigator.userAgent.match(/Chrome\/(.*) /)[1], 10) >= 26; -var AudioContext = window.webkitAudioContext || window.AudioContext; - - -// export support flags and constructors.prototype && PC -module.exports = { - support: !!PC, - dataChannel: isChrome || isFirefox || (PC && PC.prototype && PC.prototype.createDataChannel), - prefix: prefix, - webAudio: !!(AudioContext && AudioContext.prototype.createMediaStreamSource), - mediaStream: !!(MediaStream && MediaStream.prototype.removeTrack), - screenSharing: !!screenSharing, - AudioContext: AudioContext, - PeerConnection: PC, - SessionDescription: SessionDescription, - IceCandidate: IceCandidate -}; - -},{}],3:[function(require,module,exports){ +},{"attachmediastream":5,"getscreenmedia":6,"mockconsole":7,"socket.io-client":8,"webrtc":2,"webrtcsupport":4,"wildemitter":3}],3:[function(require,module,exports){ /* WildEmitter.js is a slim little event emitter by @henrikjoreteg largely based on @visionmedia's Emitter from UI Kit. @@ -597,6 +560,44 @@ WildEmitter.prototype.getWildcardCallbacks = function (eventName) { return result; }; +},{}],4:[function(require,module,exports){ +// created by @HenrikJoreteg +var prefix; +var isChrome = false; +var isFirefox = false; +var ua = window.navigator.userAgent.toLowerCase(); + +// basic sniffing +if (ua.indexOf('firefox') !== -1) { + prefix = 'moz'; + isFirefox = true; +} else if (ua.indexOf('chrome') !== -1) { + prefix = 'webkit'; + isChrome = true; +} + +var PC = window.mozRTCPeerConnection || window.webkitRTCPeerConnection; +var IceCandidate = window.mozRTCIceCandidate || window.RTCIceCandidate; +var SessionDescription = window.mozRTCSessionDescription || window.RTCSessionDescription; +var MediaStream = window.webkitMediaStream || window.MediaStream; +var screenSharing = window.location.protocol === 'https:' && window.navigator.userAgent.match('Chrome') && parseInt(window.navigator.userAgent.match(/Chrome\/(.*) /)[1], 10) >= 26; +var AudioContext = window.webkitAudioContext || window.AudioContext; + + +// export support flags and constructors.prototype && PC +module.exports = { + support: !!PC, + dataChannel: isChrome || isFirefox || (PC && PC.prototype && PC.prototype.createDataChannel), + prefix: prefix, + webAudio: !!(AudioContext && AudioContext.prototype.createMediaStreamSource), + mediaStream: !!(MediaStream && MediaStream.prototype.removeTrack), + screenSharing: !!screenSharing, + AudioContext: AudioContext, + PeerConnection: PC, + SessionDescription: SessionDescription, + IceCandidate: IceCandidate +}; + },{}],5:[function(require,module,exports){ module.exports = function (stream, el, options) { var URL = window.URL; @@ -4528,6 +4529,9 @@ if (typeof define === "function" && define.amd) { // getScreenMedia helper by @HenrikJoreteg var getUserMedia = require('getusermedia'); +// cache for constraints and callback +var cache = {}; + module.exports = function (constraints, cb) { var hasConstraints = arguments.length === 2; var callback = hasConstraints ? cb : constraints; @@ -4539,18 +4543,62 @@ module.exports = function (constraints, cb) { return callback(error); } - constraints = (hasConstraints && constraints) || { - video: { - mandatory: { + if (window.navigator.userAgent.match('Chrome')) { + var chromever = parseInt(window.navigator.userAgent.match(/Chrome\/(.*) /)[1], 10); + if (chromever >= 26 && chromever <= 33) { + // chrome 26 - chrome 33 way to do it -- requires bad chrome://flags + constraints = (hasConstraints && constraints) || { + video: { + mandatory: { + maxWidth: window.screen.width, + maxHeight: window.screen.height, + maxFrameRate: 3, + chromeMediaSource: 'screen' + } + } + }; + getUserMedia(constraints, callback); + } else { + // chrome 34+ way requiring an extension + var pending = window.setTimeout(function () { + error = new Error('NavigatorUserMediaError'); + error.name = 'EXTENSION_UNAVAILABLE'; + return callback(error); + }, 1000); + cache[pending] = [callback, hasConstraints ? constraint : null]; + window.postMessage({ type: 'getScreen', id: pending }, '*'); + } + } +}; + +window.addEventListener('message', function (event) { + if (event.origin != window.location.origin) { + return; + } + if (event.data.type == 'gotScreen' && cache[event.data.id]) { + var data = cache[event.data.id]; + var constraints = data[1]; + var callback = data[0]; + delete cache[event.data.id]; + + if (event.data.sourceId === '') { // user canceled + var error = error = new Error('NavigatorUserMediaError'); + error.name = 'PERMISSION_DENIED'; + callback(error); + } else { + constraints = constraints || {audio: false, video: {mandatory: { + chromeMediaSource: 'desktop', + chromeMediaSourceId: event.data.sourceId, maxWidth: window.screen.width, maxHeight: window.screen.height, maxFrameRate: 3, - chromeMediaSource: 'screen' - } + }}}; + getUserMedia(constraints, callback); } - }; - getUserMedia(constraints, callback); -}; + } else if (event.data.type == 'getScreenPending') { + window.clearTimeout(event.data.id); + } +}); },{"getusermedia":9}],10:[function(require,module,exports){ // getUserMedia helper by @HenrikJoreteg @@ -4616,6 +4664,44 @@ module.exports = function (constraints, cb) { }); }; +},{}],11:[function(require,module,exports){ +// created by @HenrikJoreteg +var prefix; +var isChrome = false; +var isFirefox = false; +var ua = navigator.userAgent.toLowerCase(); + +// basic sniffing +if (ua.indexOf('firefox') !== -1) { + prefix = 'moz'; + isFirefox = true; +} else if (ua.indexOf('chrome') !== -1) { + prefix = 'webkit'; + isChrome = true; +} + +var PC = window.mozRTCPeerConnection || window.webkitRTCPeerConnection; +var IceCandidate = window.mozRTCIceCandidate || window.RTCIceCandidate; +var SessionDescription = window.mozRTCSessionDescription || window.RTCSessionDescription; +var MediaStream = window.webkitMediaStream || window.MediaStream; +var screenSharing = navigator.userAgent.match('Chrome') && parseInt(navigator.userAgent.match(/Chrome\/(.*) /)[1], 10) >= 26; +var AudioContext = window.webkitAudioContext || window.AudioContext; + + +// export support flags and constructors.prototype && PC +module.exports = { + support: !!PC, + dataChannel: isChrome || isFirefox || (PC && PC.prototype && PC.prototype.createDataChannel), + prefix: prefix, + webAudio: !!(AudioContext && AudioContext.prototype.createMediaStreamSource), + mediaStream: !!(MediaStream && MediaStream.prototype.removeTrack), + screenSharing: !!screenSharing, + AudioContext: AudioContext, + PeerConnection: PC, + SessionDescription: SessionDescription, + IceCandidate: IceCandidate +}; + },{}],9:[function(require,module,exports){ // getUserMedia helper by @HenrikJoreteg var func = (window.navigator.getUserMedia || @@ -4859,6 +4945,7 @@ WebRTC.prototype.setupAudioMonitor = function (stream) { audio.on('volume_change', function (volume, treshold) { if (self.hardMuted) return; self.emit('volumeChange', volume, treshold); + // FIXME: should use sendDirectlyToAll, but currently has different semantics wrt payload self.peers.forEach(function (peer) { if (peer.enableDataChannels) { var dc = peer.getDataChannel('hark'); @@ -4935,6 +5022,7 @@ WebRTC.prototype.sendToAll = function (message, payload) { }; // sends message to all using a datachannel +// only sends to anyone who has an open datachannel WebRTC.prototype.sendDirectlyToAll = function (channel, message, payload) { this.peers.forEach(function (peer) { if (peer.enableDataChannels) { @@ -4967,6 +5055,8 @@ function Peer(options) { // we can use this as the trigger for starting the offer/answer process // automatically. We'll just leave it be for now while this stabalizes. this.pc.on('negotiationNeeded', this.emit.bind(this, 'negotiationNeeded')); + this.pc.on('iceConnectionStateChange', this.emit.bind(this, 'iceConnectionStateChange')); + this.pc.on('signalingStateChange', this.emit.bind(this, 'signalingStateChange')); this.logger = this.parent.logger; // handle screensharing/broadcast mode @@ -5024,8 +5114,6 @@ Peer.prototype.handleMessage = function (message) { this.parent.emit('mute', {id: message.from, name: message.payload.name}); } else if (message.type === 'unmute') { this.parent.emit('unmute', {id: message.from, name: message.payload.name}); - } else { - this.parent.emit(message.type, {id: message.from, payload: message.payload}); } }; @@ -5044,13 +5132,17 @@ Peer.prototype.send = function (messageType, payload) { }; // send via data channel +// returns true when message was sent and false if channel is not open Peer.prototype.sendDirectly = function (channel, messageType, payload) { var message = { type: messageType, payload: payload }; this.logger.log('sending via datachannel', channel, messageType, message); - this.getDataChannel(channel).send(JSON.stringify(message)); + var dc = this.getDataChannel(channel); + if (dc.readyState != 'open') return false; + dc.send(JSON.stringify(message)); + return true; }; // Internal method registering handlers for a data channel and emitting events on the peer @@ -5133,7 +5225,7 @@ Peer.prototype.handleDataChannelAdded = function (channel) { module.exports = WebRTC; -},{"getusermedia":10,"hark":12,"mediastream-gain":13,"mockconsole":7,"rtcpeerconnection":11,"webrtcsupport":4,"wildemitter":3}],14:[function(require,module,exports){ +},{"getusermedia":10,"hark":13,"mediastream-gain":14,"mockconsole":7,"rtcpeerconnection":12,"webrtcsupport":11,"wildemitter":3}],15:[function(require,module,exports){ var events = require('events'); exports.isArray = isArray; @@ -5480,7 +5572,7 @@ exports.format = function(f) { return str; }; -},{"events":15}],16:[function(require,module,exports){ +},{"events":16}],17:[function(require,module,exports){ // Underscore.js 1.6.0 // http://underscorejs.org // (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors @@ -6825,7 +6917,7 @@ exports.format = function(f) { } }).call(this); -},{}],17:[function(require,module,exports){ +},{}],18:[function(require,module,exports){ /* WildEmitter.js is a slim little event emitter by @henrikjoreteg largely based on @visionmedia's Emitter from UI Kit. @@ -6966,323 +7058,72 @@ WildEmitter.prototype.getWildcardCallbacks = function (eventName) { return result; }; -},{}],18:[function(require,module,exports){ -// shim for using process in browser +},{}],12:[function(require,module,exports){ +var _ = require('underscore'); +var util = require('util'); +var webrtc = require('webrtcsupport'); +var SJJ = require('sdp-jingle-json'); +var WildEmitter = require('wildemitter'); +var peerconn = require('traceablepeerconnection'); -var process = module.exports = {}; +function PeerConnection(config, constraints) { + var self = this; + var item; + WildEmitter.call(this); -process.nextTick = (function () { - var canSetImmediate = typeof window !== 'undefined' - && window.setImmediate; - var canPost = typeof window !== 'undefined' - && window.postMessage && window.addEventListener - ; + config = config || {}; + config.iceServers = config.iceServers || []; - if (canSetImmediate) { - return function (f) { return window.setImmediate(f) }; - } + this.pc = new peerconn(config, constraints); + // proxy events + this.pc.on('*', function () { + self.emit.apply(self, arguments); + }); - if (canPost) { - var queue = []; - window.addEventListener('message', function (ev) { - var source = ev.source; - if ((source === window || source === null) && ev.data === 'process-tick') { - ev.stopPropagation(); - if (queue.length > 0) { - var fn = queue.shift(); - fn(); - } - } - }, true); + // proxy some events directly + this.pc.onremovestream = this.emit.bind(this, 'removeStream'); + this.pc.onnegotiationneeded = this.emit.bind(this, 'negotiationNeeded'); + this.pc.oniceconnectionstatechange = this.emit.bind(this, 'iceConnectionStateChange'); + this.pc.onsignalingstatechange = this.emit.bind(this, 'signalingStateChange'); - return function nextTick(fn) { - queue.push(fn); - window.postMessage('process-tick', '*'); - }; - } + // handle incoming ice and data channel events + this.pc.onaddstream = this._onAddStream.bind(this); + this.pc.onicecandidate = this._onIce.bind(this); + this.pc.ondatachannel = this._onDataChannel.bind(this); - return function nextTick(fn) { - setTimeout(fn, 0); + this.localDescription = { + contents: [] + }; + this.remoteDescription = { + contents: [] }; -})(); - -process.title = 'browser'; -process.browser = true; -process.env = {}; -process.argv = []; - -process.binding = function (name) { - throw new Error('process.binding is not supported'); -} -// TODO(shtylman) -process.cwd = function () { return '/' }; -process.chdir = function (dir) { - throw new Error('process.chdir is not supported'); -}; + this.localStream = null; + this.remoteStreams = []; -},{}],15:[function(require,module,exports){ -var process=require("__browserify_process");if (!process.EventEmitter) process.EventEmitter = function () {}; + this.config = { + debug: false, + ice: {}, + sid: '', + isInitiator: true, + sdpSessionID: Date.now(), + useJingle: false + }; -var EventEmitter = exports.EventEmitter = process.EventEmitter; -var isArray = typeof Array.isArray === 'function' - ? Array.isArray - : function (xs) { - return Object.prototype.toString.call(xs) === '[object Array]' + // apply our config + for (item in config) { + this.config[item] = config[item]; } -; -function indexOf (xs, x) { - if (xs.indexOf) return xs.indexOf(x); - for (var i = 0; i < xs.length; i++) { - if (x === xs[i]) return i; + + if (this.config.debug) { + this.on('*', function (eventName, event) { + var logger = config.logger || console; + logger.log('PeerConnection event:', arguments); + }); } - return -1; } -// By default EventEmitters will print a warning if more than -// 10 listeners are added to it. This is a useful default which -// helps finding memory leaks. -// -// Obviously not all Emitters should be limited to 10. This function allows -// that to be increased. Set to zero for unlimited. -var defaultMaxListeners = 10; -EventEmitter.prototype.setMaxListeners = function(n) { - if (!this._events) this._events = {}; - this._events.maxListeners = n; -}; - - -EventEmitter.prototype.emit = function(type) { - // If there is no 'error' event listener then throw. - if (type === 'error') { - if (!this._events || !this._events.error || - (isArray(this._events.error) && !this._events.error.length)) - { - if (arguments[1] instanceof Error) { - throw arguments[1]; // Unhandled 'error' event - } else { - throw new Error("Uncaught, unspecified 'error' event."); - } - return false; - } - } - - if (!this._events) return false; - var handler = this._events[type]; - if (!handler) return false; - - if (typeof handler == 'function') { - switch (arguments.length) { - // fast cases - case 1: - handler.call(this); - break; - case 2: - handler.call(this, arguments[1]); - break; - case 3: - handler.call(this, arguments[1], arguments[2]); - break; - // slower - default: - var args = Array.prototype.slice.call(arguments, 1); - handler.apply(this, args); - } - return true; - - } else if (isArray(handler)) { - var args = Array.prototype.slice.call(arguments, 1); - - var listeners = handler.slice(); - for (var i = 0, l = listeners.length; i < l; i++) { - listeners[i].apply(this, args); - } - return true; - - } else { - return false; - } -}; - -// EventEmitter is defined in src/node_events.cc -// EventEmitter.prototype.emit() is also defined there. -EventEmitter.prototype.addListener = function(type, listener) { - if ('function' !== typeof listener) { - throw new Error('addListener only takes instances of Function'); - } - - if (!this._events) this._events = {}; - - // To avoid recursion in the case that type == "newListeners"! Before - // adding it to the listeners, first emit "newListeners". - this.emit('newListener', type, listener); - - if (!this._events[type]) { - // Optimize the case of one listener. Don't need the extra array object. - this._events[type] = listener; - } else if (isArray(this._events[type])) { - - // Check for listener leak - if (!this._events[type].warned) { - var m; - if (this._events.maxListeners !== undefined) { - m = this._events.maxListeners; - } else { - m = defaultMaxListeners; - } - - if (m && m > 0 && this._events[type].length > m) { - this._events[type].warned = true; - console.error('(node) warning: possible EventEmitter memory ' + - 'leak detected. %d listeners added. ' + - 'Use emitter.setMaxListeners() to increase limit.', - this._events[type].length); - console.trace(); - } - } - - // If we've already got an array, just append. - this._events[type].push(listener); - } else { - // Adding the second element, need to change to array. - this._events[type] = [this._events[type], listener]; - } - - return this; -}; - -EventEmitter.prototype.on = EventEmitter.prototype.addListener; - -EventEmitter.prototype.once = function(type, listener) { - var self = this; - self.on(type, function g() { - self.removeListener(type, g); - listener.apply(this, arguments); - }); - - return this; -}; - -EventEmitter.prototype.removeListener = function(type, listener) { - if ('function' !== typeof listener) { - throw new Error('removeListener only takes instances of Function'); - } - - // does not use listeners(), so no side effect of creating _events[type] - if (!this._events || !this._events[type]) return this; - - var list = this._events[type]; - - if (isArray(list)) { - var i = indexOf(list, listener); - if (i < 0) return this; - list.splice(i, 1); - if (list.length == 0) - delete this._events[type]; - } else if (this._events[type] === listener) { - delete this._events[type]; - } - - return this; -}; - -EventEmitter.prototype.removeAllListeners = function(type) { - if (arguments.length === 0) { - this._events = {}; - return this; - } - - // does not use listeners(), so no side effect of creating _events[type] - if (type && this._events && this._events[type]) this._events[type] = null; - return this; -}; - -EventEmitter.prototype.listeners = function(type) { - if (!this._events) this._events = {}; - if (!this._events[type]) this._events[type] = []; - if (!isArray(this._events[type])) { - this._events[type] = [this._events[type]]; - } - return this._events[type]; -}; - -EventEmitter.listenerCount = function(emitter, type) { - var ret; - if (!emitter._events || !emitter._events[type]) - ret = 0; - else if (typeof emitter._events[type] === 'function') - ret = 1; - else - ret = emitter._events[type].length; - return ret; -}; - -},{"__browserify_process":18}],11:[function(require,module,exports){ -var _ = require('underscore'); -var util = require('util'); -var webrtc = require('webrtcsupport'); -var SJJ = require('sdp-jingle-json'); -var WildEmitter = require('wildemitter'); -var peerconn = require('traceablepeerconnection'); - -function PeerConnection(config, constraints) { - var self = this; - var item; - WildEmitter.call(this); - - config = config || {}; - config.iceServers = config.iceServers || []; - - this.pc = new peerconn(config, constraints); - // proxy events - this.pc.on('*', function () { - self.emit.apply(self, arguments); - }); - - // proxy some events directly - this.pc.onremovestream = this.emit.bind(this, 'removeStream'); - this.pc.onnegotiationneeded = this.emit.bind(this, 'negotiationNeeded'); - this.pc.oniceconnectionstatechange = this.emit.bind(this, 'iceConnectionStateChange'); - this.pc.onsignalingstatechange = this.emit.bind(this, 'signalingStateChange'); - - // handle incoming ice and data channel events - this.pc.onaddstream = this._onAddStream.bind(this); - this.pc.onicecandidate = this._onIce.bind(this); - this.pc.ondatachannel = this._onDataChannel.bind(this); - - this.localDescription = { - contents: [] - }; - this.remoteDescription = { - contents: [] - }; - - this.localStream = null; - this.remoteStreams = []; - - this.config = { - debug: false, - ice: {}, - sid: '', - isInitiator: true, - sdpSessionID: Date.now(), - useJingle: false - }; - - // apply our config - for (item in config) { - this.config[item] = config[item]; - } - - if (this.config.debug) { - this.on('*', function (eventName, event) { - var logger = config.logger || console; - logger.log('PeerConnection event:', arguments); - }); - } -} - -util.inherits(PeerConnection, WildEmitter); +util.inherits(PeerConnection, WildEmitter); if (PeerConnection.prototype.__defineGetter__) { PeerConnection.prototype.__defineGetter__('signalingState', function () { @@ -7580,7 +7421,7 @@ PeerConnection.prototype.createDataChannel = function (name, opts) { module.exports = PeerConnection; -},{"sdp-jingle-json":20,"traceablepeerconnection":19,"underscore":16,"util":14,"webrtcsupport":4,"wildemitter":17}],13:[function(require,module,exports){ +},{"sdp-jingle-json":20,"traceablepeerconnection":19,"underscore":17,"util":15,"webrtcsupport":11,"wildemitter":18}],14:[function(require,module,exports){ var support = require('webrtcsupport'); @@ -7627,28 +7468,279 @@ GainController.prototype.on = function () { module.exports = GainController; -},{"webrtcsupport":4}],12:[function(require,module,exports){ -var WildEmitter = require('wildemitter'); - -function getMaxVolume (analyser, fftBins) { - var maxVolume = -Infinity; - analyser.getFloatFrequencyData(fftBins); +},{"webrtcsupport":11}],21:[function(require,module,exports){ +// shim for using process in browser - for(var i=0, ii=fftBins.length; i < ii; i++) { - if (fftBins[i] > maxVolume && fftBins[i] < 0) { - maxVolume = fftBins[i]; - } - }; +var process = module.exports = {}; - return maxVolume; -} +process.nextTick = (function () { + var canSetImmediate = typeof window !== 'undefined' + && window.setImmediate; + var canPost = typeof window !== 'undefined' + && window.postMessage && window.addEventListener + ; + if (canSetImmediate) { + return function (f) { return window.setImmediate(f) }; + } -var audioContextType = window.webkitAudioContext || window.AudioContext; -// use a single audio context due to hardware limits -var audioContext = null; -module.exports = function(stream, options) { - var harker = new WildEmitter(); + if (canPost) { + var queue = []; + window.addEventListener('message', function (ev) { + var source = ev.source; + if ((source === window || source === null) && ev.data === 'process-tick') { + ev.stopPropagation(); + if (queue.length > 0) { + var fn = queue.shift(); + fn(); + } + } + }, true); + + return function nextTick(fn) { + queue.push(fn); + window.postMessage('process-tick', '*'); + }; + } + + return function nextTick(fn) { + setTimeout(fn, 0); + }; +})(); + +process.title = 'browser'; +process.browser = true; +process.env = {}; +process.argv = []; + +process.binding = function (name) { + throw new Error('process.binding is not supported'); +} + +// TODO(shtylman) +process.cwd = function () { return '/' }; +process.chdir = function (dir) { + throw new Error('process.chdir is not supported'); +}; + +},{}],16:[function(require,module,exports){ +var process=require("__browserify_process");if (!process.EventEmitter) process.EventEmitter = function () {}; + +var EventEmitter = exports.EventEmitter = process.EventEmitter; +var isArray = typeof Array.isArray === 'function' + ? Array.isArray + : function (xs) { + return Object.prototype.toString.call(xs) === '[object Array]' + } +; +function indexOf (xs, x) { + if (xs.indexOf) return xs.indexOf(x); + for (var i = 0; i < xs.length; i++) { + if (x === xs[i]) return i; + } + return -1; +} + +// By default EventEmitters will print a warning if more than +// 10 listeners are added to it. This is a useful default which +// helps finding memory leaks. +// +// Obviously not all Emitters should be limited to 10. This function allows +// that to be increased. Set to zero for unlimited. +var defaultMaxListeners = 10; +EventEmitter.prototype.setMaxListeners = function(n) { + if (!this._events) this._events = {}; + this._events.maxListeners = n; +}; + + +EventEmitter.prototype.emit = function(type) { + // If there is no 'error' event listener then throw. + if (type === 'error') { + if (!this._events || !this._events.error || + (isArray(this._events.error) && !this._events.error.length)) + { + if (arguments[1] instanceof Error) { + throw arguments[1]; // Unhandled 'error' event + } else { + throw new Error("Uncaught, unspecified 'error' event."); + } + return false; + } + } + + if (!this._events) return false; + var handler = this._events[type]; + if (!handler) return false; + + if (typeof handler == 'function') { + switch (arguments.length) { + // fast cases + case 1: + handler.call(this); + break; + case 2: + handler.call(this, arguments[1]); + break; + case 3: + handler.call(this, arguments[1], arguments[2]); + break; + // slower + default: + var args = Array.prototype.slice.call(arguments, 1); + handler.apply(this, args); + } + return true; + + } else if (isArray(handler)) { + var args = Array.prototype.slice.call(arguments, 1); + + var listeners = handler.slice(); + for (var i = 0, l = listeners.length; i < l; i++) { + listeners[i].apply(this, args); + } + return true; + + } else { + return false; + } +}; + +// EventEmitter is defined in src/node_events.cc +// EventEmitter.prototype.emit() is also defined there. +EventEmitter.prototype.addListener = function(type, listener) { + if ('function' !== typeof listener) { + throw new Error('addListener only takes instances of Function'); + } + + if (!this._events) this._events = {}; + + // To avoid recursion in the case that type == "newListeners"! Before + // adding it to the listeners, first emit "newListeners". + this.emit('newListener', type, listener); + + if (!this._events[type]) { + // Optimize the case of one listener. Don't need the extra array object. + this._events[type] = listener; + } else if (isArray(this._events[type])) { + + // Check for listener leak + if (!this._events[type].warned) { + var m; + if (this._events.maxListeners !== undefined) { + m = this._events.maxListeners; + } else { + m = defaultMaxListeners; + } + + if (m && m > 0 && this._events[type].length > m) { + this._events[type].warned = true; + console.error('(node) warning: possible EventEmitter memory ' + + 'leak detected. %d listeners added. ' + + 'Use emitter.setMaxListeners() to increase limit.', + this._events[type].length); + console.trace(); + } + } + + // If we've already got an array, just append. + this._events[type].push(listener); + } else { + // Adding the second element, need to change to array. + this._events[type] = [this._events[type], listener]; + } + + return this; +}; + +EventEmitter.prototype.on = EventEmitter.prototype.addListener; + +EventEmitter.prototype.once = function(type, listener) { + var self = this; + self.on(type, function g() { + self.removeListener(type, g); + listener.apply(this, arguments); + }); + + return this; +}; + +EventEmitter.prototype.removeListener = function(type, listener) { + if ('function' !== typeof listener) { + throw new Error('removeListener only takes instances of Function'); + } + + // does not use listeners(), so no side effect of creating _events[type] + if (!this._events || !this._events[type]) return this; + + var list = this._events[type]; + + if (isArray(list)) { + var i = indexOf(list, listener); + if (i < 0) return this; + list.splice(i, 1); + if (list.length == 0) + delete this._events[type]; + } else if (this._events[type] === listener) { + delete this._events[type]; + } + + return this; +}; + +EventEmitter.prototype.removeAllListeners = function(type) { + if (arguments.length === 0) { + this._events = {}; + return this; + } + + // does not use listeners(), so no side effect of creating _events[type] + if (type && this._events && this._events[type]) this._events[type] = null; + return this; +}; + +EventEmitter.prototype.listeners = function(type) { + if (!this._events) this._events = {}; + if (!this._events[type]) this._events[type] = []; + if (!isArray(this._events[type])) { + this._events[type] = [this._events[type]]; + } + return this._events[type]; +}; + +EventEmitter.listenerCount = function(emitter, type) { + var ret; + if (!emitter._events || !emitter._events[type]) + ret = 0; + else if (typeof emitter._events[type] === 'function') + ret = 1; + else + ret = emitter._events[type].length; + return ret; +}; + +},{"__browserify_process":21}],13:[function(require,module,exports){ +var WildEmitter = require('wildemitter'); + +function getMaxVolume (analyser, fftBins) { + var maxVolume = -Infinity; + analyser.getFloatFrequencyData(fftBins); + + for(var i=0, ii=fftBins.length; i < ii; i++) { + if (fftBins[i] > maxVolume && fftBins[i] < 0) { + maxVolume = fftBins[i]; + } + }; + + return maxVolume; +} + + +var audioContextType = window.webkitAudioContext || window.AudioContext; +// use a single audio context due to hardware limits +var audioContext = null; +module.exports = function(stream, options) { + var harker = new WildEmitter(); // make it not break in non-supported browsers @@ -7755,7 +7847,7 @@ exports.toSessionJSON = tojson.toSessionJSON; exports.toMediaJSON = tojson.toMediaJSON; exports.toCandidateJSON = tojson.toCandidateJSON; -},{"./lib/tojson":22,"./lib/tosdp":21}],21:[function(require,module,exports){ +},{"./lib/tojson":23,"./lib/tosdp":22}],22:[function(require,module,exports){ var senders = { 'initiator': 'sendonly', 'responder': 'recvonly', @@ -7903,35 +7995,236 @@ exports.toMediaSDP = function (content) { return sdp.join('\r\n'); }; -exports.toCandidateSDP = function (candidate) { - var sdp = []; - - sdp.push(candidate.foundation); - sdp.push(candidate.component); - sdp.push(candidate.protocol); - sdp.push(candidate.priority); - sdp.push(candidate.ip); - sdp.push(candidate.port); - - var type = candidate.type; - sdp.push('typ'); - sdp.push(type); - if (type === 'srflx' || type === 'prflx' || type === 'relay') { - if (candidate.relAddr && candidate.relPort) { - sdp.push('raddr'); - sdp.push(candidate.relAddr); - sdp.push('rport'); - sdp.push(candidate.relPort); +exports.toCandidateSDP = function (candidate) { + var sdp = []; + + sdp.push(candidate.foundation); + sdp.push(candidate.component); + sdp.push(candidate.protocol); + sdp.push(candidate.priority); + sdp.push(candidate.ip); + sdp.push(candidate.port); + + var type = candidate.type; + sdp.push('typ'); + sdp.push(type); + if (type === 'srflx' || type === 'prflx' || type === 'relay') { + if (candidate.relAddr && candidate.relPort) { + sdp.push('raddr'); + sdp.push(candidate.relAddr); + sdp.push('rport'); + sdp.push(candidate.relPort); + } + } + + sdp.push('generation'); + sdp.push(candidate.generation || '0'); + + return 'a=candidate:' + sdp.join(' '); +}; + +},{}],19:[function(require,module,exports){ +// based on https://github.com/ESTOS/strophe.jingle/ +// adds wildemitter support +var util = require('util'); +var webrtc = require('webrtcsupport'); +var WildEmitter = require('wildemitter'); + +function dumpSDP(description) { + return 'type: ' + description.type + '\r\n' + description.sdp; +} + +function TraceablePeerConnection(config, constraints) { + var self = this; + WildEmitter.call(this); + + this.peerconnection = new webrtc.PeerConnection(config, constraints); + + this.trace = function (what, info) { + self.emit('PeerConnectionTrace', { + time: new Date(), + type: what, + value: info || "" + }); + }; + + this.onicecandidate = null; + this.peerconnection.onicecandidate = function (event) { + self.trace('onicecandidate', JSON.stringify(event.candidate, null, ' ')); + if (self.onicecandidate !== null) { + self.onicecandidate(event); + } + }; + this.onaddstream = null; + this.peerconnection.onaddstream = function (event) { + self.trace('onaddstream', event.stream.id); + if (self.onaddstream !== null) { + self.onaddstream(event); + } + }; + this.onremovestream = null; + this.peerconnection.onremovestream = function (event) { + self.trace('onremovestream', event.stream.id); + if (self.onremovestream !== null) { + self.onremovestream(event); + } + }; + this.onsignalingstatechange = null; + this.peerconnection.onsignalingstatechange = function (event) { + self.trace('onsignalingstatechange', self.signalingState); + if (self.onsignalingstatechange !== null) { + self.onsignalingstatechange(event); + } + }; + this.oniceconnectionstatechange = null; + this.peerconnection.oniceconnectionstatechange = function (event) { + self.trace('oniceconnectionstatechange', self.iceConnectionState); + if (self.oniceconnectionstatechange !== null) { + self.oniceconnectionstatechange(event); + } + }; + this.onnegotiationneeded = null; + this.peerconnection.onnegotiationneeded = function (event) { + self.trace('onnegotiationneeded'); + if (self.onnegotiationneeded !== null) { + self.onnegotiationneeded(event); + } + }; + self.ondatachannel = null; + this.peerconnection.ondatachannel = function (event) { + self.trace('ondatachannel', event); + if (self.ondatachannel !== null) { + self.ondatachannel(event); + } + }; +} + +util.inherits(TraceablePeerConnection, WildEmitter); + +if (TraceablePeerConnection.prototype.__defineGetter__ !== undefined) { + TraceablePeerConnection.prototype.__defineGetter__('signalingState', function () { return this.peerconnection.signalingState; }); + TraceablePeerConnection.prototype.__defineGetter__('iceConnectionState', function () { return this.peerconnection.iceConnectionState; }); + TraceablePeerConnection.prototype.__defineGetter__('localDescription', function () { return this.peerconnection.localDescription; }); + TraceablePeerConnection.prototype.__defineGetter__('remoteDescription', function () { return this.peerconnection.remoteDescription; }); +} + +TraceablePeerConnection.prototype.addStream = function (stream) { + this.trace('addStream', stream.id); + this.peerconnection.addStream(stream); +}; + +TraceablePeerConnection.prototype.removeStream = function (stream) { + this.trace('removeStream', stream.id); + this.peerconnection.removeStream(stream); +}; + +TraceablePeerConnection.prototype.createDataChannel = function (label, opts) { + this.trace('createDataChannel', label, opts); + return this.peerconnection.createDataChannel(label, opts); +}; + +TraceablePeerConnection.prototype.setLocalDescription = function (description, successCallback, failureCallback) { + var self = this; + this.trace('setLocalDescription', dumpSDP(description)); + this.peerconnection.setLocalDescription(description, + function () { + self.trace('setLocalDescriptionOnSuccess'); + successCallback(); + }, + function (err) { + self.trace('setLocalDescriptionOnFailure', err); + failureCallback(err); + } + ); +}; + +TraceablePeerConnection.prototype.setRemoteDescription = function (description, successCallback, failureCallback) { + var self = this; + this.trace('setRemoteDescription', dumpSDP(description)); + this.peerconnection.setRemoteDescription(description, + function () { + self.trace('setRemoteDescriptionOnSuccess'); + successCallback(); + }, + function (err) { + self.trace('setRemoteDescriptionOnFailure', err); + failureCallback(err); + } + ); +}; + +TraceablePeerConnection.prototype.close = function () { + this.trace('stop'); + if (this.statsinterval !== null) { + window.clearInterval(this.statsinterval); + this.statsinterval = null; + } + if (this.peerconnection.signalingState != 'closed') { + this.peerconnection.close(); + } +}; + +TraceablePeerConnection.prototype.createOffer = function (successCallback, failureCallback, constraints) { + var self = this; + this.trace('createOffer', JSON.stringify(constraints, null, ' ')); + this.peerconnection.createOffer( + function (offer) { + self.trace('createOfferOnSuccess', dumpSDP(offer)); + successCallback(offer); + }, + function (err) { + self.trace('createOfferOnFailure', err); + failureCallback(err); + }, + constraints + ); +}; + +TraceablePeerConnection.prototype.createAnswer = function (successCallback, failureCallback, constraints) { + var self = this; + this.trace('createAnswer', JSON.stringify(constraints, null, ' ')); + this.peerconnection.createAnswer( + function (answer) { + self.trace('createAnswerOnSuccess', dumpSDP(answer)); + successCallback(answer); + }, + function (err) { + self.trace('createAnswerOnFailure', err); + failureCallback(err); + }, + constraints + ); +}; + +TraceablePeerConnection.prototype.addIceCandidate = function (candidate, successCallback, failureCallback) { + var self = this; + this.trace('addIceCandidate', JSON.stringify(candidate, null, ' ')); + this.peerconnection.addIceCandidate(candidate); + /* maybe later + this.peerconnection.addIceCandidate(candidate, + function () { + self.trace('addIceCandidateOnSuccess'); + successCallback(); + }, + function (err) { + self.trace('addIceCandidateOnFailure', err); + failureCallback(err); } - } - - sdp.push('generation'); - sdp.push(candidate.generation || '0'); + ); + */ +}; - return 'a=candidate:' + sdp.join(' '); +TraceablePeerConnection.prototype.getStats = function (callback, errback) { + if (navigator.mozGetUserMedia) { + // ignore for now... + } else { + this.peerconnection.getStats(callback); + } }; -},{}],22:[function(require,module,exports){ +module.exports = TraceablePeerConnection; + +},{"util":15,"webrtcsupport":11,"wildemitter":18}],23:[function(require,module,exports){ var parsers = require('./parsers'); var idCounter = Math.random(); @@ -8097,7 +8390,7 @@ exports.toCandidateJSON = function (line) { return candidate; }; -},{"./parsers":23}],23:[function(require,module,exports){ +},{"./parsers":24}],24:[function(require,module,exports){ exports.lines = function (sdp) { return sdp.split('\r\n').filter(function (line) { return line.length > 0; @@ -8331,207 +8624,6 @@ exports.groups = function (lines) { return parsed; }; -},{}],19:[function(require,module,exports){ -// based on https://github.com/ESTOS/strophe.jingle/ -// adds wildemitter support -var util = require('util'); -var webrtc = require('webrtcsupport'); -var WildEmitter = require('wildemitter'); - -function dumpSDP(description) { - return 'type: ' + description.type + '\r\n' + description.sdp; -} - -function TraceablePeerConnection(config, constraints) { - var self = this; - WildEmitter.call(this); - - this.peerconnection = new webrtc.PeerConnection(config, constraints); - - this.trace = function (what, info) { - self.emit('PeerConnectionTrace', { - time: new Date(), - type: what, - value: info || "" - }); - }; - - this.onicecandidate = null; - this.peerconnection.onicecandidate = function (event) { - self.trace('onicecandidate', JSON.stringify(event.candidate, null, ' ')); - if (self.onicecandidate !== null) { - self.onicecandidate(event); - } - }; - this.onaddstream = null; - this.peerconnection.onaddstream = function (event) { - self.trace('onaddstream', event.stream.id); - if (self.onaddstream !== null) { - self.onaddstream(event); - } - }; - this.onremovestream = null; - this.peerconnection.onremovestream = function (event) { - self.trace('onremovestream', event.stream.id); - if (self.onremovestream !== null) { - self.onremovestream(event); - } - }; - this.onsignalingstatechange = null; - this.peerconnection.onsignalingstatechange = function (event) { - self.trace('onsignalingstatechange', self.signalingState); - if (self.onsignalingstatechange !== null) { - self.onsignalingstatechange(event); - } - }; - this.oniceconnectionstatechange = null; - this.peerconnection.oniceconnectionstatechange = function (event) { - self.trace('oniceconnectionstatechange', self.iceConnectionState); - if (self.oniceconnectionstatechange !== null) { - self.oniceconnectionstatechange(event); - } - }; - this.onnegotiationneeded = null; - this.peerconnection.onnegotiationneeded = function (event) { - self.trace('onnegotiationneeded'); - if (self.onnegotiationneeded !== null) { - self.onnegotiationneeded(event); - } - }; - self.ondatachannel = null; - this.peerconnection.ondatachannel = function (event) { - self.trace('ondatachannel', event); - if (self.ondatachannel !== null) { - self.ondatachannel(event); - } - }; -} - -util.inherits(TraceablePeerConnection, WildEmitter); - -if (TraceablePeerConnection.prototype.__defineGetter__ !== undefined) { - TraceablePeerConnection.prototype.__defineGetter__('signalingState', function () { return this.peerconnection.signalingState; }); - TraceablePeerConnection.prototype.__defineGetter__('iceConnectionState', function () { return this.peerconnection.iceConnectionState; }); - TraceablePeerConnection.prototype.__defineGetter__('localDescription', function () { return this.peerconnection.localDescription; }); - TraceablePeerConnection.prototype.__defineGetter__('remoteDescription', function () { return this.peerconnection.remoteDescription; }); -} - -TraceablePeerConnection.prototype.addStream = function (stream) { - this.trace('addStream', stream.id); - this.peerconnection.addStream(stream); -}; - -TraceablePeerConnection.prototype.removeStream = function (stream) { - this.trace('removeStream', stream.id); - this.peerconnection.removeStream(stream); -}; - -TraceablePeerConnection.prototype.createDataChannel = function (label, opts) { - this.trace('createDataChannel', label, opts); - return this.peerconnection.createDataChannel(label, opts); -}; - -TraceablePeerConnection.prototype.setLocalDescription = function (description, successCallback, failureCallback) { - var self = this; - this.trace('setLocalDescription', dumpSDP(description)); - this.peerconnection.setLocalDescription(description, - function () { - self.trace('setLocalDescriptionOnSuccess'); - successCallback(); - }, - function (err) { - self.trace('setLocalDescriptionOnFailure', err); - failureCallback(err); - } - ); -}; - -TraceablePeerConnection.prototype.setRemoteDescription = function (description, successCallback, failureCallback) { - var self = this; - this.trace('setRemoteDescription', dumpSDP(description)); - this.peerconnection.setRemoteDescription(description, - function () { - self.trace('setRemoteDescriptionOnSuccess'); - successCallback(); - }, - function (err) { - self.trace('setRemoteDescriptionOnFailure', err); - failureCallback(err); - } - ); -}; - -TraceablePeerConnection.prototype.close = function () { - this.trace('stop'); - if (this.statsinterval !== null) { - window.clearInterval(this.statsinterval); - this.statsinterval = null; - } - if (this.peerconnection.signalingState != 'closed') { - this.peerconnection.close(); - } -}; - -TraceablePeerConnection.prototype.createOffer = function (successCallback, failureCallback, constraints) { - var self = this; - this.trace('createOffer', JSON.stringify(constraints, null, ' ')); - this.peerconnection.createOffer( - function (offer) { - self.trace('createOfferOnSuccess', dumpSDP(offer)); - successCallback(offer); - }, - function (err) { - self.trace('createOfferOnFailure', err); - failureCallback(err); - }, - constraints - ); -}; - -TraceablePeerConnection.prototype.createAnswer = function (successCallback, failureCallback, constraints) { - var self = this; - this.trace('createAnswer', JSON.stringify(constraints, null, ' ')); - this.peerconnection.createAnswer( - function (answer) { - self.trace('createAnswerOnSuccess', dumpSDP(answer)); - successCallback(answer); - }, - function (err) { - self.trace('createAnswerOnFailure', err); - failureCallback(err); - }, - constraints - ); -}; - -TraceablePeerConnection.prototype.addIceCandidate = function (candidate, successCallback, failureCallback) { - var self = this; - this.trace('addIceCandidate', JSON.stringify(candidate, null, ' ')); - this.peerconnection.addIceCandidate(candidate); - /* maybe later - this.peerconnection.addIceCandidate(candidate, - function () { - self.trace('addIceCandidateOnSuccess'); - successCallback(); - }, - function (err) { - self.trace('addIceCandidateOnFailure', err); - failureCallback(err); - } - ); - */ -}; - -TraceablePeerConnection.prototype.getStats = function (callback, errback) { - if (navigator.mozGetUserMedia) { - // ignore for now... - } else { - this.peerconnection.getStats(callback); - } -}; - -module.exports = TraceablePeerConnection; - -},{"util":14,"webrtcsupport":4,"wildemitter":17}]},{},[1])(1) +},{}]},{},[1])(1) }); -; +; \ No newline at end of file