diff --git a/public/js/simplewebrtc.bundle.js b/public/js/simplewebrtc.bundle.js
index 1141605..9e707b9 100644
--- a/public/js/simplewebrtc.bundle.js
+++ b/public/js/simplewebrtc.bundle.js
@@ -463,59 +463,7 @@ SimpleWebRTC.prototype.sendFile = function () {
module.exports = SimpleWebRTC;
-},{"./socketioconnection":3,"./webrtc":2,"attachmediastream":7,"mockconsole":6,"webrtcsupport":5,"wildemitter":4}],5:[function(require,module,exports){
-// created by @HenrikJoreteg
-var prefix;
-var version;
-
-if (window.mozRTCPeerConnection || navigator.mozGetUserMedia) {
- prefix = 'moz';
- version = parseInt(navigator.userAgent.match(/Firefox\/([0-9]+)\./)[1], 10);
-} else if (window.webkitRTCPeerConnection || navigator.webkitGetUserMedia) {
- prefix = 'webkit';
- version = navigator.userAgent.match(/Chrom(e|ium)/) && parseInt(navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./)[2], 10);
-}
-
-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:' &&
- ((prefix === 'webkit' && version >= 26) ||
- (prefix === 'moz' && version >= 33))
-var AudioContext = window.AudioContext || window.webkitAudioContext;
-var videoEl = document.createElement('video');
-var supportVp8 = videoEl && videoEl.canPlayType && videoEl.canPlayType('video/webm; codecs="vp8", vorbis') === "probably";
-var getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.msGetUserMedia || navigator.mozGetUserMedia;
-
-// export support flags and constructors.prototype && PC
-module.exports = {
- prefix: prefix,
- browserVersion: version,
- support: !!PC && supportVp8 && !!getUserMedia,
- // new support style
- supportRTCPeerConnection: !!PC,
- supportVp8: supportVp8,
- supportGetUserMedia: !!getUserMedia,
- supportDataChannel: !!(PC && PC.prototype && PC.prototype.createDataChannel),
- supportWebAudio: !!(AudioContext && AudioContext.prototype.createMediaStreamSource),
- supportMediaStream: !!(MediaStream && MediaStream.prototype.removeTrack),
- supportScreenSharing: !!screenSharing,
- // old deprecated style. Dont use this anymore
- dataChannel: !!(PC && PC.prototype && PC.prototype.createDataChannel),
- webAudio: !!(AudioContext && AudioContext.prototype.createMediaStreamSource),
- mediaStream: !!(MediaStream && MediaStream.prototype.removeTrack),
- screenSharing: !!screenSharing,
- // constructors
- AudioContext: AudioContext,
- PeerConnection: PC,
- SessionDescription: SessionDescription,
- IceCandidate: IceCandidate,
- MediaStream: MediaStream,
- getUserMedia: getUserMedia
-};
-
-},{}],4:[function(require,module,exports){
+},{"./socketioconnection":3,"./webrtc":2,"attachmediastream":7,"mockconsole":6,"webrtcsupport":5,"wildemitter":4}],4:[function(require,module,exports){
/*
WildEmitter.js is a slim little event emitter by @henrikjoreteg largely based
on @visionmedia's Emitter from UI Kit.
@@ -660,6 +608,58 @@ WildEmitter.prototype.getWildcardCallbacks = function (eventName) {
return result;
};
+},{}],5:[function(require,module,exports){
+// created by @HenrikJoreteg
+var prefix;
+var version;
+
+if (window.mozRTCPeerConnection || navigator.mozGetUserMedia) {
+ prefix = 'moz';
+ version = parseInt(navigator.userAgent.match(/Firefox\/([0-9]+)\./)[1], 10);
+} else if (window.webkitRTCPeerConnection || navigator.webkitGetUserMedia) {
+ prefix = 'webkit';
+ version = navigator.userAgent.match(/Chrom(e|ium)/) && parseInt(navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./)[2], 10);
+}
+
+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:' &&
+ ((prefix === 'webkit' && version >= 26) ||
+ (prefix === 'moz' && version >= 33))
+var AudioContext = window.AudioContext || window.webkitAudioContext;
+var videoEl = document.createElement('video');
+var supportVp8 = videoEl && videoEl.canPlayType && videoEl.canPlayType('video/webm; codecs="vp8", vorbis') === "probably";
+var getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.msGetUserMedia || navigator.mozGetUserMedia;
+
+// export support flags and constructors.prototype && PC
+module.exports = {
+ prefix: prefix,
+ browserVersion: version,
+ support: !!PC && supportVp8 && !!getUserMedia,
+ // new support style
+ supportRTCPeerConnection: !!PC,
+ supportVp8: supportVp8,
+ supportGetUserMedia: !!getUserMedia,
+ supportDataChannel: !!(PC && PC.prototype && PC.prototype.createDataChannel),
+ supportWebAudio: !!(AudioContext && AudioContext.prototype.createMediaStreamSource),
+ supportMediaStream: !!(MediaStream && MediaStream.prototype.removeTrack),
+ supportScreenSharing: !!screenSharing,
+ // old deprecated style. Dont use this anymore
+ dataChannel: !!(PC && PC.prototype && PC.prototype.createDataChannel),
+ webAudio: !!(AudioContext && AudioContext.prototype.createMediaStreamSource),
+ mediaStream: !!(MediaStream && MediaStream.prototype.removeTrack),
+ screenSharing: !!screenSharing,
+ // constructors
+ AudioContext: AudioContext,
+ PeerConnection: PC,
+ SessionDescription: SessionDescription,
+ IceCandidate: IceCandidate,
+ MediaStream: MediaStream,
+ getUserMedia: getUserMedia
+};
+
},{}],6:[function(require,module,exports){
var methods = "assert,count,debug,dir,dirxml,error,exception,group,groupCollapsed,groupEnd,info,log,markTimeline,profile,profileEnd,time,timeEnd,trace,warn".split(",");
var l = methods.length;
@@ -5389,6 +5389,9 @@ var INBAND_FILETRANSFER_V1 = 'https://simplewebrtc.com/protocol/filetransfer#inb
function Peer(options) {
var self = this;
+ // call emitter constructor
+ WildEmitter.call(this);
+
this.id = options.id;
this.parent = options.parent;
this.type = options.type || 'video';
@@ -5448,9 +5451,6 @@ function Peer(options) {
});
}
- // call emitter constructor
- WildEmitter.call(this);
-
this.on('channelOpen', function (channel) {
if (channel.protocol === INBAND_FILETRANSFER_V1) {
channel.onmessage = function (event) {
@@ -5506,7 +5506,7 @@ 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 {
+ } else {
this.parent.emit(message.type, {id: message.from, payload: message.payload, roomType: message.roomType});
}
};
@@ -5656,91 +5656,7 @@ Peer.prototype.sendFile = function (file) {
module.exports = Peer;
-},{"filetransfer":15,"rtcpeerconnection":14,"util":8,"webrtcsupport":5,"wildemitter":4}],16:[function(require,module,exports){
-// getUserMedia helper by @HenrikJoreteg
-var func = (window.navigator.getUserMedia ||
- window.navigator.webkitGetUserMedia ||
- window.navigator.mozGetUserMedia ||
- window.navigator.msGetUserMedia);
-
-
-module.exports = function (constraints, cb) {
- var options, error;
- var haveOpts = arguments.length === 2;
- var defaultOpts = {video: true, audio: true};
-
- var denied = 'PermissionDeniedError';
- var altDenied = 'PERMISSION_DENIED';
- var notSatisfied = 'ConstraintNotSatisfiedError';
-
- // make constraints optional
- if (!haveOpts) {
- cb = constraints;
- constraints = defaultOpts;
- }
-
- // treat lack of browser support like an error
- if (!func) {
- // throw proper error per spec
- error = new Error('MediaStreamError');
- error.name = 'NotSupportedError';
-
- // keep all callbacks async
- return window.setTimeout(function () {
- cb(error);
- }, 0);
- }
-
- // normalize error handling when no media types are requested
- if (!constraints.audio && !constraints.video) {
- error = new Error('MediaStreamError');
- error.name = 'NoMediaRequestedError';
-
- // keep all callbacks async
- return window.setTimeout(function () {
- cb(error);
- }, 0);
- }
-
- if (localStorage && localStorage.useFirefoxFakeDevice === "true") {
- constraints.fake = true;
- }
-
- func.call(window.navigator, constraints, function (stream) {
- cb(null, stream);
- }, function (err) {
- var error;
- // coerce into an error object since FF gives us a string
- // there are only two valid names according to the spec
- // we coerce all non-denied to "constraint not satisfied".
- if (typeof err === 'string') {
- error = new Error('MediaStreamError');
- if (err === denied || err === altDenied) {
- error.name = denied;
- } else {
- error.name = notSatisfied;
- }
- } else {
- // if we get an error object make sure '.name' property is set
- // according to spec: http://dev.w3.org/2011/webrtc/editor/getusermedia.html#navigatorusermediaerror-and-navigatorusermediaerrorcallback
- error = err;
- if (!error.name) {
- // this is likely chrome which
- // sets a property called "ERROR_DENIED" on the error object
- // if so we make sure to set a name
- if (error[denied]) {
- err.name = denied;
- } else {
- err.name = notSatisfied;
- }
- }
- }
-
- cb(error);
- });
-};
-
-},{}],10:[function(require,module,exports){
+},{"filetransfer":15,"rtcpeerconnection":14,"util":8,"webrtcsupport":5,"wildemitter":4}],10:[function(require,module,exports){
var util = require('util');
var hark = require('hark');
var webrtc = require('webrtcsupport');
@@ -5757,6 +5673,7 @@ function LocalMedia(opts) {
var config = this.config = {
autoAdjustMic: false,
detectSpeakingEvents: true,
+ audioFallback: false,
media: {
audio: true,
video: true
@@ -5791,6 +5708,7 @@ LocalMedia.prototype.start = function (mediaConstraints, cb) {
var constraints = mediaConstraints || this.config.media;
getUserMedia(constraints, function (err, stream) {
+
if (!err) {
if (constraints.audio && self.config.detectSpeakingEvents) {
self.setupAudioMonitor(stream, self.config.harkOptions);
@@ -5816,6 +5734,13 @@ LocalMedia.prototype.start = function (mediaConstraints, cb) {
};
self.emit('localStream', stream);
+ } else {
+ // Fallback for users without a camera
+ if (self.config.audioFallback && err.name === 'DevicesNotFoundError' && constraints.video !== false) {
+ constraints.video = false;
+ self.start(constraints, cb);
+ return;
+ }
}
if (cb) {
return cb(err, stream);
@@ -5827,23 +5752,35 @@ LocalMedia.prototype.stop = function (stream) {
var self = this;
// FIXME: duplicates cleanup code until fixed in FF
if (stream) {
- stream.stop();
- self.emit('localStreamStopped', stream);
+ stream.getTracks().forEach(function (track) { track.stop(); });
var idx = self.localStreams.indexOf(stream);
if (idx > -1) {
+ self.emit('localStreamStopped', stream);
self.localStreams = self.localStreams.splice(idx, 1);
+ } else {
+ idx = self.localScreens.indexOf(stream);
+ if (idx > -1) {
+ self.emit('localScreenStopped', stream);
+ self.localScreens = self.localScreens.splce(idx, 1);
+ }
}
} else {
- if (this.audioMonitor) {
- this.audioMonitor.stop();
- delete this.audioMonitor;
- }
- this.localStreams.forEach(function (stream) {
- stream.stop();
- self.emit('localStreamStopped', stream);
- });
- this.localStreams = [];
+ this.stopStreams();
+ this.stopScreenShare();
+ }
+};
+
+LocalMedia.prototype.stopStreams = function () {
+ var self = this;
+ if (this.audioMonitor) {
+ this.audioMonitor.stop();
+ delete this.audioMonitor;
}
+ this.localStreams.forEach(function (stream) {
+ stream.getTracks().forEach(function (track) { track.stop(); });
+ self.emit('localStreamStopped', stream);
+ });
+ this.localStreams = [];
};
LocalMedia.prototype.startScreenShare = function (cb) {
@@ -5873,11 +5810,14 @@ LocalMedia.prototype.startScreenShare = function (cb) {
};
LocalMedia.prototype.stopScreenShare = function (stream) {
+ var self = this;
if (stream) {
- stream.stop();
+ stream.getTracks().forEach(function (track) { track.stop(); });
+ this.emit('localScreenStopped', stream);
} else {
this.localScreens.forEach(function (stream) {
- stream.stop();
+ stream.getTracks().forEach(function (track) { track.stop(); });
+ self.emit('localScreenStopped', stream);
});
this.localScreens = [];
}
@@ -6018,51 +5958,676 @@ Object.defineProperty(LocalMedia.prototype, 'localScreen', {
module.exports = LocalMedia;
-},{"getscreenmedia":18,"getusermedia":16,"hark":17,"mediastream-gain":19,"mockconsole":6,"util":8,"webrtcsupport":5,"wildemitter":4}],14:[function(require,module,exports){
-var util = require('util');
-var each = require('lodash.foreach');
-var pluck = require('lodash.pluck');
-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);
+},{"getscreenmedia":17,"getusermedia":16,"hark":18,"mediastream-gain":19,"mockconsole":6,"util":8,"webrtcsupport":5,"wildemitter":4}],20:[function(require,module,exports){
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree.
+ */
+
+/* More information about these options at jshint.com/docs/options */
+/* jshint browser: true, camelcase: true, curly: true, devel: true,
+ eqeqeq: true, forin: false, globalstrict: true, node: true,
+ quotmark: single, undef: true, unused: strict */
+/* global mozRTCIceCandidate, mozRTCPeerConnection, Promise,
+mozRTCSessionDescription, webkitRTCPeerConnection, MediaStreamTrack */
+/* exported trace,requestUserMedia */
+
+'use strict';
+
+var getUserMedia = null;
+var attachMediaStream = null;
+var reattachMediaStream = null;
+var webrtcDetectedBrowser = null;
+var webrtcDetectedVersion = null;
+var webrtcMinimumVersion = null;
+var webrtcUtils = {
+ log: function() {
+ // suppress console.log output when being included as a module.
+ if (typeof module !== 'undefined' ||
+ typeof require === 'function' && typeof define === 'function') {
+ return;
+ }
+ console.log.apply(console, arguments);
+ }
+};
- config = config || {};
- config.iceServers = config.iceServers || [];
+function trace(text) {
+ // This function is used for logging.
+ if (text[text.length - 1] === '\n') {
+ text = text.substring(0, text.length - 1);
+ }
+ if (window.performance) {
+ var now = (window.performance.now() / 1000).toFixed(3);
+ webrtcUtils.log(now + ': ' + text);
+ } else {
+ webrtcUtils.log(text);
+ }
+}
- // make sure this only gets enabled in Google Chrome
- // EXPERIMENTAL FLAG, might get removed without notice
- this.enableChromeNativeSimulcast = false;
- if (constraints && constraints.optional &&
- webrtc.prefix === 'webkit' &&
- navigator.appVersion.match(/Chromium\//) === null) {
- constraints.optional.forEach(function (constraint, idx) {
- if (constraint.enableChromeNativeSimulcast) {
- self.enableChromeNativeSimulcast = true;
+if (typeof window === 'object') {
+ if (window.HTMLMediaElement &&
+ !('srcObject' in window.HTMLMediaElement.prototype)) {
+ // Shim the srcObject property, once, when HTMLMediaElement is found.
+ Object.defineProperty(window.HTMLMediaElement.prototype, 'srcObject', {
+ get: function() {
+ // If prefixed srcObject property exists, return it.
+ // Otherwise use the shimmed property, _srcObject
+ return 'mozSrcObject' in this ? this.mozSrcObject : this._srcObject;
+ },
+ set: function(stream) {
+ if ('mozSrcObject' in this) {
+ this.mozSrcObject = stream;
+ } else {
+ // Use _srcObject as a private property for this shim
+ this._srcObject = stream;
+ // TODO: revokeObjectUrl(this.src) when !stream to release resources?
+ this.src = URL.createObjectURL(stream);
+ }
+ }
+ });
+ }
+ // Proxy existing globals
+ getUserMedia = window.navigator && window.navigator.getUserMedia;
+}
+
+// Attach a media stream to an element.
+attachMediaStream = function(element, stream) {
+ element.srcObject = stream;
+};
+
+reattachMediaStream = function(to, from) {
+ to.srcObject = from.srcObject;
+};
+
+if (typeof window === 'undefined' || !window.navigator) {
+ webrtcUtils.log('This does not appear to be a browser');
+ webrtcDetectedBrowser = 'not a browser';
+} else if (navigator.mozGetUserMedia && window.mozRTCPeerConnection) {
+ webrtcUtils.log('This appears to be Firefox');
+
+ webrtcDetectedBrowser = 'firefox';
+
+ // the detected firefox version.
+ webrtcDetectedVersion =
+ parseInt(navigator.userAgent.match(/Firefox\/([0-9]+)\./)[1], 10);
+
+ // the minimum firefox version still supported by adapter.
+ webrtcMinimumVersion = 31;
+
+ // The RTCPeerConnection object.
+ window.RTCPeerConnection = function(pcConfig, pcConstraints) {
+ if (webrtcDetectedVersion < 38) {
+ // .urls is not supported in FF < 38.
+ // create RTCIceServers with a single url.
+ if (pcConfig && pcConfig.iceServers) {
+ var newIceServers = [];
+ for (var i = 0; i < pcConfig.iceServers.length; i++) {
+ var server = pcConfig.iceServers[i];
+ if (server.hasOwnProperty('urls')) {
+ for (var j = 0; j < server.urls.length; j++) {
+ var newServer = {
+ url: server.urls[j]
+ };
+ if (server.urls[j].indexOf('turn') === 0) {
+ newServer.username = server.username;
+ newServer.credential = server.credential;
+ }
+ newIceServers.push(newServer);
}
- });
+ } else {
+ newIceServers.push(pcConfig.iceServers[i]);
+ }
+ }
+ pcConfig.iceServers = newIceServers;
+ }
}
+ return new mozRTCPeerConnection(pcConfig, pcConstraints); // jscs:ignore requireCapitalizedConstructors
+ };
- // EXPERIMENTAL FLAG, might get removed without notice
- this.enableMultiStreamHacks = false;
- if (constraints && constraints.optional &&
- webrtc.prefix === 'webkit') {
- constraints.optional.forEach(function (constraint, idx) {
- if (constraint.enableMultiStreamHacks) {
- self.enableMultiStreamHacks = true;
+ // The RTCSessionDescription object.
+ window.RTCSessionDescription = mozRTCSessionDescription;
+
+ // The RTCIceCandidate object.
+ window.RTCIceCandidate = mozRTCIceCandidate;
+
+ // getUserMedia constraints shim.
+ getUserMedia = function(constraints, onSuccess, onError) {
+ var constraintsToFF37 = function(c) {
+ if (typeof c !== 'object' || c.require) {
+ return c;
+ }
+ var require = [];
+ Object.keys(c).forEach(function(key) {
+ if (key === 'require' || key === 'advanced' || key === 'mediaSource') {
+ return;
+ }
+ var r = c[key] = (typeof c[key] === 'object') ?
+ c[key] : {ideal: c[key]};
+ if (r.min !== undefined ||
+ r.max !== undefined || r.exact !== undefined) {
+ require.push(key);
+ }
+ if (r.exact !== undefined) {
+ if (typeof r.exact === 'number') {
+ r.min = r.max = r.exact;
+ } else {
+ c[key] = r.exact;
+ }
+ delete r.exact;
+ }
+ if (r.ideal !== undefined) {
+ c.advanced = c.advanced || [];
+ var oc = {};
+ if (typeof r.ideal === 'number') {
+ oc[key] = {min: r.ideal, max: r.ideal};
+ } else {
+ oc[key] = r.ideal;
+ }
+ c.advanced.push(oc);
+ delete r.ideal;
+ if (!Object.keys(r).length) {
+ delete c[key];
+ }
+ }
+ });
+ if (require.length) {
+ c.require = require;
+ }
+ return c;
+ };
+ if (webrtcDetectedVersion < 38) {
+ webrtcUtils.log('spec: ' + JSON.stringify(constraints));
+ if (constraints.audio) {
+ constraints.audio = constraintsToFF37(constraints.audio);
+ }
+ if (constraints.video) {
+ constraints.video = constraintsToFF37(constraints.video);
+ }
+ webrtcUtils.log('ff37: ' + JSON.stringify(constraints));
+ }
+ return navigator.mozGetUserMedia(constraints, onSuccess, onError);
+ };
+
+ navigator.getUserMedia = getUserMedia;
+
+ // Shim for mediaDevices on older versions.
+ if (!navigator.mediaDevices) {
+ navigator.mediaDevices = {getUserMedia: requestUserMedia,
+ addEventListener: function() { },
+ removeEventListener: function() { }
+ };
+ }
+ navigator.mediaDevices.enumerateDevices =
+ navigator.mediaDevices.enumerateDevices || function() {
+ return new Promise(function(resolve) {
+ var infos = [
+ {kind: 'audioinput', deviceId: 'default', label: '', groupId: ''},
+ {kind: 'videoinput', deviceId: 'default', label: '', groupId: ''}
+ ];
+ resolve(infos);
+ });
+ };
+
+ if (webrtcDetectedVersion < 41) {
+ // Work around http://bugzil.la/1169665
+ var orgEnumerateDevices =
+ navigator.mediaDevices.enumerateDevices.bind(navigator.mediaDevices);
+ navigator.mediaDevices.enumerateDevices = function() {
+ return orgEnumerateDevices().catch(function(e) {
+ if (e.name === 'NotFoundError') {
+ return [];
+ }
+ throw e;
+ });
+ };
+ }
+} else if (navigator.webkitGetUserMedia && !!window.chrome) {
+ webrtcUtils.log('This appears to be Chrome');
+
+ webrtcDetectedBrowser = 'chrome';
+
+ // the detected chrome version.
+ webrtcDetectedVersion =
+ parseInt(navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./)[2], 10);
+
+ // the minimum chrome version still supported by adapter.
+ webrtcMinimumVersion = 38;
+
+ // The RTCPeerConnection object.
+ window.RTCPeerConnection = function(pcConfig, pcConstraints) {
+ // Translate iceTransportPolicy to iceTransports,
+ // see https://code.google.com/p/webrtc/issues/detail?id=4869
+ if (pcConfig && pcConfig.iceTransportPolicy) {
+ pcConfig.iceTransports = pcConfig.iceTransportPolicy;
+ }
+
+ var pc = new webkitRTCPeerConnection(pcConfig, pcConstraints); // jscs:ignore requireCapitalizedConstructors
+ var origGetStats = pc.getStats.bind(pc);
+ pc.getStats = function(selector, successCallback, errorCallback) { // jshint ignore: line
+ var self = this;
+ var args = arguments;
+
+ // If selector is a function then we are in the old style stats so just
+ // pass back the original getStats format to avoid breaking old users.
+ if (arguments.length > 0 && typeof selector === 'function') {
+ return origGetStats(selector, successCallback);
+ }
+
+ var fixChromeStats = function(response) {
+ var standardReport = {};
+ var reports = response.result();
+ reports.forEach(function(report) {
+ var standardStats = {
+ id: report.id,
+ timestamp: report.timestamp,
+ type: report.type
+ };
+ report.names().forEach(function(name) {
+ standardStats[name] = report.stat(name);
+ });
+ standardReport[standardStats.id] = standardStats;
+ });
+
+ return standardReport;
+ };
+
+ if (arguments.length >= 2) {
+ var successCallbackWrapper = function(response) {
+ args[1](fixChromeStats(response));
+ };
+
+ return origGetStats.apply(this, [successCallbackWrapper, arguments[0]]);
+ }
+
+ // promise-support
+ return new Promise(function(resolve, reject) {
+ if (args.length === 1 && selector === null) {
+ origGetStats.apply(self, [
+ function(response) {
+ resolve.apply(null, [fixChromeStats(response)]);
+ }, reject]);
+ } else {
+ origGetStats.apply(self, [resolve, reject]);
+ }
+ });
+ };
+
+ return pc;
+ };
+
+ // add promise support
+ ['createOffer', 'createAnswer'].forEach(function(method) {
+ var nativeMethod = webkitRTCPeerConnection.prototype[method];
+ webkitRTCPeerConnection.prototype[method] = function() {
+ var self = this;
+ if (arguments.length < 1 || (arguments.length === 1 &&
+ typeof(arguments[0]) === 'object')) {
+ var opts = arguments.length === 1 ? arguments[0] : undefined;
+ return new Promise(function(resolve, reject) {
+ nativeMethod.apply(self, [resolve, reject, opts]);
+ });
+ } else {
+ return nativeMethod.apply(this, arguments);
+ }
+ };
+ });
+
+ ['setLocalDescription', 'setRemoteDescription',
+ 'addIceCandidate'].forEach(function(method) {
+ var nativeMethod = webkitRTCPeerConnection.prototype[method];
+ webkitRTCPeerConnection.prototype[method] = function() {
+ var args = arguments;
+ var self = this;
+ return new Promise(function(resolve, reject) {
+ nativeMethod.apply(self, [args[0],
+ function() {
+ resolve();
+ if (args.length >= 2) {
+ args[1].apply(null, []);
+ }
+ },
+ function(err) {
+ reject(err);
+ if (args.length >= 3) {
+ args[2].apply(null, [err]);
+ }
+ }]
+ );
+ });
+ };
+ });
+
+ // getUserMedia constraints shim.
+ var constraintsToChrome = function(c) {
+ if (typeof c !== 'object' || c.mandatory || c.optional) {
+ return c;
+ }
+ var cc = {};
+ Object.keys(c).forEach(function(key) {
+ if (key === 'require' || key === 'advanced' || key === 'mediaSource') {
+ return;
+ }
+ var r = (typeof c[key] === 'object') ? c[key] : {ideal: c[key]};
+ if (r.exact !== undefined && typeof r.exact === 'number') {
+ r.min = r.max = r.exact;
+ }
+ var oldname = function(prefix, name) {
+ if (prefix) {
+ return prefix + name.charAt(0).toUpperCase() + name.slice(1);
+ }
+ return (name === 'deviceId') ? 'sourceId' : name;
+ };
+ if (r.ideal !== undefined) {
+ cc.optional = cc.optional || [];
+ var oc = {};
+ if (typeof r.ideal === 'number') {
+ oc[oldname('min', key)] = r.ideal;
+ cc.optional.push(oc);
+ oc = {};
+ oc[oldname('max', key)] = r.ideal;
+ cc.optional.push(oc);
+ } else {
+ oc[oldname('', key)] = r.ideal;
+ cc.optional.push(oc);
+ }
+ }
+ if (r.exact !== undefined && typeof r.exact !== 'number') {
+ cc.mandatory = cc.mandatory || {};
+ cc.mandatory[oldname('', key)] = r.exact;
+ } else {
+ ['min', 'max'].forEach(function(mix) {
+ if (r[mix] !== undefined) {
+ cc.mandatory = cc.mandatory || {};
+ cc.mandatory[oldname(mix, key)] = r[mix];
+ }
+ });
+ }
+ });
+ if (c.advanced) {
+ cc.optional = (cc.optional || []).concat(c.advanced);
+ }
+ return cc;
+ };
+
+ getUserMedia = function(constraints, onSuccess, onError) {
+ if (constraints.audio) {
+ constraints.audio = constraintsToChrome(constraints.audio);
+ }
+ if (constraints.video) {
+ constraints.video = constraintsToChrome(constraints.video);
+ }
+ webrtcUtils.log('chrome: ' + JSON.stringify(constraints));
+ return navigator.webkitGetUserMedia(constraints, onSuccess, onError);
+ };
+ navigator.getUserMedia = getUserMedia;
+
+ if (!navigator.mediaDevices) {
+ navigator.mediaDevices = {getUserMedia: requestUserMedia,
+ enumerateDevices: function() {
+ return new Promise(function(resolve) {
+ var kinds = {audio: 'audioinput', video: 'videoinput'};
+ return MediaStreamTrack.getSources(function(devices) {
+ resolve(devices.map(function(device) {
+ return {label: device.label,
+ kind: kinds[device.kind],
+ deviceId: device.id,
+ groupId: ''};
+ }));
+ });
+ });
+ }};
+ }
+
+ // A shim for getUserMedia method on the mediaDevices object.
+ // TODO(KaptenJansson) remove once implemented in Chrome stable.
+ if (!navigator.mediaDevices.getUserMedia) {
+ navigator.mediaDevices.getUserMedia = function(constraints) {
+ return requestUserMedia(constraints);
+ };
+ } else {
+ // Even though Chrome 45 has navigator.mediaDevices and a getUserMedia
+ // function which returns a Promise, it does not accept spec-style
+ // constraints.
+ var origGetUserMedia = navigator.mediaDevices.getUserMedia.
+ bind(navigator.mediaDevices);
+ navigator.mediaDevices.getUserMedia = function(c) {
+ webrtcUtils.log('spec: ' + JSON.stringify(c)); // whitespace for alignment
+ c.audio = constraintsToChrome(c.audio);
+ c.video = constraintsToChrome(c.video);
+ webrtcUtils.log('chrome: ' + JSON.stringify(c));
+ return origGetUserMedia(c);
+ };
+ }
+
+ // Dummy devicechange event methods.
+ // TODO(KaptenJansson) remove once implemented in Chrome stable.
+ if (typeof navigator.mediaDevices.addEventListener === 'undefined') {
+ navigator.mediaDevices.addEventListener = function() {
+ webrtcUtils.log('Dummy mediaDevices.addEventListener called.');
+ };
+ }
+ if (typeof navigator.mediaDevices.removeEventListener === 'undefined') {
+ navigator.mediaDevices.removeEventListener = function() {
+ webrtcUtils.log('Dummy mediaDevices.removeEventListener called.');
+ };
+ }
+
+ // Attach a media stream to an element.
+ attachMediaStream = function(element, stream) {
+ if (webrtcDetectedVersion >= 43) {
+ element.srcObject = stream;
+ } else if (typeof element.src !== 'undefined') {
+ element.src = URL.createObjectURL(stream);
+ } else {
+ webrtcUtils.log('Error attaching stream to element.');
+ }
+ };
+ reattachMediaStream = function(to, from) {
+ if (webrtcDetectedVersion >= 43) {
+ to.srcObject = from.srcObject;
+ } else {
+ to.src = from.src;
+ }
+ };
+
+} else if (navigator.mediaDevices && navigator.userAgent.match(
+ /Edge\/(\d+).(\d+)$/)) {
+ webrtcUtils.log('This appears to be Edge');
+ webrtcDetectedBrowser = 'edge';
+
+ webrtcDetectedVersion =
+ parseInt(navigator.userAgent.match(/Edge\/(\d+).(\d+)$/)[2], 10);
+
+ // the minimum version still supported by adapter.
+ webrtcMinimumVersion = 12;
+} else {
+ webrtcUtils.log('Browser does not appear to be WebRTC-capable');
+}
+
+// Returns the result of getUserMedia as a Promise.
+function requestUserMedia(constraints) {
+ return new Promise(function(resolve, reject) {
+ getUserMedia(constraints, resolve, reject);
+ });
+}
+
+var webrtcTesting = {};
+Object.defineProperty(webrtcTesting, 'version', {
+ set: function(version) {
+ webrtcDetectedVersion = version;
+ }
+});
+
+if (typeof module !== 'undefined') {
+ var RTCPeerConnection;
+ if (typeof window !== 'undefined') {
+ RTCPeerConnection = window.RTCPeerConnection;
+ }
+ module.exports = {
+ RTCPeerConnection: RTCPeerConnection,
+ getUserMedia: getUserMedia,
+ attachMediaStream: attachMediaStream,
+ reattachMediaStream: reattachMediaStream,
+ webrtcDetectedBrowser: webrtcDetectedBrowser,
+ webrtcDetectedVersion: webrtcDetectedVersion,
+ webrtcMinimumVersion: webrtcMinimumVersion,
+ webrtcTesting: webrtcTesting
+ //requestUserMedia: not exposed on purpose.
+ //trace: not exposed on purpose.
+ };
+} else if ((typeof require === 'function') && (typeof define === 'function')) {
+ // Expose objects and functions when RequireJS is doing the loading.
+ define([], function() {
+ return {
+ RTCPeerConnection: window.RTCPeerConnection,
+ getUserMedia: getUserMedia,
+ attachMediaStream: attachMediaStream,
+ reattachMediaStream: reattachMediaStream,
+ webrtcDetectedBrowser: webrtcDetectedBrowser,
+ webrtcDetectedVersion: webrtcDetectedVersion,
+ webrtcMinimumVersion: webrtcMinimumVersion,
+ webrtcTesting: webrtcTesting
+ //requestUserMedia: not exposed on purpose.
+ //trace: not exposed on purpose.
+ };
+ });
+}
+
+},{}],15:[function(require,module,exports){
+var WildEmitter = require('wildemitter');
+var util = require('util');
+
+function Sender(opts) {
+ WildEmitter.call(this);
+ var options = opts || {};
+ this.config = {
+ chunksize: 16384,
+ pacing: 0
+ };
+ // set our config from options
+ var item;
+ for (item in options) {
+ this.config[item] = options[item];
+ }
+
+ this.file = null;
+ this.channel = null;
+}
+util.inherits(Sender, WildEmitter);
+
+Sender.prototype.send = function (file, channel) {
+ var self = this;
+ this.file = file;
+ this.channel = channel;
+ var sliceFile = function(offset) {
+ var reader = new window.FileReader();
+ reader.onload = (function() {
+ return function(e) {
+ self.channel.send(e.target.result);
+ self.emit('progress', offset, file.size, e.target.result);
+ if (file.size > offset + e.target.result.byteLength) {
+ window.setTimeout(sliceFile, self.config.pacing, offset + self.config.chunksize);
+ } else {
+ self.emit('progress', file.size, file.size, null);
+ self.emit('sentFile');
+ }
+ };
+ })(file);
+ var slice = file.slice(offset, offset + self.config.chunksize);
+ reader.readAsArrayBuffer(slice);
+ };
+ window.setTimeout(sliceFile, 0, 0);
+};
+
+function Receiver() {
+ WildEmitter.call(this);
+
+ this.receiveBuffer = [];
+ this.received = 0;
+ this.metadata = {};
+ this.channel = null;
+}
+util.inherits(Receiver, WildEmitter);
+
+Receiver.prototype.receive = function (metadata, channel) {
+ var self = this;
+
+ if (metadata) {
+ this.metadata = metadata;
+ }
+ this.channel = channel;
+ // chrome only supports arraybuffers and those make it easier to calc the hash
+ channel.binaryType = 'arraybuffer';
+ this.channel.onmessage = function (event) {
+ var len = event.data.byteLength;
+ self.received += len;
+ self.receiveBuffer.push(event.data);
+
+ self.emit('progress', self.received, self.metadata.size, event.data);
+ if (self.received === self.metadata.size) {
+ self.emit('receivedFile', new window.Blob(self.receiveBuffer), self.metadata);
+ self.receiveBuffer = []; // discard receivebuffer
+ } else if (self.received > self.metadata.size) {
+ // FIXME
+ console.error('received more than expected, discarding...');
+ self.receiveBuffer = []; // just discard...
+
+ }
+ };
+};
+
+module.exports = {};
+module.exports.support = typeof window !== 'undefined' && window && window.File && window.FileReader && window.Blob;
+module.exports.Sender = Sender;
+module.exports.Receiver = Receiver;
+
+},{"util":8,"wildemitter":4}],14:[function(require,module,exports){
+var util = require('util');
+var each = require('lodash.foreach');
+var pluck = require('lodash.pluck');
+var SJJ = require('sdp-jingle-json');
+var WildEmitter = require('wildemitter');
+var peerconn = require('traceablepeerconnection');
+var adapter = require('webrtc-adapter-test');
+
+function PeerConnection(config, constraints) {
+ var self = this;
+ var item;
+ WildEmitter.call(this);
+
+ config = config || {};
+ config.iceServers = config.iceServers || [];
+
+ // make sure this only gets enabled in Google Chrome
+ // EXPERIMENTAL FLAG, might get removed without notice
+ this.enableChromeNativeSimulcast = false;
+ if (constraints && constraints.optional &&
+ adapter.webrtcDetectedBrowser === 'chrome' &&
+ navigator.appVersion.match(/Chromium\//) === null) {
+ constraints.optional.forEach(function (constraint) {
+ if (constraint.enableChromeNativeSimulcast) {
+ self.enableChromeNativeSimulcast = true;
+ }
+ });
+ }
+
+ // EXPERIMENTAL FLAG, might get removed without notice
+ this.enableMultiStreamHacks = false;
+ if (constraints && constraints.optional &&
+ adapter.webrtcDetectedBrowser === 'chrome') {
+ constraints.optional.forEach(function (constraint) {
+ if (constraint.enableMultiStreamHacks) {
+ self.enableMultiStreamHacks = true;
}
});
}
// EXPERIMENTAL FLAG, might get removed without notice
this.restrictBandwidth = 0;
if (constraints && constraints.optional) {
- constraints.optional.forEach(function (constraint, idx) {
+ constraints.optional.forEach(function (constraint) {
if (constraint.andyetRestrictBandwidth) {
self.restrictBandwidth = constraint.andyetRestrictBandwidth;
}
@@ -6075,7 +6640,7 @@ function PeerConnection(config, constraints) {
// ~20ms seems good
this.batchIceCandidates = 0;
if (constraints && constraints.optional) {
- constraints.optional.forEach(function (constraint, idx) {
+ constraints.optional.forEach(function (constraint) {
if (constraint.andyetBatchIce) {
self.batchIceCandidates = constraint.andyetBatchIce;
}
@@ -6087,8 +6652,8 @@ function PeerConnection(config, constraints) {
// this attemps to strip out candidates with an already known foundation
// and type -- i.e. those which are gathered via the same TURN server
// but different transports (TURN udp, tcp and tls respectively)
- if (constraints && constraints.optional && webrtc.prefix === 'webkit') {
- constraints.optional.forEach(function (constraint, idx) {
+ if (constraints && constraints.optional && adapter.webrtcDetectedBrowser === 'chrome') {
+ constraints.optional.forEach(function (constraint) {
if (constraint.andyetFasterICE) {
self.eliminateDuplicateCandidates = constraint.andyetFasterICE;
}
@@ -6098,7 +6663,7 @@ function PeerConnection(config, constraints) {
// when using a server such as the jitsi videobridge we don't need to signal
// our candidates
if (constraints && constraints.optional) {
- constraints.optional.forEach(function (constraint, idx) {
+ constraints.optional.forEach(function (constraint) {
if (constraint.andyetDontSignalCandidates) {
self.dontSignalCandidates = constraint.andyetDontSignalCandidates;
}
@@ -6109,7 +6674,7 @@ function PeerConnection(config, constraints) {
// EXPERIMENTAL FLAG, might get removed without notice
this.assumeSetLocalSuccess = false;
if (constraints && constraints.optional) {
- constraints.optional.forEach(function (constraint, idx) {
+ constraints.optional.forEach(function (constraint) {
if (constraint.andyetAssumeSetLocalSuccess) {
self.assumeSetLocalSuccess = constraint.andyetAssumeSetLocalSuccess;
}
@@ -6119,10 +6684,10 @@ function PeerConnection(config, constraints) {
// EXPERIMENTAL FLAG, might get removed without notice
// working around https://bugzilla.mozilla.org/show_bug.cgi?id=1087551
// pass in a timeout for this
- if (webrtc.prefix === 'moz') {
+ if (adapter.webrtcDetectedBrowser === 'firefox') {
if (constraints && constraints.optional) {
this.wtFirefox = 0;
- constraints.optional.forEach(function (constraint, idx) {
+ constraints.optional.forEach(function (constraint) {
if (constraint.andyetFirefoxMakesMeSad) {
self.wtFirefox = constraint.andyetFirefoxMakesMeSad;
if (self.wtFirefox > 0) {
@@ -6179,7 +6744,7 @@ function PeerConnection(config, constraints) {
}
if (this.config.debug) {
- this.on('*', function (eventName, event) {
+ this.on('*', function () {
var logger = config.logger || console;
logger.log('PeerConnection event:', arguments);
});
@@ -6279,7 +6844,7 @@ PeerConnection.prototype.processIce = function (update, cb) {
function (candidate) {
var iceCandidate = SJJ.toCandidateSDP(candidate) + '\r\n';
self.pc.addIceCandidate(
- new webrtc.IceCandidate({
+ new RTCIceCandidate({
candidate: iceCandidate,
sdpMLineIndex: mline,
sdpMid: mid
@@ -6308,7 +6873,7 @@ PeerConnection.prototype.processIce = function (update, cb) {
}
self.pc.addIceCandidate(
- new webrtc.IceCandidate(update.candidate),
+ new RTCIceCandidate(update.candidate),
function () { },
function (err) {
self.emit('error', err);
@@ -6462,7 +7027,7 @@ PeerConnection.prototype.handleOffer = function (offer, cb) {
self._checkRemoteCandidate(line);
}
});
- self.pc.setRemoteDescription(new webrtc.SessionDescription(offer),
+ self.pc.setRemoteDescription(new RTCSessionDescription(offer),
function () {
cb();
},
@@ -6494,7 +7059,6 @@ PeerConnection.prototype.answerBroadcastOnly = function (cb) {
// Answer an offer with given constraints default is audio/video
PeerConnection.prototype.answer = function (constraints, cb) {
- var self = this;
var hasConstraints = arguments.length === 2;
var callback = hasConstraints ? cb : constraints;
var mediaConstraints = hasConstraints && constraints ? constraints : {
@@ -6525,14 +7089,14 @@ PeerConnection.prototype.handleAnswer = function (answer, cb) {
}
});
self.pc.setRemoteDescription(
- new webrtc.SessionDescription(answer),
+ new RTCSessionDescription(answer),
function () {
if (self.wtFirefox) {
window.setTimeout(function () {
self.firefoxcandidatebuffer.forEach(function (candidate) {
// add candidates later
self.pc.addIceCandidate(
- new webrtc.IceCandidate(candidate),
+ new RTCIceCandidate(candidate),
function () { },
function (err) {
self.emit('error', err);
@@ -6573,7 +7137,6 @@ PeerConnection.prototype._answer = function (constraints, cb) {
self.pc.createAnswer(
function (answer) {
var sim = [];
- var rtx = [];
if (self.enableChromeNativeSimulcast) {
// native simulcast part 1: add another SSRC
answer.jingle = SJJ.toSessionJSON(answer.sdp, {
@@ -6581,7 +7144,6 @@ PeerConnection.prototype._answer = function (constraints, cb) {
direction: 'outgoing'
});
if (answer.jingle.contents.length >= 2 && answer.jingle.contents[1].name === 'video') {
- var hasSimgroup = false;
var groups = answer.jingle.contents[1].description.sourceGroups || [];
var hasSim = false;
groups.forEach(function (group) {
@@ -6649,7 +7211,6 @@ PeerConnection.prototype._answer = function (constraints, cb) {
direction: 'outgoing'
});
}
- var groups = expandedAnswer.jingle.contents[1].description.sourceGroups || [];
expandedAnswer.jingle.contents[1].description.sources.forEach(function (source, idx) {
// the floor idx/2 is a hack that relies on a particular order
// of groups, alternating between sim and rtx
@@ -6840,8 +7401,9 @@ PeerConnection.prototype.createDataChannel = function (name, opts) {
};
// a wrapper around getStats which hides the differences (where possible)
+// TODO: remove in favor of adapter.js shim
PeerConnection.prototype.getStats = function (cb) {
- if (webrtc.prefix === 'moz') {
+ if (adapter.webrtcDetectedBrowser === 'firefox') {
this.pc.getStats(
function (res) {
var items = [];
@@ -6874,95 +7436,88 @@ PeerConnection.prototype.getStats = function (cb) {
module.exports = PeerConnection;
-},{"lodash.foreach":22,"lodash.pluck":23,"sdp-jingle-json":20,"traceablepeerconnection":21,"util":8,"webrtcsupport":5,"wildemitter":4}],15:[function(require,module,exports){
-var WildEmitter = require('wildemitter');
-var util = require('util');
+},{"lodash.foreach":23,"lodash.pluck":24,"sdp-jingle-json":21,"traceablepeerconnection":22,"util":8,"webrtc-adapter-test":20,"wildemitter":4}],16:[function(require,module,exports){
+// getUserMedia helper by @HenrikJoreteg
+var adapter = require('webrtc-adapter-test');
-function Sender(opts) {
- WildEmitter.call(this);
- var options = opts || {};
- this.config = {
- chunksize: 16384,
- pacing: 0
- };
- // set our config from options
- var item;
- for (item in options) {
- this.config[item] = options[item];
- }
+module.exports = function (constraints, cb) {
+ var options, error;
+ var haveOpts = arguments.length === 2;
+ var defaultOpts = {video: true, audio: true};
- this.file = null;
- this.channel = null;
-}
-util.inherits(Sender, WildEmitter);
+ var denied = 'PermissionDeniedError';
+ var altDenied = 'PERMISSION_DENIED';
+ var notSatisfied = 'ConstraintNotSatisfiedError';
-Sender.prototype.send = function (file, channel) {
- var self = this;
- this.file = file;
- this.channel = channel;
- var sliceFile = function(offset) {
- var reader = new window.FileReader();
- reader.onload = (function() {
- return function(e) {
- self.channel.send(e.target.result);
- self.emit('progress', offset, file.size, e.target.result);
- if (file.size > offset + e.target.result.byteLength) {
- window.setTimeout(sliceFile, self.config.pacing, offset + self.config.chunksize);
- } else {
- self.emit('progress', file.size, file.size, null);
- self.emit('sentFile');
- }
- };
- })(file);
- var slice = file.slice(offset, offset + self.config.chunksize);
- reader.readAsArrayBuffer(slice);
- };
- window.setTimeout(sliceFile, 0, 0);
-};
+ // make constraints optional
+ if (!haveOpts) {
+ cb = constraints;
+ constraints = defaultOpts;
+ }
-function Receiver() {
- WildEmitter.call(this);
+ // treat lack of browser support like an error
+ if (!navigator.getUserMedia) {
+ // throw proper error per spec
+ error = new Error('MediaStreamError');
+ error.name = 'NotSupportedError';
- this.receiveBuffer = [];
- this.received = 0;
- this.metadata = {};
- this.channel = null;
-}
-util.inherits(Receiver, WildEmitter);
+ // keep all callbacks async
+ return window.setTimeout(function () {
+ cb(error);
+ }, 0);
+ }
-Receiver.prototype.receive = function (metadata, channel) {
- var self = this;
+ // normalize error handling when no media types are requested
+ if (!constraints.audio && !constraints.video) {
+ error = new Error('MediaStreamError');
+ error.name = 'NoMediaRequestedError';
- if (metadata) {
- this.metadata = metadata;
+ // keep all callbacks async
+ return window.setTimeout(function () {
+ cb(error);
+ }, 0);
}
- this.channel = channel;
- // chrome only supports arraybuffers and those make it easier to calc the hash
- channel.binaryType = 'arraybuffer';
- this.channel.onmessage = function (event) {
- var len = event.data.byteLength;
- self.received += len;
- self.receiveBuffer.push(event.data);
- self.emit('progress', self.received, self.metadata.size, event.data);
- if (self.received === self.metadata.size) {
- self.emit('receivedFile', new window.Blob(self.receiveBuffer), self.metadata);
- self.receiveBuffer = []; // discard receivebuffer
- } else if (self.received > self.metadata.size) {
- // FIXME
- console.error('received more than expected, discarding...');
- self.receiveBuffer = []; // just discard...
+ // testing support
+ if (localStorage && localStorage.useFirefoxFakeDevice === "true") {
+ constraints.fake = true;
+ }
+ navigator.getUserMedia(constraints, function (stream) {
+ cb(null, stream);
+ }, function (err) {
+ var error;
+ // coerce into an error object since FF gives us a string
+ // there are only two valid names according to the spec
+ // we coerce all non-denied to "constraint not satisfied".
+ if (typeof err === 'string') {
+ error = new Error('MediaStreamError');
+ if (err === denied || err === altDenied) {
+ error.name = denied;
+ } else {
+ error.name = notSatisfied;
+ }
+ } else {
+ // if we get an error object make sure '.name' property is set
+ // according to spec: http://dev.w3.org/2011/webrtc/editor/getusermedia.html#navigatorusermediaerror-and-navigatorusermediaerrorcallback
+ error = err;
+ if (!error.name) {
+ // this is likely chrome which
+ // sets a property called "ERROR_DENIED" on the error object
+ // if so we make sure to set a name
+ if (error[denied]) {
+ err.name = denied;
+ } else {
+ err.name = notSatisfied;
+ }
+ }
}
- };
-};
-module.exports = {};
-module.exports.support = window && window.File && window.FileReader && window.Blob;
-module.exports.Sender = Sender;
-module.exports.Receiver = Receiver;
+ cb(error);
+ });
+};
-},{"util":8,"wildemitter":4}],17:[function(require,module,exports){
+},{"webrtc-adapter-test":25}],18:[function(require,module,exports){
var WildEmitter = require('wildemitter');
function getMaxVolume (analyser, fftBins) {
@@ -7092,129 +7647,545 @@ module.exports = function(stream, options) {
return harker;
}
-},{"wildemitter":24}],20:[function(require,module,exports){
-var toSDP = require('./lib/tosdp');
-var toJSON = require('./lib/tojson');
-
+},{"wildemitter":26}],25:[function(require,module,exports){
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree.
+ */
+
+/* More information about these options at jshint.com/docs/options */
+/* jshint browser: true, camelcase: true, curly: true, devel: true,
+ eqeqeq: true, forin: false, globalstrict: true, node: true,
+ quotmark: single, undef: true, unused: strict */
+/* global mozRTCIceCandidate, mozRTCPeerConnection, Promise,
+mozRTCSessionDescription, webkitRTCPeerConnection, MediaStreamTrack */
+/* exported trace,requestUserMedia */
+
+'use strict';
+
+var getUserMedia = null;
+var attachMediaStream = null;
+var reattachMediaStream = null;
+var webrtcDetectedBrowser = null;
+var webrtcDetectedVersion = null;
+var webrtcMinimumVersion = null;
+var webrtcUtils = {
+ log: function() {
+ // suppress console.log output when being included as a module.
+ if (typeof module !== 'undefined' ||
+ typeof require === 'function' && typeof define === 'function') {
+ return;
+ }
+ console.log.apply(console, arguments);
+ }
+};
-// Converstion from JSON to SDP
+function trace(text) {
+ // This function is used for logging.
+ if (text[text.length - 1] === '\n') {
+ text = text.substring(0, text.length - 1);
+ }
+ if (window.performance) {
+ var now = (window.performance.now() / 1000).toFixed(3);
+ webrtcUtils.log(now + ': ' + text);
+ } else {
+ webrtcUtils.log(text);
+ }
+}
-exports.toIncomingSDPOffer = function (session) {
- return toSDP.toSessionSDP(session, {
- role: 'responder',
- direction: 'incoming'
- });
-};
-exports.toOutgoingSDPOffer = function (session) {
- return toSDP.toSessionSDP(session, {
- role: 'initiator',
- direction: 'outgoing'
- });
-};
-exports.toIncomingSDPAnswer = function (session) {
- return toSDP.toSessionSDP(session, {
- role: 'initiator',
- direction: 'incoming'
- });
-};
-exports.toOutgoingSDPAnswer = function (session) {
- return toSDP.toSessionSDP(session, {
- role: 'responder',
- direction: 'outgoing'
- });
-};
-exports.toIncomingMediaSDPOffer = function (media) {
- return toSDP.toMediaSDP(media, {
- role: 'responder',
- direction: 'incoming'
- });
-};
-exports.toOutgoingMediaSDPOffer = function (media) {
- return toSDP.toMediaSDP(media, {
- role: 'initiator',
- direction: 'outgoing'
- });
-};
-exports.toIncomingMediaSDPAnswer = function (media) {
- return toSDP.toMediaSDP(media, {
- role: 'initiator',
- direction: 'incoming'
- });
-};
-exports.toOutgoingMediaSDPAnswer = function (media) {
- return toSDP.toMediaSDP(media, {
- role: 'responder',
- direction: 'outgoing'
+if (typeof window === 'object') {
+ if (window.HTMLMediaElement &&
+ !('srcObject' in window.HTMLMediaElement.prototype)) {
+ // Shim the srcObject property, once, when HTMLMediaElement is found.
+ Object.defineProperty(window.HTMLMediaElement.prototype, 'srcObject', {
+ get: function() {
+ // If prefixed srcObject property exists, return it.
+ // Otherwise use the shimmed property, _srcObject
+ return 'mozSrcObject' in this ? this.mozSrcObject : this._srcObject;
+ },
+ set: function(stream) {
+ if ('mozSrcObject' in this) {
+ this.mozSrcObject = stream;
+ } else {
+ // Use _srcObject as a private property for this shim
+ this._srcObject = stream;
+ // TODO: revokeObjectUrl(this.src) when !stream to release resources?
+ this.src = URL.createObjectURL(stream);
+ }
+ }
});
-};
-exports.toCandidateSDP = toSDP.toCandidateSDP;
-exports.toMediaSDP = toSDP.toMediaSDP;
-exports.toSessionSDP = toSDP.toSessionSDP;
+ }
+ // Proxy existing globals
+ getUserMedia = window.navigator && window.navigator.getUserMedia;
+}
+
+// Attach a media stream to an element.
+attachMediaStream = function(element, stream) {
+ element.srcObject = stream;
+};
+
+reattachMediaStream = function(to, from) {
+ to.srcObject = from.srcObject;
+};
+
+if (typeof window === 'undefined' || !window.navigator) {
+ webrtcUtils.log('This does not appear to be a browser');
+ webrtcDetectedBrowser = 'not a browser';
+} else if (navigator.mozGetUserMedia && window.mozRTCPeerConnection) {
+ webrtcUtils.log('This appears to be Firefox');
+
+ webrtcDetectedBrowser = 'firefox';
+
+ // the detected firefox version.
+ webrtcDetectedVersion =
+ parseInt(navigator.userAgent.match(/Firefox\/([0-9]+)\./)[1], 10);
+
+ // the minimum firefox version still supported by adapter.
+ webrtcMinimumVersion = 31;
+
+ // The RTCPeerConnection object.
+ window.RTCPeerConnection = function(pcConfig, pcConstraints) {
+ if (webrtcDetectedVersion < 38) {
+ // .urls is not supported in FF < 38.
+ // create RTCIceServers with a single url.
+ if (pcConfig && pcConfig.iceServers) {
+ var newIceServers = [];
+ for (var i = 0; i < pcConfig.iceServers.length; i++) {
+ var server = pcConfig.iceServers[i];
+ if (server.hasOwnProperty('urls')) {
+ for (var j = 0; j < server.urls.length; j++) {
+ var newServer = {
+ url: server.urls[j]
+ };
+ if (server.urls[j].indexOf('turn') === 0) {
+ newServer.username = server.username;
+ newServer.credential = server.credential;
+ }
+ newIceServers.push(newServer);
+ }
+ } else {
+ newIceServers.push(pcConfig.iceServers[i]);
+ }
+ }
+ pcConfig.iceServers = newIceServers;
+ }
+ }
+ return new mozRTCPeerConnection(pcConfig, pcConstraints); // jscs:ignore requireCapitalizedConstructors
+ };
+ // The RTCSessionDescription object.
+ window.RTCSessionDescription = mozRTCSessionDescription;
-// Conversion from SDP to JSON
+ // The RTCIceCandidate object.
+ window.RTCIceCandidate = mozRTCIceCandidate;
-exports.toIncomingJSONOffer = function (sdp, creators) {
- return toJSON.toSessionJSON(sdp, {
- role: 'responder',
- direction: 'incoming',
- creators: creators
- });
-};
-exports.toOutgoingJSONOffer = function (sdp, creators) {
- return toJSON.toSessionJSON(sdp, {
- role: 'initiator',
- direction: 'outgoing',
- creators: creators
- });
-};
-exports.toIncomingJSONAnswer = function (sdp, creators) {
- return toJSON.toSessionJSON(sdp, {
- role: 'initiator',
- direction: 'incoming',
- creators: creators
- });
-};
-exports.toOutgoingJSONAnswer = function (sdp, creators) {
- return toJSON.toSessionJSON(sdp, {
- role: 'responder',
- direction: 'outgoing',
- creators: creators
+ // getUserMedia constraints shim.
+ getUserMedia = function(constraints, onSuccess, onError) {
+ var constraintsToFF37 = function(c) {
+ if (typeof c !== 'object' || c.require) {
+ return c;
+ }
+ var require = [];
+ Object.keys(c).forEach(function(key) {
+ if (key === 'require' || key === 'advanced' || key === 'mediaSource') {
+ return;
+ }
+ var r = c[key] = (typeof c[key] === 'object') ?
+ c[key] : {ideal: c[key]};
+ if (r.min !== undefined ||
+ r.max !== undefined || r.exact !== undefined) {
+ require.push(key);
+ }
+ if (r.exact !== undefined) {
+ if (typeof r.exact === 'number') {
+ r.min = r.max = r.exact;
+ } else {
+ c[key] = r.exact;
+ }
+ delete r.exact;
+ }
+ if (r.ideal !== undefined) {
+ c.advanced = c.advanced || [];
+ var oc = {};
+ if (typeof r.ideal === 'number') {
+ oc[key] = {min: r.ideal, max: r.ideal};
+ } else {
+ oc[key] = r.ideal;
+ }
+ c.advanced.push(oc);
+ delete r.ideal;
+ if (!Object.keys(r).length) {
+ delete c[key];
+ }
+ }
+ });
+ if (require.length) {
+ c.require = require;
+ }
+ return c;
+ };
+ if (webrtcDetectedVersion < 38) {
+ webrtcUtils.log('spec: ' + JSON.stringify(constraints));
+ if (constraints.audio) {
+ constraints.audio = constraintsToFF37(constraints.audio);
+ }
+ if (constraints.video) {
+ constraints.video = constraintsToFF37(constraints.video);
+ }
+ webrtcUtils.log('ff37: ' + JSON.stringify(constraints));
+ }
+ return navigator.mozGetUserMedia(constraints, onSuccess, onError);
+ };
+
+ navigator.getUserMedia = getUserMedia;
+
+ // Shim for mediaDevices on older versions.
+ if (!navigator.mediaDevices) {
+ navigator.mediaDevices = {getUserMedia: requestUserMedia,
+ addEventListener: function() { },
+ removeEventListener: function() { }
+ };
+ }
+ navigator.mediaDevices.enumerateDevices =
+ navigator.mediaDevices.enumerateDevices || function() {
+ return new Promise(function(resolve) {
+ var infos = [
+ {kind: 'audioinput', deviceId: 'default', label: '', groupId: ''},
+ {kind: 'videoinput', deviceId: 'default', label: '', groupId: ''}
+ ];
+ resolve(infos);
});
-};
-exports.toIncomingMediaJSONOffer = function (sdp, creator) {
- return toJSON.toMediaJSON(sdp, {
- role: 'responder',
- direction: 'incoming',
- creator: creator
- });
-};
-exports.toOutgoingMediaJSONOffer = function (sdp, creator) {
- return toJSON.toMediaJSON(sdp, {
- role: 'initiator',
- direction: 'outgoing',
- creator: creator
- });
-};
-exports.toIncomingMediaJSONAnswer = function (sdp, creator) {
- return toJSON.toMediaJSON(sdp, {
- role: 'initiator',
- direction: 'incoming',
- creator: creator
- });
-};
-exports.toOutgoingMediaJSONAnswer = function (sdp, creator) {
- return toJSON.toMediaJSON(sdp, {
- role: 'responder',
- direction: 'outgoing',
- creator: creator
+ };
+
+ if (webrtcDetectedVersion < 41) {
+ // Work around http://bugzil.la/1169665
+ var orgEnumerateDevices =
+ navigator.mediaDevices.enumerateDevices.bind(navigator.mediaDevices);
+ navigator.mediaDevices.enumerateDevices = function() {
+ return orgEnumerateDevices().catch(function(e) {
+ if (e.name === 'NotFoundError') {
+ return [];
+ }
+ throw e;
+ });
+ };
+ }
+} else if (navigator.webkitGetUserMedia && !!window.chrome) {
+ webrtcUtils.log('This appears to be Chrome');
+
+ webrtcDetectedBrowser = 'chrome';
+
+ // the detected chrome version.
+ webrtcDetectedVersion =
+ parseInt(navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./)[2], 10);
+
+ // the minimum chrome version still supported by adapter.
+ webrtcMinimumVersion = 38;
+
+ // The RTCPeerConnection object.
+ window.RTCPeerConnection = function(pcConfig, pcConstraints) {
+ // Translate iceTransportPolicy to iceTransports,
+ // see https://code.google.com/p/webrtc/issues/detail?id=4869
+ if (pcConfig && pcConfig.iceTransportPolicy) {
+ pcConfig.iceTransports = pcConfig.iceTransportPolicy;
+ }
+
+ var pc = new webkitRTCPeerConnection(pcConfig, pcConstraints); // jscs:ignore requireCapitalizedConstructors
+ var origGetStats = pc.getStats.bind(pc);
+ pc.getStats = function(selector, successCallback, errorCallback) { // jshint ignore: line
+ var self = this;
+ var args = arguments;
+
+ // If selector is a function then we are in the old style stats so just
+ // pass back the original getStats format to avoid breaking old users.
+ if (arguments.length > 0 && typeof selector === 'function') {
+ return origGetStats(selector, successCallback);
+ }
+
+ var fixChromeStats = function(response) {
+ var standardReport = {};
+ var reports = response.result();
+ reports.forEach(function(report) {
+ var standardStats = {
+ id: report.id,
+ timestamp: report.timestamp,
+ type: report.type
+ };
+ report.names().forEach(function(name) {
+ standardStats[name] = report.stat(name);
+ });
+ standardReport[standardStats.id] = standardStats;
+ });
+
+ return standardReport;
+ };
+
+ if (arguments.length >= 2) {
+ var successCallbackWrapper = function(response) {
+ args[1](fixChromeStats(response));
+ };
+
+ return origGetStats.apply(this, [successCallbackWrapper, arguments[0]]);
+ }
+
+ // promise-support
+ return new Promise(function(resolve, reject) {
+ if (args.length === 1 && selector === null) {
+ origGetStats.apply(self, [
+ function(response) {
+ resolve.apply(null, [fixChromeStats(response)]);
+ }, reject]);
+ } else {
+ origGetStats.apply(self, [resolve, reject]);
+ }
+ });
+ };
+
+ return pc;
+ };
+
+ // add promise support
+ ['createOffer', 'createAnswer'].forEach(function(method) {
+ var nativeMethod = webkitRTCPeerConnection.prototype[method];
+ webkitRTCPeerConnection.prototype[method] = function() {
+ var self = this;
+ if (arguments.length < 1 || (arguments.length === 1 &&
+ typeof(arguments[0]) === 'object')) {
+ var opts = arguments.length === 1 ? arguments[0] : undefined;
+ return new Promise(function(resolve, reject) {
+ nativeMethod.apply(self, [resolve, reject, opts]);
+ });
+ } else {
+ return nativeMethod.apply(this, arguments);
+ }
+ };
+ });
+
+ ['setLocalDescription', 'setRemoteDescription',
+ 'addIceCandidate'].forEach(function(method) {
+ var nativeMethod = webkitRTCPeerConnection.prototype[method];
+ webkitRTCPeerConnection.prototype[method] = function() {
+ var args = arguments;
+ var self = this;
+ return new Promise(function(resolve, reject) {
+ nativeMethod.apply(self, [args[0],
+ function() {
+ resolve();
+ if (args.length >= 2) {
+ args[1].apply(null, []);
+ }
+ },
+ function(err) {
+ reject(err);
+ if (args.length >= 3) {
+ args[2].apply(null, [err]);
+ }
+ }]
+ );
+ });
+ };
+ });
+
+ // getUserMedia constraints shim.
+ var constraintsToChrome = function(c) {
+ if (typeof c !== 'object' || c.mandatory || c.optional) {
+ return c;
+ }
+ var cc = {};
+ Object.keys(c).forEach(function(key) {
+ if (key === 'require' || key === 'advanced' || key === 'mediaSource') {
+ return;
+ }
+ var r = (typeof c[key] === 'object') ? c[key] : {ideal: c[key]};
+ if (r.exact !== undefined && typeof r.exact === 'number') {
+ r.min = r.max = r.exact;
+ }
+ var oldname = function(prefix, name) {
+ if (prefix) {
+ return prefix + name.charAt(0).toUpperCase() + name.slice(1);
+ }
+ return (name === 'deviceId') ? 'sourceId' : name;
+ };
+ if (r.ideal !== undefined) {
+ cc.optional = cc.optional || [];
+ var oc = {};
+ if (typeof r.ideal === 'number') {
+ oc[oldname('min', key)] = r.ideal;
+ cc.optional.push(oc);
+ oc = {};
+ oc[oldname('max', key)] = r.ideal;
+ cc.optional.push(oc);
+ } else {
+ oc[oldname('', key)] = r.ideal;
+ cc.optional.push(oc);
+ }
+ }
+ if (r.exact !== undefined && typeof r.exact !== 'number') {
+ cc.mandatory = cc.mandatory || {};
+ cc.mandatory[oldname('', key)] = r.exact;
+ } else {
+ ['min', 'max'].forEach(function(mix) {
+ if (r[mix] !== undefined) {
+ cc.mandatory = cc.mandatory || {};
+ cc.mandatory[oldname(mix, key)] = r[mix];
+ }
+ });
+ }
});
-};
-exports.toCandidateJSON = toJSON.toCandidateJSON;
-exports.toMediaJSON = toJSON.toMediaJSON;
-exports.toSessionJSON = toJSON.toSessionJSON;
+ if (c.advanced) {
+ cc.optional = (cc.optional || []).concat(c.advanced);
+ }
+ return cc;
+ };
+
+ getUserMedia = function(constraints, onSuccess, onError) {
+ if (constraints.audio) {
+ constraints.audio = constraintsToChrome(constraints.audio);
+ }
+ if (constraints.video) {
+ constraints.video = constraintsToChrome(constraints.video);
+ }
+ webrtcUtils.log('chrome: ' + JSON.stringify(constraints));
+ return navigator.webkitGetUserMedia(constraints, onSuccess, onError);
+ };
+ navigator.getUserMedia = getUserMedia;
+
+ if (!navigator.mediaDevices) {
+ navigator.mediaDevices = {getUserMedia: requestUserMedia,
+ enumerateDevices: function() {
+ return new Promise(function(resolve) {
+ var kinds = {audio: 'audioinput', video: 'videoinput'};
+ return MediaStreamTrack.getSources(function(devices) {
+ resolve(devices.map(function(device) {
+ return {label: device.label,
+ kind: kinds[device.kind],
+ deviceId: device.id,
+ groupId: ''};
+ }));
+ });
+ });
+ }};
+ }
+
+ // A shim for getUserMedia method on the mediaDevices object.
+ // TODO(KaptenJansson) remove once implemented in Chrome stable.
+ if (!navigator.mediaDevices.getUserMedia) {
+ navigator.mediaDevices.getUserMedia = function(constraints) {
+ return requestUserMedia(constraints);
+ };
+ } else {
+ // Even though Chrome 45 has navigator.mediaDevices and a getUserMedia
+ // function which returns a Promise, it does not accept spec-style
+ // constraints.
+ var origGetUserMedia = navigator.mediaDevices.getUserMedia.
+ bind(navigator.mediaDevices);
+ navigator.mediaDevices.getUserMedia = function(c) {
+ webrtcUtils.log('spec: ' + JSON.stringify(c)); // whitespace for alignment
+ c.audio = constraintsToChrome(c.audio);
+ c.video = constraintsToChrome(c.video);
+ webrtcUtils.log('chrome: ' + JSON.stringify(c));
+ return origGetUserMedia(c);
+ };
+ }
+
+ // Dummy devicechange event methods.
+ // TODO(KaptenJansson) remove once implemented in Chrome stable.
+ if (typeof navigator.mediaDevices.addEventListener === 'undefined') {
+ navigator.mediaDevices.addEventListener = function() {
+ webrtcUtils.log('Dummy mediaDevices.addEventListener called.');
+ };
+ }
+ if (typeof navigator.mediaDevices.removeEventListener === 'undefined') {
+ navigator.mediaDevices.removeEventListener = function() {
+ webrtcUtils.log('Dummy mediaDevices.removeEventListener called.');
+ };
+ }
+
+ // Attach a media stream to an element.
+ attachMediaStream = function(element, stream) {
+ if (webrtcDetectedVersion >= 43) {
+ element.srcObject = stream;
+ } else if (typeof element.src !== 'undefined') {
+ element.src = URL.createObjectURL(stream);
+ } else {
+ webrtcUtils.log('Error attaching stream to element.');
+ }
+ };
+ reattachMediaStream = function(to, from) {
+ if (webrtcDetectedVersion >= 43) {
+ to.srcObject = from.srcObject;
+ } else {
+ to.src = from.src;
+ }
+ };
+
+} else if (navigator.mediaDevices && navigator.userAgent.match(
+ /Edge\/(\d+).(\d+)$/)) {
+ webrtcUtils.log('This appears to be Edge');
+ webrtcDetectedBrowser = 'edge';
+
+ webrtcDetectedVersion =
+ parseInt(navigator.userAgent.match(/Edge\/(\d+).(\d+)$/)[2], 10);
+
+ // the minimum version still supported by adapter.
+ webrtcMinimumVersion = 12;
+} else {
+ webrtcUtils.log('Browser does not appear to be WebRTC-capable');
+}
+
+// Returns the result of getUserMedia as a Promise.
+function requestUserMedia(constraints) {
+ return new Promise(function(resolve, reject) {
+ getUserMedia(constraints, resolve, reject);
+ });
+}
+
+var webrtcTesting = {};
+Object.defineProperty(webrtcTesting, 'version', {
+ set: function(version) {
+ webrtcDetectedVersion = version;
+ }
+});
+
+if (typeof module !== 'undefined') {
+ var RTCPeerConnection;
+ if (typeof window !== 'undefined') {
+ RTCPeerConnection = window.RTCPeerConnection;
+ }
+ module.exports = {
+ RTCPeerConnection: RTCPeerConnection,
+ getUserMedia: getUserMedia,
+ attachMediaStream: attachMediaStream,
+ reattachMediaStream: reattachMediaStream,
+ webrtcDetectedBrowser: webrtcDetectedBrowser,
+ webrtcDetectedVersion: webrtcDetectedVersion,
+ webrtcMinimumVersion: webrtcMinimumVersion,
+ webrtcTesting: webrtcTesting
+ //requestUserMedia: not exposed on purpose.
+ //trace: not exposed on purpose.
+ };
+} else if ((typeof require === 'function') && (typeof define === 'function')) {
+ // Expose objects and functions when RequireJS is doing the loading.
+ define([], function() {
+ return {
+ RTCPeerConnection: window.RTCPeerConnection,
+ getUserMedia: getUserMedia,
+ attachMediaStream: attachMediaStream,
+ reattachMediaStream: reattachMediaStream,
+ webrtcDetectedBrowser: webrtcDetectedBrowser,
+ webrtcDetectedVersion: webrtcDetectedVersion,
+ webrtcMinimumVersion: webrtcMinimumVersion,
+ webrtcTesting: webrtcTesting
+ //requestUserMedia: not exposed on purpose.
+ //trace: not exposed on purpose.
+ };
+ });
+}
-},{"./lib/tojson":26,"./lib/tosdp":25}],24:[function(require,module,exports){
+},{}],26:[function(require,module,exports){
/*
WildEmitter.js is a slim little event emitter by @henrikjoreteg largely based
on @visionmedia's Emitter from UI Kit.
@@ -7358,7 +8329,129 @@ WildEmitter.prototype.getWildcardCallbacks = function (eventName) {
return result;
};
-},{}],18:[function(require,module,exports){
+},{}],21:[function(require,module,exports){
+var toSDP = require('./lib/tosdp');
+var toJSON = require('./lib/tojson');
+
+
+// Converstion from JSON to SDP
+
+exports.toIncomingSDPOffer = function (session) {
+ return toSDP.toSessionSDP(session, {
+ role: 'responder',
+ direction: 'incoming'
+ });
+};
+exports.toOutgoingSDPOffer = function (session) {
+ return toSDP.toSessionSDP(session, {
+ role: 'initiator',
+ direction: 'outgoing'
+ });
+};
+exports.toIncomingSDPAnswer = function (session) {
+ return toSDP.toSessionSDP(session, {
+ role: 'initiator',
+ direction: 'incoming'
+ });
+};
+exports.toOutgoingSDPAnswer = function (session) {
+ return toSDP.toSessionSDP(session, {
+ role: 'responder',
+ direction: 'outgoing'
+ });
+};
+exports.toIncomingMediaSDPOffer = function (media) {
+ return toSDP.toMediaSDP(media, {
+ role: 'responder',
+ direction: 'incoming'
+ });
+};
+exports.toOutgoingMediaSDPOffer = function (media) {
+ return toSDP.toMediaSDP(media, {
+ role: 'initiator',
+ direction: 'outgoing'
+ });
+};
+exports.toIncomingMediaSDPAnswer = function (media) {
+ return toSDP.toMediaSDP(media, {
+ role: 'initiator',
+ direction: 'incoming'
+ });
+};
+exports.toOutgoingMediaSDPAnswer = function (media) {
+ return toSDP.toMediaSDP(media, {
+ role: 'responder',
+ direction: 'outgoing'
+ });
+};
+exports.toCandidateSDP = toSDP.toCandidateSDP;
+exports.toMediaSDP = toSDP.toMediaSDP;
+exports.toSessionSDP = toSDP.toSessionSDP;
+
+
+// Conversion from SDP to JSON
+
+exports.toIncomingJSONOffer = function (sdp, creators) {
+ return toJSON.toSessionJSON(sdp, {
+ role: 'responder',
+ direction: 'incoming',
+ creators: creators
+ });
+};
+exports.toOutgoingJSONOffer = function (sdp, creators) {
+ return toJSON.toSessionJSON(sdp, {
+ role: 'initiator',
+ direction: 'outgoing',
+ creators: creators
+ });
+};
+exports.toIncomingJSONAnswer = function (sdp, creators) {
+ return toJSON.toSessionJSON(sdp, {
+ role: 'initiator',
+ direction: 'incoming',
+ creators: creators
+ });
+};
+exports.toOutgoingJSONAnswer = function (sdp, creators) {
+ return toJSON.toSessionJSON(sdp, {
+ role: 'responder',
+ direction: 'outgoing',
+ creators: creators
+ });
+};
+exports.toIncomingMediaJSONOffer = function (sdp, creator) {
+ return toJSON.toMediaJSON(sdp, {
+ role: 'responder',
+ direction: 'incoming',
+ creator: creator
+ });
+};
+exports.toOutgoingMediaJSONOffer = function (sdp, creator) {
+ return toJSON.toMediaJSON(sdp, {
+ role: 'initiator',
+ direction: 'outgoing',
+ creator: creator
+ });
+};
+exports.toIncomingMediaJSONAnswer = function (sdp, creator) {
+ return toJSON.toMediaJSON(sdp, {
+ role: 'initiator',
+ direction: 'incoming',
+ creator: creator
+ });
+};
+exports.toOutgoingMediaJSONAnswer = function (sdp, creator) {
+ return toJSON.toMediaJSON(sdp, {
+ role: 'responder',
+ direction: 'outgoing',
+ creator: creator
+ });
+};
+exports.toCandidateJSON = toJSON.toCandidateJSON;
+exports.toMediaJSON = toJSON.toMediaJSON;
+exports.toSessionJSON = toJSON.toSessionJSON;
+
+},{"./lib/tojson":28,"./lib/tosdp":27}],17:[function(require,module,exports){
// getScreenMedia helper by @HenrikJoreteg
var getUserMedia = require('getusermedia');
@@ -7383,7 +8476,7 @@ module.exports = function (constraints, cb) {
// "known" crash in chrome 34 and 35 on linux
if (window.navigator.userAgent.match('Linux')) maxver = 35;
- // check that the extension is installed by looking for a
+ // check that the extension is installed by looking for a
// sessionStorage variable that contains the extension id
// this has to be set after installation unless the contest
// script does that
@@ -7396,7 +8489,7 @@ module.exports = function (constraints, cb) {
error.name = 'PERMISSION_DENIED';
callback(error);
} else {
- var constraints = constraints || {audio: false, video: {
+ constraints = (hasConstraints && constraints) || {audio: false, video: {
mandatory: {
chromeMediaSource: 'desktop',
maxWidth: window.screen.width,
@@ -7413,6 +8506,30 @@ module.exports = function (constraints, cb) {
}
}
);
+ } else if (window.cefGetScreenMedia) {
+ //window.cefGetScreenMedia is experimental - may be removed without notice
+ window.cefGetScreenMedia(function(sourceId) {
+ if (!sourceId) {
+ var error = new Error('cefGetScreenMediaError');
+ error.name = 'CEF_GETSCREENMEDIA_CANCELED';
+ callback(error);
+ } else {
+ constraints = (hasConstraints && constraints) || {audio: false, video: {
+ mandatory: {
+ chromeMediaSource: 'desktop',
+ maxWidth: window.screen.width,
+ maxHeight: window.screen.height,
+ maxFrameRate: 3
+ },
+ optional: [
+ {googLeakyBucket: true},
+ {googTemporalLayeredScreencast: true}
+ ]
+ }};
+ constraints.video.mandatory.chromeMediaSourceId = sourceId;
+ getUserMedia(constraints, callback);
+ }
+ });
} else if (isCef || (chromever >= 26 && chromever <= maxver)) {
// chrome 26 - chrome 33 way to do it -- requires bad chrome://flags
// note: this is basically in maintenance mode and will go away soon
@@ -7506,7 +8623,54 @@ window.addEventListener('message', function (event) {
}
});
-},{"getusermedia":16}],22:[function(require,module,exports){
+},{"getusermedia":16}],19:[function(require,module,exports){
+var support = require('webrtcsupport');
+
+
+function GainController(stream) {
+ this.support = support.webAudio && support.mediaStream;
+
+ // set our starting value
+ this.gain = 1;
+
+ if (this.support) {
+ var context = this.context = new support.AudioContext();
+ this.microphone = context.createMediaStreamSource(stream);
+ this.gainFilter = context.createGain();
+ this.destination = context.createMediaStreamDestination();
+ this.outputStream = this.destination.stream;
+ this.microphone.connect(this.gainFilter);
+ this.gainFilter.connect(this.destination);
+ stream.addTrack(this.outputStream.getAudioTracks()[0]);
+ stream.removeTrack(stream.getAudioTracks()[0]);
+ }
+ this.stream = stream;
+}
+
+// setting
+GainController.prototype.setGain = function (val) {
+ // check for support
+ if (!this.support) return;
+ this.gainFilter.gain.value = val;
+ this.gain = val;
+};
+
+GainController.prototype.getGain = function () {
+ return this.gain;
+};
+
+GainController.prototype.off = function () {
+ return this.setGain(0);
+};
+
+GainController.prototype.on = function () {
+ this.setGain(1);
+};
+
+
+module.exports = GainController;
+
+},{"webrtcsupport":5}],23:[function(require,module,exports){
/**
* lodash 3.0.3 (Custom Build)
* Build: `lodash modern modularize exports="npm" -o ./`
@@ -7570,54 +8734,7 @@ var forEach = createForEach(arrayEach, baseEach);
module.exports = forEach;
-},{"lodash._arrayeach":30,"lodash._baseeach":28,"lodash._bindcallback":29,"lodash.isarray":27}],19:[function(require,module,exports){
-var support = require('webrtcsupport');
-
-
-function GainController(stream) {
- this.support = support.webAudio && support.mediaStream;
-
- // set our starting value
- this.gain = 1;
-
- if (this.support) {
- var context = this.context = new support.AudioContext();
- this.microphone = context.createMediaStreamSource(stream);
- this.gainFilter = context.createGain();
- this.destination = context.createMediaStreamDestination();
- this.outputStream = this.destination.stream;
- this.microphone.connect(this.gainFilter);
- this.gainFilter.connect(this.destination);
- stream.addTrack(this.outputStream.getAudioTracks()[0]);
- stream.removeTrack(stream.getAudioTracks()[0]);
- }
- this.stream = stream;
-}
-
-// setting
-GainController.prototype.setGain = function (val) {
- // check for support
- if (!this.support) return;
- this.gainFilter.gain.value = val;
- this.gain = val;
-};
-
-GainController.prototype.getGain = function () {
- return this.gain;
-};
-
-GainController.prototype.off = function () {
- return this.setGain(0);
-};
-
-GainController.prototype.on = function () {
- this.setGain(1);
-};
-
-
-module.exports = GainController;
-
-},{"webrtcsupport":5}],23:[function(require,module,exports){
+},{"lodash._arrayeach":29,"lodash._baseeach":30,"lodash._bindcallback":31,"lodash.isarray":32}],24:[function(require,module,exports){
/**
* lodash 3.1.2 (Custom Build)
* Build: `lodash modern modularize exports="npm" -o ./`
@@ -7776,540 +8893,89 @@ function property(path) {
module.exports = pluck;
-},{"lodash._baseget":33,"lodash._topath":34,"lodash.isarray":31,"lodash.map":32}],31:[function(require,module,exports){
-/**
- * lodash 3.0.3 (Custom Build)
- * Build: `lodash modern modularize exports="npm" -o ./`
- * Copyright 2012-2015 The Dojo Foundation
- * Based on Underscore.js 1.8.3
- * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
- * Available under MIT license
- */
+},{"lodash._baseget":33,"lodash._topath":34,"lodash.isarray":35,"lodash.map":36}],27:[function(require,module,exports){
+var SENDERS = require('./senders');
-/** `Object#toString` result references. */
-var arrayTag = '[object Array]',
- funcTag = '[object Function]';
-/**
- * Used to match `RegExp` [special characters](http://www.regular-expressions.info/characters.html#special).
- * In addition to special characters the forward slash is escaped to allow for
- * easier `eval` use and `Function` compilation.
- */
-var reRegExpChars = /[.*+?^${}()|[\]\/\\]/g,
- reHasRegExpChars = RegExp(reRegExpChars.source);
+exports.toSessionSDP = function (session, opts) {
+ var role = opts.role || 'initiator';
+ var direction = opts.direction || 'outgoing';
+ var sid = opts.sid || session.sid || Date.now();
+ var time = opts.time || Date.now();
-/** Used to detect host constructors (Safari > 5). */
-var reIsHostCtor = /^\[object .+?Constructor\]$/;
+ var sdp = [
+ 'v=0',
+ 'o=- ' + sid + ' ' + time + ' IN IP4 0.0.0.0',
+ 's=-',
+ 't=0 0',
+ 'a=msid-semantic: WMS *'
+ ];
-/**
- * Converts `value` to a string if it's not one. An empty string is returned
- * for `null` or `undefined` values.
- *
- * @private
- * @param {*} value The value to process.
- * @returns {string} Returns the string.
- */
-function baseToString(value) {
- if (typeof value == 'string') {
- return value;
- }
- return value == null ? '' : (value + '');
-}
+ var groups = session.groups || [];
+ groups.forEach(function (group) {
+ sdp.push('a=group:' + group.semantics + ' ' + group.contents.join(' '));
+ });
-/**
- * Checks if `value` is object-like.
- *
- * @private
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
- */
-function isObjectLike(value) {
- return !!value && typeof value == 'object';
-}
+ var contents = session.contents || [];
+ contents.forEach(function (content) {
+ sdp.push(exports.toMediaSDP(content, opts));
+ });
-/** Used for native method references. */
-var objectProto = Object.prototype;
+ return sdp.join('\r\n') + '\r\n';
+};
-/** Used to resolve the decompiled source of functions. */
-var fnToString = Function.prototype.toString;
+exports.toMediaSDP = function (content, opts) {
+ var sdp = [];
-/** Used to check objects for own properties. */
-var hasOwnProperty = objectProto.hasOwnProperty;
+ var role = opts.role || 'initiator';
+ var direction = opts.direction || 'outgoing';
-/**
- * Used to resolve the [`toStringTag`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring)
- * of values.
- */
-var objToString = objectProto.toString;
+ var desc = content.description;
+ var transport = content.transport;
+ var payloads = desc.payloads || [];
+ var fingerprints = (transport && transport.fingerprints) || [];
-/** Used to detect if a method is native. */
-var reIsNative = RegExp('^' +
- escapeRegExp(fnToString.call(hasOwnProperty))
- .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
-);
+ var mline = [];
+ if (desc.descType == 'datachannel') {
+ mline.push('application');
+ mline.push('1');
+ mline.push('DTLS/SCTP');
+ if (transport.sctp) {
+ transport.sctp.forEach(function (map) {
+ mline.push(map.number);
+ });
+ }
+ } else {
+ mline.push(desc.media);
+ mline.push('1');
+ if ((desc.encryption && desc.encryption.length > 0) || (fingerprints.length > 0)) {
+ mline.push('RTP/SAVPF');
+ } else {
+ mline.push('RTP/AVPF');
+ }
+ payloads.forEach(function (payload) {
+ mline.push(payload.id);
+ });
+ }
-/* Native method references for those with the same name as other `lodash` methods. */
-var nativeIsArray = getNative(Array, 'isArray');
-/**
- * Used as the [maximum length](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.max_safe_integer)
- * of an array-like value.
- */
-var MAX_SAFE_INTEGER = 9007199254740991;
+ sdp.push('m=' + mline.join(' '));
-/**
- * Gets the native function at `key` of `object`.
- *
- * @private
- * @param {Object} object The object to query.
- * @param {string} key The key of the method to get.
- * @returns {*} Returns the function if it's native, else `undefined`.
- */
-function getNative(object, key) {
- var value = object == null ? undefined : object[key];
- return isNative(value) ? value : undefined;
-}
+ sdp.push('c=IN IP4 0.0.0.0');
+ if (desc.bandwidth && desc.bandwidth.type && desc.bandwidth.bandwidth) {
+ sdp.push('b=' + desc.bandwidth.type + ':' + desc.bandwidth.bandwidth);
+ }
+ if (desc.descType == 'rtp') {
+ sdp.push('a=rtcp:1 IN IP4 0.0.0.0');
+ }
-/**
- * Checks if `value` is a valid array-like length.
- *
- * **Note:** This function is based on [`ToLength`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength).
- *
- * @private
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
- */
-function isLength(value) {
- return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
-}
-
-/**
- * Checks if `value` is classified as an `Array` object.
- *
- * @static
- * @memberOf _
- * @category Lang
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
- * @example
- *
- * _.isArray([1, 2, 3]);
- * // => true
- *
- * _.isArray(function() { return arguments; }());
- * // => false
- */
-var isArray = nativeIsArray || function(value) {
- return isObjectLike(value) && isLength(value.length) && objToString.call(value) == arrayTag;
-};
-
-/**
- * Checks if `value` is a native function.
- *
- * @static
- * @memberOf _
- * @category Lang
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is a native function, else `false`.
- * @example
- *
- * _.isNative(Array.prototype.push);
- * // => true
- *
- * _.isNative(_);
- * // => false
- */
-function isNative(value) {
- if (value == null) {
- return false;
- }
- if (objToString.call(value) == funcTag) {
- return reIsNative.test(fnToString.call(value));
- }
- return isObjectLike(value) && reIsHostCtor.test(value);
-}
-
-/**
- * Escapes the `RegExp` special characters "\", "/", "^", "$", ".", "|", "?",
- * "*", "+", "(", ")", "[", "]", "{" and "}" in `string`.
- *
- * @static
- * @memberOf _
- * @category String
- * @param {string} [string=''] The string to escape.
- * @returns {string} Returns the escaped string.
- * @example
- *
- * _.escapeRegExp('[lodash](https://lodash.com/)');
- * // => '\[lodash\]\(https:\/\/lodash\.com\/\)'
- */
-function escapeRegExp(string) {
- string = baseToString(string);
- return (string && reHasRegExpChars.test(string))
- ? string.replace(reRegExpChars, '\\$&')
- : string;
-}
-
-module.exports = isArray;
-
-},{}],27:[function(require,module,exports){
-/**
- * lodash 3.0.3 (Custom Build)
- * Build: `lodash modern modularize exports="npm" -o ./`
- * Copyright 2012-2015 The Dojo Foundation
- * Based on Underscore.js 1.8.3
- * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
- * Available under MIT license
- */
-
-/** `Object#toString` result references. */
-var arrayTag = '[object Array]',
- funcTag = '[object Function]';
-
-/**
- * Used to match `RegExp` [special characters](http://www.regular-expressions.info/characters.html#special).
- * In addition to special characters the forward slash is escaped to allow for
- * easier `eval` use and `Function` compilation.
- */
-var reRegExpChars = /[.*+?^${}()|[\]\/\\]/g,
- reHasRegExpChars = RegExp(reRegExpChars.source);
-
-/** Used to detect host constructors (Safari > 5). */
-var reIsHostCtor = /^\[object .+?Constructor\]$/;
-
-/**
- * Converts `value` to a string if it's not one. An empty string is returned
- * for `null` or `undefined` values.
- *
- * @private
- * @param {*} value The value to process.
- * @returns {string} Returns the string.
- */
-function baseToString(value) {
- if (typeof value == 'string') {
- return value;
- }
- return value == null ? '' : (value + '');
-}
-
-/**
- * Checks if `value` is object-like.
- *
- * @private
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
- */
-function isObjectLike(value) {
- return !!value && typeof value == 'object';
-}
-
-/** Used for native method references. */
-var objectProto = Object.prototype;
-
-/** Used to resolve the decompiled source of functions. */
-var fnToString = Function.prototype.toString;
-
-/** Used to check objects for own properties. */
-var hasOwnProperty = objectProto.hasOwnProperty;
-
-/**
- * Used to resolve the [`toStringTag`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring)
- * of values.
- */
-var objToString = objectProto.toString;
-
-/** Used to detect if a method is native. */
-var reIsNative = RegExp('^' +
- escapeRegExp(fnToString.call(hasOwnProperty))
- .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
-);
-
-/* Native method references for those with the same name as other `lodash` methods. */
-var nativeIsArray = getNative(Array, 'isArray');
-
-/**
- * Used as the [maximum length](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.max_safe_integer)
- * of an array-like value.
- */
-var MAX_SAFE_INTEGER = 9007199254740991;
-
-/**
- * Gets the native function at `key` of `object`.
- *
- * @private
- * @param {Object} object The object to query.
- * @param {string} key The key of the method to get.
- * @returns {*} Returns the function if it's native, else `undefined`.
- */
-function getNative(object, key) {
- var value = object == null ? undefined : object[key];
- return isNative(value) ? value : undefined;
-}
-
-/**
- * Checks if `value` is a valid array-like length.
- *
- * **Note:** This function is based on [`ToLength`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength).
- *
- * @private
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
- */
-function isLength(value) {
- return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
-}
-
-/**
- * Checks if `value` is classified as an `Array` object.
- *
- * @static
- * @memberOf _
- * @category Lang
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
- * @example
- *
- * _.isArray([1, 2, 3]);
- * // => true
- *
- * _.isArray(function() { return arguments; }());
- * // => false
- */
-var isArray = nativeIsArray || function(value) {
- return isObjectLike(value) && isLength(value.length) && objToString.call(value) == arrayTag;
-};
-
-/**
- * Checks if `value` is a native function.
- *
- * @static
- * @memberOf _
- * @category Lang
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is a native function, else `false`.
- * @example
- *
- * _.isNative(Array.prototype.push);
- * // => true
- *
- * _.isNative(_);
- * // => false
- */
-function isNative(value) {
- if (value == null) {
- return false;
- }
- if (objToString.call(value) == funcTag) {
- return reIsNative.test(fnToString.call(value));
- }
- return isObjectLike(value) && reIsHostCtor.test(value);
-}
-
-/**
- * Escapes the `RegExp` special characters "\", "/", "^", "$", ".", "|", "?",
- * "*", "+", "(", ")", "[", "]", "{" and "}" in `string`.
- *
- * @static
- * @memberOf _
- * @category String
- * @param {string} [string=''] The string to escape.
- * @returns {string} Returns the escaped string.
- * @example
- *
- * _.escapeRegExp('[lodash](https://lodash.com/)');
- * // => '\[lodash\]\(https:\/\/lodash\.com\/\)'
- */
-function escapeRegExp(string) {
- string = baseToString(string);
- return (string && reHasRegExpChars.test(string))
- ? string.replace(reRegExpChars, '\\$&')
- : string;
-}
-
-module.exports = isArray;
-
-},{}],30:[function(require,module,exports){
-/**
- * lodash 3.0.0 (Custom Build)
- * Build: `lodash modern modularize exports="npm" -o ./`
- * Copyright 2012-2015 The Dojo Foundation
- * Based on Underscore.js 1.7.0
- * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
- * Available under MIT license
- */
-
-/**
- * A specialized version of `_.forEach` for arrays without support for callback
- * shorthands or `this` binding.
- *
- * @private
- * @param {Array} array The array to iterate over.
- * @param {Function} iteratee The function invoked per iteration.
- * @returns {Array} Returns `array`.
- */
-function arrayEach(array, iteratee) {
- var index = -1,
- length = array.length;
-
- while (++index < length) {
- if (iteratee(array[index], index, array) === false) {
- break;
- }
- }
- return array;
-}
-
-module.exports = arrayEach;
-
-},{}],29:[function(require,module,exports){
-/**
- * lodash 3.0.1 (Custom Build)
- * Build: `lodash modern modularize exports="npm" -o ./`
- * Copyright 2012-2015 The Dojo Foundation
- * Based on Underscore.js 1.8.3
- * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
- * Available under MIT license
- */
-
-/**
- * A specialized version of `baseCallback` which only supports `this` binding
- * and specifying the number of arguments to provide to `func`.
- *
- * @private
- * @param {Function} func The function to bind.
- * @param {*} thisArg The `this` binding of `func`.
- * @param {number} [argCount] The number of arguments to provide to `func`.
- * @returns {Function} Returns the callback.
- */
-function bindCallback(func, thisArg, argCount) {
- if (typeof func != 'function') {
- return identity;
- }
- if (thisArg === undefined) {
- return func;
- }
- switch (argCount) {
- case 1: return function(value) {
- return func.call(thisArg, value);
- };
- case 3: return function(value, index, collection) {
- return func.call(thisArg, value, index, collection);
- };
- case 4: return function(accumulator, value, index, collection) {
- return func.call(thisArg, accumulator, value, index, collection);
- };
- case 5: return function(value, other, key, object, source) {
- return func.call(thisArg, value, other, key, object, source);
- };
- }
- return function() {
- return func.apply(thisArg, arguments);
- };
-}
-
-/**
- * This method returns the first argument provided to it.
- *
- * @static
- * @memberOf _
- * @category Utility
- * @param {*} value Any value.
- * @returns {*} Returns `value`.
- * @example
- *
- * var object = { 'user': 'fred' };
- *
- * _.identity(object) === object;
- * // => true
- */
-function identity(value) {
- return value;
-}
-
-module.exports = bindCallback;
-
-},{}],25:[function(require,module,exports){
-var SENDERS = require('./senders');
-
-
-exports.toSessionSDP = function (session, opts) {
- var role = opts.role || 'initiator';
- var direction = opts.direction || 'outgoing';
- var sid = opts.sid || session.sid || Date.now();
- var time = opts.time || Date.now();
-
- var sdp = [
- 'v=0',
- 'o=- ' + sid + ' ' + time + ' IN IP4 0.0.0.0',
- 's=-',
- 't=0 0'
- ];
-
- var groups = session.groups || [];
- groups.forEach(function (group) {
- sdp.push('a=group:' + group.semantics + ' ' + group.contents.join(' '));
- });
-
- var contents = session.contents || [];
- contents.forEach(function (content) {
- sdp.push(exports.toMediaSDP(content, opts));
- });
-
- return sdp.join('\r\n') + '\r\n';
-};
-
-exports.toMediaSDP = function (content, opts) {
- var sdp = [];
-
- var role = opts.role || 'initiator';
- var direction = opts.direction || 'outgoing';
-
- var desc = content.description;
- var transport = content.transport;
- var payloads = desc.payloads || [];
- var fingerprints = (transport && transport.fingerprints) || [];
-
- var mline = [];
- if (desc.descType == 'datachannel') {
- mline.push('application');
- mline.push('1');
- mline.push('DTLS/SCTP');
- if (transport.sctp) {
- transport.sctp.forEach(function (map) {
- mline.push(map.number);
- });
- }
- } else {
- mline.push(desc.media);
- mline.push('1');
- if ((desc.encryption && desc.encryption.length > 0) || (fingerprints.length > 0)) {
- mline.push('RTP/SAVPF');
- } else {
- mline.push('RTP/AVPF');
- }
- payloads.forEach(function (payload) {
- mline.push(payload.id);
- });
- }
-
-
- sdp.push('m=' + mline.join(' '));
-
- sdp.push('c=IN IP4 0.0.0.0');
- if (desc.bandwidth && desc.bandwidth.type && desc.bandwidth.bandwidth) {
- sdp.push('b=' + desc.bandwidth.type + ':' + desc.bandwidth.bandwidth);
- }
- if (desc.descType == 'rtp') {
- sdp.push('a=rtcp:1 IN IP4 0.0.0.0');
- }
-
- if (transport) {
- if (transport.ufrag) {
- sdp.push('a=ice-ufrag:' + transport.ufrag);
- }
- if (transport.pwd) {
- sdp.push('a=ice-pwd:' + transport.pwd);
- }
+ if (transport) {
+ if (transport.ufrag) {
+ sdp.push('a=ice-ufrag:' + transport.ufrag);
+ }
+ if (transport.pwd) {
+ sdp.push('a=ice-pwd:' + transport.pwd);
+ }
var pushedSetup = false;
fingerprints.forEach(function (fingerprint) {
@@ -8331,6 +8997,14 @@ exports.toMediaSDP = function (content, opts) {
}
sdp.push('a=mid:' + content.name);
+ if (desc.sources && desc.sources.length) {
+ (desc.sources[0].parameters || []).forEach(function (param) {
+ if (param.key === 'msid') {
+ sdp.push('a=msid:' + param.value);
+ }
+ });
+ }
+
if (desc.mux) {
sdp.push('a=rtcp-mux');
}
@@ -8444,7 +9118,7 @@ exports.toCandidateSDP = function (candidate) {
return 'a=candidate:' + sdp.join(' ');
};
-},{"./senders":35}],26:[function(require,module,exports){
+},{"./senders":37}],28:[function(require,module,exports){
var SENDERS = require('./senders');
var parsers = require('./parsers');
var idCounter = Math.random();
@@ -8602,7 +9276,25 @@ exports.toMediaJSON = function (media, session, opts) {
desc.sourceGroups = parsers.sourceGroups(ssrcGroupLines || []);
var ssrcLines = parsers.findLines('a=ssrc:', lines);
- desc.sources = parsers.sources(ssrcLines || []);
+ var sources = desc.sources = parsers.sources(ssrcLines || []);
+
+ var msidLine = parsers.findLine('a=msid:', lines);
+ if (msidLine) {
+ var msid = parsers.msid(msidLine);
+ ['msid', 'mslabel', 'label'].forEach(function (key) {
+ for (var i = 0; i < sources.length; i++) {
+ var found = false;
+ for (var j = 0; j < sources[i].parameters.length; j++) {
+ if (sources[i].parameters[j].key === key) {
+ found = true;
+ }
+ }
+ if (!found) {
+ sources[i].parameters.push({ key: key, value: msid[key] });
+ }
+ }
+ });
+ }
if (parsers.findLine('a=x-google-flag:conference', lines, sessionLines)) {
desc.googConferenceFlag = true;
@@ -8620,37 +9312,319 @@ exports.toMediaJSON = function (media, session, opts) {
trans.fingerprints.push(fp);
});
- var ufragLine = parsers.findLine('a=ice-ufrag:', lines, sessionLines);
- var pwdLine = parsers.findLine('a=ice-pwd:', lines, sessionLines);
- if (ufragLine && pwdLine) {
- trans.ufrag = ufragLine.substr(12);
- trans.pwd = pwdLine.substr(10);
- trans.candidates = [];
+ var ufragLine = parsers.findLine('a=ice-ufrag:', lines, sessionLines);
+ var pwdLine = parsers.findLine('a=ice-pwd:', lines, sessionLines);
+ if (ufragLine && pwdLine) {
+ trans.ufrag = ufragLine.substr(12);
+ trans.pwd = pwdLine.substr(10);
+ trans.candidates = [];
+
+ var candidateLines = parsers.findLines('a=candidate:', lines, sessionLines);
+ candidateLines.forEach(function (line) {
+ trans.candidates.push(exports.toCandidateJSON(line));
+ });
+ }
+
+ if (desc.descType == 'datachannel') {
+ var sctpmapLines = parsers.findLines('a=sctpmap:', lines);
+ sctpmapLines.forEach(function (line) {
+ var sctp = parsers.sctpmap(line);
+ trans.sctp.push(sctp);
+ });
+ }
+
+ return content;
+};
+
+exports.toCandidateJSON = function (line) {
+ var candidate = parsers.candidate(line.split('\r\n')[0]);
+ candidate.id = (idCounter++).toString(36).substr(0, 12);
+ return candidate;
+};
+
+},{"./parsers":38,"./senders":37}],29:[function(require,module,exports){
+/**
+ * lodash 3.0.0 (Custom Build)
+ * Build: `lodash modern modularize exports="npm" -o ./`
+ * Copyright 2012-2015 The Dojo Foundation
+ * Based on Underscore.js 1.7.0
+ * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
+ * Available under MIT license
+ */
+
+/**
+ * A specialized version of `_.forEach` for arrays without support for callback
+ * shorthands or `this` binding.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Array} Returns `array`.
+ */
+function arrayEach(array, iteratee) {
+ var index = -1,
+ length = array.length;
+
+ while (++index < length) {
+ if (iteratee(array[index], index, array) === false) {
+ break;
+ }
+ }
+ return array;
+}
+
+module.exports = arrayEach;
+
+},{}],31:[function(require,module,exports){
+/**
+ * lodash 3.0.1 (Custom Build)
+ * Build: `lodash modern modularize exports="npm" -o ./`
+ * Copyright 2012-2015 The Dojo Foundation
+ * Based on Underscore.js 1.8.3
+ * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
+ * Available under MIT license
+ */
+
+/**
+ * A specialized version of `baseCallback` which only supports `this` binding
+ * and specifying the number of arguments to provide to `func`.
+ *
+ * @private
+ * @param {Function} func The function to bind.
+ * @param {*} thisArg The `this` binding of `func`.
+ * @param {number} [argCount] The number of arguments to provide to `func`.
+ * @returns {Function} Returns the callback.
+ */
+function bindCallback(func, thisArg, argCount) {
+ if (typeof func != 'function') {
+ return identity;
+ }
+ if (thisArg === undefined) {
+ return func;
+ }
+ switch (argCount) {
+ case 1: return function(value) {
+ return func.call(thisArg, value);
+ };
+ case 3: return function(value, index, collection) {
+ return func.call(thisArg, value, index, collection);
+ };
+ case 4: return function(accumulator, value, index, collection) {
+ return func.call(thisArg, accumulator, value, index, collection);
+ };
+ case 5: return function(value, other, key, object, source) {
+ return func.call(thisArg, value, other, key, object, source);
+ };
+ }
+ return function() {
+ return func.apply(thisArg, arguments);
+ };
+}
+
+/**
+ * This method returns the first argument provided to it.
+ *
+ * @static
+ * @memberOf _
+ * @category Utility
+ * @param {*} value Any value.
+ * @returns {*} Returns `value`.
+ * @example
+ *
+ * var object = { 'user': 'fred' };
+ *
+ * _.identity(object) === object;
+ * // => true
+ */
+function identity(value) {
+ return value;
+}
+
+module.exports = bindCallback;
+
+},{}],32:[function(require,module,exports){
+/**
+ * lodash 3.0.4 (Custom Build)
+ * Build: `lodash modern modularize exports="npm" -o ./`
+ * Copyright 2012-2015 The Dojo Foundation
+ * Based on Underscore.js 1.8.3
+ * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
+ * Available under MIT license
+ */
+
+/** `Object#toString` result references. */
+var arrayTag = '[object Array]',
+ funcTag = '[object Function]';
+
+/** Used to detect host constructors (Safari > 5). */
+var reIsHostCtor = /^\[object .+?Constructor\]$/;
+
+/**
+ * Checks if `value` is object-like.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
+ */
+function isObjectLike(value) {
+ return !!value && typeof value == 'object';
+}
+
+/** Used for native method references. */
+var objectProto = Object.prototype;
+
+/** Used to resolve the decompiled source of functions. */
+var fnToString = Function.prototype.toString;
+
+/** Used to check objects for own properties. */
+var hasOwnProperty = objectProto.hasOwnProperty;
+
+/**
+ * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)
+ * of values.
+ */
+var objToString = objectProto.toString;
+
+/** Used to detect if a method is native. */
+var reIsNative = RegExp('^' +
+ fnToString.call(hasOwnProperty).replace(/[\\^$.*+?()[\]{}|]/g, '\\$&')
+ .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
+);
+
+/* Native method references for those with the same name as other `lodash` methods. */
+var nativeIsArray = getNative(Array, 'isArray');
- var candidateLines = parsers.findLines('a=candidate:', lines, sessionLines);
- candidateLines.forEach(function (line) {
- trans.candidates.push(exports.toCandidateJSON(line));
- });
- }
+/**
+ * Used as the [maximum length](http://ecma-international.org/ecma-262/6.0/#sec-number.max_safe_integer)
+ * of an array-like value.
+ */
+var MAX_SAFE_INTEGER = 9007199254740991;
- if (desc.descType == 'datachannel') {
- var sctpmapLines = parsers.findLines('a=sctpmap:', lines);
- sctpmapLines.forEach(function (line) {
- var sctp = parsers.sctpmap(line);
- trans.sctp.push(sctp);
- });
- }
+/**
+ * Gets the native function at `key` of `object`.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @param {string} key The key of the method to get.
+ * @returns {*} Returns the function if it's native, else `undefined`.
+ */
+function getNative(object, key) {
+ var value = object == null ? undefined : object[key];
+ return isNative(value) ? value : undefined;
+}
- return content;
-};
+/**
+ * Checks if `value` is a valid array-like length.
+ *
+ * **Note:** This function is based on [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength).
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
+ */
+function isLength(value) {
+ return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
+}
-exports.toCandidateJSON = function (line) {
- var candidate = parsers.candidate(line.split('\r\n')[0]);
- candidate.id = (idCounter++).toString(36).substr(0, 12);
- return candidate;
+/**
+ * Checks if `value` is classified as an `Array` object.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+ * @example
+ *
+ * _.isArray([1, 2, 3]);
+ * // => true
+ *
+ * _.isArray(function() { return arguments; }());
+ * // => false
+ */
+var isArray = nativeIsArray || function(value) {
+ return isObjectLike(value) && isLength(value.length) && objToString.call(value) == arrayTag;
};
-},{"./parsers":36,"./senders":35}],33:[function(require,module,exports){
+/**
+ * Checks if `value` is classified as a `Function` object.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+ * @example
+ *
+ * _.isFunction(_);
+ * // => true
+ *
+ * _.isFunction(/abc/);
+ * // => false
+ */
+function isFunction(value) {
+ // The use of `Object#toString` avoids issues with the `typeof` operator
+ // in older versions of Chrome and Safari which return 'function' for regexes
+ // and Safari 8 equivalents which return 'object' for typed array constructors.
+ return isObject(value) && objToString.call(value) == funcTag;
+}
+
+/**
+ * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`.
+ * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is an object, else `false`.
+ * @example
+ *
+ * _.isObject({});
+ * // => true
+ *
+ * _.isObject([1, 2, 3]);
+ * // => true
+ *
+ * _.isObject(1);
+ * // => false
+ */
+function isObject(value) {
+ // Avoid a V8 JIT bug in Chrome 19-20.
+ // See https://code.google.com/p/v8/issues/detail?id=2291 for more details.
+ var type = typeof value;
+ return !!value && (type == 'object' || type == 'function');
+}
+
+/**
+ * Checks if `value` is a native function.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a native function, else `false`.
+ * @example
+ *
+ * _.isNative(Array.prototype.push);
+ * // => true
+ *
+ * _.isNative(_);
+ * // => false
+ */
+function isNative(value) {
+ if (value == null) {
+ return false;
+ }
+ if (isFunction(value)) {
+ return reIsNative.test(fnToString.call(value));
+ }
+ return isObjectLike(value) && reIsHostCtor.test(value);
+}
+
+module.exports = isArray;
+
+},{}],33:[function(require,module,exports){
/**
* lodash 3.7.2 (Custom Build)
* Build: `lodash modern modularize exports="npm" -o ./`
@@ -8687,14 +9661,170 @@ function baseGet(object, path, pathKey) {
}
/**
- * Converts `value` to an object if it's not one.
+ * Converts `value` to an object if it's not one.
+ *
+ * @private
+ * @param {*} value The value to process.
+ * @returns {Object} Returns the object.
+ */
+function toObject(value) {
+ return isObject(value) ? value : Object(value);
+}
+
+/**
+ * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`.
+ * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is an object, else `false`.
+ * @example
+ *
+ * _.isObject({});
+ * // => true
+ *
+ * _.isObject([1, 2, 3]);
+ * // => true
+ *
+ * _.isObject(1);
+ * // => false
+ */
+function isObject(value) {
+ // Avoid a V8 JIT bug in Chrome 19-20.
+ // See https://code.google.com/p/v8/issues/detail?id=2291 for more details.
+ var type = typeof value;
+ return !!value && (type == 'object' || type == 'function');
+}
+
+module.exports = baseGet;
+
+},{}],35:[function(require,module,exports){
+/**
+ * lodash 3.0.4 (Custom Build)
+ * Build: `lodash modern modularize exports="npm" -o ./`
+ * Copyright 2012-2015 The Dojo Foundation
+ * Based on Underscore.js 1.8.3
+ * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
+ * Available under MIT license
+ */
+
+/** `Object#toString` result references. */
+var arrayTag = '[object Array]',
+ funcTag = '[object Function]';
+
+/** Used to detect host constructors (Safari > 5). */
+var reIsHostCtor = /^\[object .+?Constructor\]$/;
+
+/**
+ * Checks if `value` is object-like.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
+ */
+function isObjectLike(value) {
+ return !!value && typeof value == 'object';
+}
+
+/** Used for native method references. */
+var objectProto = Object.prototype;
+
+/** Used to resolve the decompiled source of functions. */
+var fnToString = Function.prototype.toString;
+
+/** Used to check objects for own properties. */
+var hasOwnProperty = objectProto.hasOwnProperty;
+
+/**
+ * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)
+ * of values.
+ */
+var objToString = objectProto.toString;
+
+/** Used to detect if a method is native. */
+var reIsNative = RegExp('^' +
+ fnToString.call(hasOwnProperty).replace(/[\\^$.*+?()[\]{}|]/g, '\\$&')
+ .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
+);
+
+/* Native method references for those with the same name as other `lodash` methods. */
+var nativeIsArray = getNative(Array, 'isArray');
+
+/**
+ * Used as the [maximum length](http://ecma-international.org/ecma-262/6.0/#sec-number.max_safe_integer)
+ * of an array-like value.
+ */
+var MAX_SAFE_INTEGER = 9007199254740991;
+
+/**
+ * Gets the native function at `key` of `object`.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @param {string} key The key of the method to get.
+ * @returns {*} Returns the function if it's native, else `undefined`.
+ */
+function getNative(object, key) {
+ var value = object == null ? undefined : object[key];
+ return isNative(value) ? value : undefined;
+}
+
+/**
+ * Checks if `value` is a valid array-like length.
+ *
+ * **Note:** This function is based on [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength).
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
+ */
+function isLength(value) {
+ return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
+}
+
+/**
+ * Checks if `value` is classified as an `Array` object.
*
- * @private
- * @param {*} value The value to process.
- * @returns {Object} Returns the object.
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+ * @example
+ *
+ * _.isArray([1, 2, 3]);
+ * // => true
+ *
+ * _.isArray(function() { return arguments; }());
+ * // => false
*/
-function toObject(value) {
- return isObject(value) ? value : Object(value);
+var isArray = nativeIsArray || function(value) {
+ return isObjectLike(value) && isLength(value.length) && objToString.call(value) == arrayTag;
+};
+
+/**
+ * Checks if `value` is classified as a `Function` object.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+ * @example
+ *
+ * _.isFunction(_);
+ * // => true
+ *
+ * _.isFunction(/abc/);
+ * // => false
+ */
+function isFunction(value) {
+ // The use of `Object#toString` avoids issues with the `typeof` operator
+ // in older versions of Chrome and Safari which return 'function' for regexes
+ // and Safari 8 equivalents which return 'object' for typed array constructors.
+ return isObject(value) && objToString.call(value) == funcTag;
}
/**
@@ -8724,246 +9854,306 @@ function isObject(value) {
return !!value && (type == 'object' || type == 'function');
}
-module.exports = baseGet;
+/**
+ * Checks if `value` is a native function.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a native function, else `false`.
+ * @example
+ *
+ * _.isNative(Array.prototype.push);
+ * // => true
+ *
+ * _.isNative(_);
+ * // => false
+ */
+function isNative(value) {
+ if (value == null) {
+ return false;
+ }
+ if (isFunction(value)) {
+ return reIsNative.test(fnToString.call(value));
+ }
+ return isObjectLike(value) && reIsHostCtor.test(value);
+}
-},{}],21:[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');
+module.exports = isArray;
-function dumpSDP(description) {
- return {
- type: description.type,
- sdp: description.sdp
- };
-}
+},{}],38:[function(require,module,exports){
+exports.lines = function (sdp) {
+ return sdp.split('\r\n').filter(function (line) {
+ return line.length > 0;
+ });
+};
-function dumpStream(stream) {
- var info = {
- label: stream.id,
- };
- if (stream.getAudioTracks().length) {
- info.audio = stream.getAudioTracks().map(function (track) {
- return track.id;
- });
+exports.findLine = function (prefix, mediaLines, sessionLines) {
+ var prefixLength = prefix.length;
+ for (var i = 0; i < mediaLines.length; i++) {
+ if (mediaLines[i].substr(0, prefixLength) === prefix) {
+ return mediaLines[i];
+ }
}
- if (stream.getVideoTracks().length) {
- info.video = stream.getVideoTracks().map(function (track) {
- return track.id;
- });
+ // Continue searching in parent session section
+ if (!sessionLines) {
+ return false;
}
- return info;
-}
-
-function TraceablePeerConnection(config, constraints) {
- var self = this;
- WildEmitter.call(this);
- this.peerconnection = new webrtc.PeerConnection(config, constraints);
+ for (var j = 0; j < sessionLines.length; j++) {
+ if (sessionLines[j].substr(0, prefixLength) === prefix) {
+ return sessionLines[j];
+ }
+ }
- this.trace = function (what, info) {
- self.emit('PeerConnectionTrace', {
- time: new Date(),
- type: what,
- value: info || ""
- });
- };
+ return false;
+};
- this.onicecandidate = null;
- this.peerconnection.onicecandidate = function (event) {
- self.trace('onicecandidate', event.candidate);
- if (self.onicecandidate !== null) {
- self.onicecandidate(event);
- }
- };
- this.onaddstream = null;
- this.peerconnection.onaddstream = function (event) {
- self.trace('onaddstream', dumpStream(event.stream));
- if (self.onaddstream !== null) {
- self.onaddstream(event);
+exports.findLines = function (prefix, mediaLines, sessionLines) {
+ var results = [];
+ var prefixLength = prefix.length;
+ for (var i = 0; i < mediaLines.length; i++) {
+ if (mediaLines[i].substr(0, prefixLength) === prefix) {
+ results.push(mediaLines[i]);
}
- };
- this.onremovestream = null;
- this.peerconnection.onremovestream = function (event) {
- self.trace('onremovestream', dumpStream(event.stream));
- if (self.onremovestream !== null) {
- self.onremovestream(event);
+ }
+ if (results.length || !sessionLines) {
+ return results;
+ }
+ for (var j = 0; j < sessionLines.length; j++) {
+ if (sessionLines[j].substr(0, prefixLength) === prefix) {
+ results.push(sessionLines[j]);
}
+ }
+ return results;
+};
+
+exports.mline = function (line) {
+ var parts = line.substr(2).split(' ');
+ var parsed = {
+ media: parts[0],
+ port: parts[1],
+ proto: parts[2],
+ formats: []
};
- this.onsignalingstatechange = null;
- this.peerconnection.onsignalingstatechange = function (event) {
- self.trace('onsignalingstatechange', self.signalingState);
- if (self.onsignalingstatechange !== null) {
- self.onsignalingstatechange(event);
+ for (var i = 3; i < parts.length; i++) {
+ if (parts[i]) {
+ parsed.formats.push(parts[i]);
}
+ }
+ return parsed;
+};
+
+exports.rtpmap = function (line) {
+ var parts = line.substr(9).split(' ');
+ var parsed = {
+ id: parts.shift()
};
- this.oniceconnectionstatechange = null;
- this.peerconnection.oniceconnectionstatechange = function (event) {
- self.trace('oniceconnectionstatechange', self.iceConnectionState);
- if (self.oniceconnectionstatechange !== null) {
- self.oniceconnectionstatechange(event);
- }
+
+ parts = parts[0].split('/');
+
+ parsed.name = parts[0];
+ parsed.clockrate = parts[1];
+ parsed.channels = parts.length == 3 ? parts[2] : '1';
+ return parsed;
+};
+
+exports.sctpmap = function (line) {
+ // based on -05 draft
+ var parts = line.substr(10).split(' ');
+ var parsed = {
+ number: parts.shift(),
+ protocol: parts.shift(),
+ streams: parts.shift()
};
- this.onnegotiationneeded = null;
- this.peerconnection.onnegotiationneeded = function (event) {
- self.trace('onnegotiationneeded');
- if (self.onnegotiationneeded !== null) {
- self.onnegotiationneeded(event);
+ return parsed;
+};
+
+
+exports.fmtp = function (line) {
+ var kv, key, value;
+ var parts = line.substr(line.indexOf(' ') + 1).split(';');
+ var parsed = [];
+ for (var i = 0; i < parts.length; i++) {
+ kv = parts[i].split('=');
+ key = kv[0].trim();
+ value = kv[1];
+ if (key && value) {
+ parsed.push({key: key, value: value});
+ } else if (key) {
+ parsed.push({key: '', value: key});
}
+ }
+ return parsed;
+};
+
+exports.crypto = function (line) {
+ var parts = line.substr(9).split(' ');
+ var parsed = {
+ tag: parts[0],
+ cipherSuite: parts[1],
+ keyParams: parts[2],
+ sessionParams: parts.slice(3).join(' ')
};
- self.ondatachannel = null;
- this.peerconnection.ondatachannel = function (event) {
- self.trace('ondatachannel', event);
- if (self.ondatachannel !== null) {
- self.ondatachannel(event);
- }
+ return parsed;
+};
+
+exports.fingerprint = function (line) {
+ var parts = line.substr(14).split(' ');
+ return {
+ hash: parts[0],
+ value: parts[1]
};
- this.getLocalStreams = this.peerconnection.getLocalStreams.bind(this.peerconnection);
- this.getRemoteStreams = this.peerconnection.getRemoteStreams.bind(this.peerconnection);
-}
+};
-util.inherits(TraceablePeerConnection, WildEmitter);
+exports.extmap = function (line) {
+ var parts = line.substr(9).split(' ');
+ var parsed = {};
-Object.defineProperty(TraceablePeerConnection.prototype, 'signalingState', {
- get: function () {
- return this.peerconnection.signalingState;
+ var idpart = parts.shift();
+ var sp = idpart.indexOf('/');
+ if (sp >= 0) {
+ parsed.id = idpart.substr(0, sp);
+ parsed.senders = idpart.substr(sp + 1);
+ } else {
+ parsed.id = idpart;
+ parsed.senders = 'sendrecv';
}
-});
-Object.defineProperty(TraceablePeerConnection.prototype, 'iceConnectionState', {
- get: function () {
- return this.peerconnection.iceConnectionState;
+ parsed.uri = parts.shift() || '';
+
+ return parsed;
+};
+
+exports.rtcpfb = function (line) {
+ var parts = line.substr(10).split(' ');
+ var parsed = {};
+ parsed.id = parts.shift();
+ parsed.type = parts.shift();
+ if (parsed.type === 'trr-int') {
+ parsed.value = parts.shift();
+ } else {
+ parsed.subtype = parts.shift() || '';
}
-});
+ parsed.parameters = parts;
+ return parsed;
+};
-Object.defineProperty(TraceablePeerConnection.prototype, 'localDescription', {
- get: function () {
- return this.peerconnection.localDescription;
+exports.candidate = function (line) {
+ var parts;
+ if (line.indexOf('a=candidate:') === 0) {
+ parts = line.substring(12).split(' ');
+ } else { // no a=candidate
+ parts = line.substring(10).split(' ');
}
-});
-Object.defineProperty(TraceablePeerConnection.prototype, 'remoteDescription', {
- get: function () {
- return this.peerconnection.remoteDescription;
+ var candidate = {
+ foundation: parts[0],
+ component: parts[1],
+ protocol: parts[2].toLowerCase(),
+ priority: parts[3],
+ ip: parts[4],
+ port: parts[5],
+ // skip parts[6] == 'typ'
+ type: parts[7],
+ generation: '0'
+ };
+
+ for (var i = 8; i < parts.length; i += 2) {
+ if (parts[i] === 'raddr') {
+ candidate.relAddr = parts[i + 1];
+ } else if (parts[i] === 'rport') {
+ candidate.relPort = parts[i + 1];
+ } else if (parts[i] === 'generation') {
+ candidate.generation = parts[i + 1];
+ } else if (parts[i] === 'tcptype') {
+ candidate.tcpType = parts[i + 1];
+ }
}
-});
-TraceablePeerConnection.prototype.addStream = function (stream) {
- this.trace('addStream', dumpStream(stream));
- this.peerconnection.addStream(stream);
-};
+ candidate.network = '1';
-TraceablePeerConnection.prototype.removeStream = function (stream) {
- this.trace('removeStream', dumpStream(stream));
- this.peerconnection.removeStream(stream);
+ return candidate;
};
-TraceablePeerConnection.prototype.createDataChannel = function (label, opts) {
- this.trace('createDataChannel', label, opts);
- return this.peerconnection.createDataChannel(label, opts);
+exports.sourceGroups = function (lines) {
+ var parsed = [];
+ for (var i = 0; i < lines.length; i++) {
+ var parts = lines[i].substr(13).split(' ');
+ parsed.push({
+ semantics: parts.shift(),
+ sources: parts
+ });
+ }
+ return parsed;
};
-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);
- }
- );
-};
+exports.sources = function (lines) {
+ // http://tools.ietf.org/html/rfc5576
+ var parsed = [];
+ var sources = {};
+ for (var i = 0; i < lines.length; i++) {
+ var parts = lines[i].substr(7).split(' ');
+ var ssrc = parts.shift();
-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);
+ if (!sources[ssrc]) {
+ var source = {
+ ssrc: ssrc,
+ parameters: []
+ };
+ parsed.push(source);
+
+ // Keep an index
+ sources[ssrc] = source;
}
- );
-};
-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();
+ parts = parts.join(' ').split(':');
+ var attribute = parts.shift();
+ var value = parts.join(':') || null;
+
+ sources[ssrc].parameters.push({
+ key: attribute,
+ value: value
+ });
}
-};
-TraceablePeerConnection.prototype.createOffer = function (successCallback, failureCallback, constraints) {
- var self = this;
- this.trace('createOffer', constraints);
- this.peerconnection.createOffer(
- function (offer) {
- self.trace('createOfferOnSuccess', dumpSDP(offer));
- successCallback(offer);
- },
- function (err) {
- self.trace('createOfferOnFailure', err);
- failureCallback(err);
- },
- constraints
- );
+ return parsed;
};
-TraceablePeerConnection.prototype.createAnswer = function (successCallback, failureCallback, constraints) {
- var self = this;
- this.trace('createAnswer', constraints);
- this.peerconnection.createAnswer(
- function (answer) {
- self.trace('createAnswerOnSuccess', dumpSDP(answer));
- successCallback(answer);
- },
- function (err) {
- self.trace('createAnswerOnFailure', err);
- failureCallback(err);
- },
- constraints
- );
+exports.groups = function (lines) {
+ // http://tools.ietf.org/html/rfc5888
+ var parsed = [];
+ var parts;
+ for (var i = 0; i < lines.length; i++) {
+ parts = lines[i].substr(8).split(' ');
+ parsed.push({
+ semantics: parts.shift(),
+ contents: parts
+ });
+ }
+ return parsed;
};
-TraceablePeerConnection.prototype.addIceCandidate = function (candidate, successCallback, failureCallback) {
- var self = this;
- this.trace('addIceCandidate', candidate);
- this.peerconnection.addIceCandidate(candidate,
- function () {
- //self.trace('addIceCandidateOnSuccess');
- if (successCallback) successCallback();
- },
- function (err) {
- self.trace('addIceCandidateOnFailure', err);
- if (failureCallback) failureCallback(err);
- }
- );
+exports.bandwidth = function (line) {
+ var parts = line.substr(2).split(':');
+ var parsed = {};
+ parsed.type = parts.shift();
+ parsed.bandwidth = parts.shift();
+ return parsed;
};
-TraceablePeerConnection.prototype.getStats = function (callback, errback) {
- if (navigator.mozGetUserMedia) {
- this.peerconnection.getStats(null, callback, errback);
- } else {
- this.peerconnection.getStats(callback);
- }
+exports.msid = function (line) {
+ var data = line.substr(7);
+ var parts = data.split(' ');
+ return {
+ msid: data,
+ mslabel: parts[0],
+ label: parts[1]
+ };
};
-module.exports = TraceablePeerConnection;
-
-},{"util":8,"webrtcsupport":5,"wildemitter":4}],35:[function(require,module,exports){
+},{}],37:[function(require,module,exports){
module.exports = {
initiator: {
incoming: {
@@ -8996,283 +10186,235 @@ module.exports = {
recvonly: 'responder',
sendonly: 'initiator',
sendrecv: 'both',
- inactive: 'none'
- },
- outgoing: {
- initiator: 'recvonly',
- responder: 'sendonly',
- both: 'sendrecv',
- none: 'inactive',
- recvonly: 'initiator',
- sendonly: 'responder',
- sendrecv: 'both',
- inactive: 'none'
- }
- }
-};
-
-},{}],36:[function(require,module,exports){
-exports.lines = function (sdp) {
- return sdp.split('\r\n').filter(function (line) {
- return line.length > 0;
- });
-};
-
-exports.findLine = function (prefix, mediaLines, sessionLines) {
- var prefixLength = prefix.length;
- for (var i = 0; i < mediaLines.length; i++) {
- if (mediaLines[i].substr(0, prefixLength) === prefix) {
- return mediaLines[i];
- }
- }
- // Continue searching in parent session section
- if (!sessionLines) {
- return false;
- }
-
- for (var j = 0; j < sessionLines.length; j++) {
- if (sessionLines[j].substr(0, prefixLength) === prefix) {
- return sessionLines[j];
- }
- }
-
- return false;
-};
-
-exports.findLines = function (prefix, mediaLines, sessionLines) {
- var results = [];
- var prefixLength = prefix.length;
- for (var i = 0; i < mediaLines.length; i++) {
- if (mediaLines[i].substr(0, prefixLength) === prefix) {
- results.push(mediaLines[i]);
- }
- }
- if (results.length || !sessionLines) {
- return results;
- }
- for (var j = 0; j < sessionLines.length; j++) {
- if (sessionLines[j].substr(0, prefixLength) === prefix) {
- results.push(sessionLines[j]);
+ inactive: 'none'
+ },
+ outgoing: {
+ initiator: 'recvonly',
+ responder: 'sendonly',
+ both: 'sendrecv',
+ none: 'inactive',
+ recvonly: 'initiator',
+ sendonly: 'responder',
+ sendrecv: 'both',
+ inactive: 'none'
}
}
- return results;
};
-exports.mline = function (line) {
- var parts = line.substr(2).split(' ');
- var parsed = {
- media: parts[0],
- port: parts[1],
- proto: parts[2],
- formats: []
+},{}],22:[function(require,module,exports){
+// based on https://github.com/ESTOS/strophe.jingle/
+// adds wildemitter support
+var util = require('util');
+var adapter = require('webrtc-adapter-test');
+var WildEmitter = require('wildemitter');
+
+function dumpSDP(description) {
+ return {
+ type: description.type,
+ sdp: description.sdp
};
- for (var i = 3; i < parts.length; i++) {
- if (parts[i]) {
- parsed.formats.push(parts[i]);
- }
- }
- return parsed;
-};
+}
-exports.rtpmap = function (line) {
- var parts = line.substr(9).split(' ');
- var parsed = {
- id: parts.shift()
+function dumpStream(stream) {
+ var info = {
+ label: stream.id,
};
+ if (stream.getAudioTracks().length) {
+ info.audio = stream.getAudioTracks().map(function (track) {
+ return track.id;
+ });
+ }
+ if (stream.getVideoTracks().length) {
+ info.video = stream.getVideoTracks().map(function (track) {
+ return track.id;
+ });
+ }
+ return info;
+}
- parts = parts[0].split('/');
+function TraceablePeerConnection(config, constraints) {
+ var self = this;
+ WildEmitter.call(this);
- parsed.name = parts[0];
- parsed.clockrate = parts[1];
- parsed.channels = parts.length == 3 ? parts[2] : '1';
- return parsed;
-};
+ this.peerconnection = new window.RTCPeerConnection(config, constraints);
-exports.sctpmap = function (line) {
- // based on -05 draft
- var parts = line.substr(10).split(' ');
- var parsed = {
- number: parts.shift(),
- protocol: parts.shift(),
- streams: parts.shift()
+ this.trace = function (what, info) {
+ self.emit('PeerConnectionTrace', {
+ time: new Date(),
+ type: what,
+ value: info || ""
+ });
};
- return parsed;
-};
-
-exports.fmtp = function (line) {
- var kv, key, value;
- var parts = line.substr(line.indexOf(' ') + 1).split(';');
- var parsed = [];
- for (var i = 0; i < parts.length; i++) {
- kv = parts[i].split('=');
- key = kv[0].trim();
- value = kv[1];
- if (key && value) {
- parsed.push({key: key, value: value});
- } else if (key) {
- parsed.push({key: '', value: key});
+ this.onicecandidate = null;
+ this.peerconnection.onicecandidate = function (event) {
+ self.trace('onicecandidate', event.candidate);
+ if (self.onicecandidate !== null) {
+ self.onicecandidate(event);
}
- }
- return parsed;
-};
-
-exports.crypto = function (line) {
- var parts = line.substr(9).split(' ');
- var parsed = {
- tag: parts[0],
- cipherSuite: parts[1],
- keyParams: parts[2],
- sessionParams: parts.slice(3).join(' ')
};
- return parsed;
-};
-
-exports.fingerprint = function (line) {
- var parts = line.substr(14).split(' ');
- return {
- hash: parts[0],
- value: parts[1]
+ this.onaddstream = null;
+ this.peerconnection.onaddstream = function (event) {
+ self.trace('onaddstream', dumpStream(event.stream));
+ if (self.onaddstream !== null) {
+ self.onaddstream(event);
+ }
};
-};
-
-exports.extmap = function (line) {
- var parts = line.substr(9).split(' ');
- var parsed = {};
+ this.onremovestream = null;
+ this.peerconnection.onremovestream = function (event) {
+ self.trace('onremovestream', dumpStream(event.stream));
+ 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);
+ }
+ };
+ this.getLocalStreams = this.peerconnection.getLocalStreams.bind(this.peerconnection);
+ this.getRemoteStreams = this.peerconnection.getRemoteStreams.bind(this.peerconnection);
+}
- var idpart = parts.shift();
- var sp = idpart.indexOf('/');
- if (sp >= 0) {
- parsed.id = idpart.substr(0, sp);
- parsed.senders = idpart.substr(sp + 1);
- } else {
- parsed.id = idpart;
- parsed.senders = 'sendrecv';
- }
+util.inherits(TraceablePeerConnection, WildEmitter);
- parsed.uri = parts.shift() || '';
+['signalingState', 'iceConnectionState', 'localDescription', 'remoteDescription'].forEach(function (prop) {
+ Object.defineProperty(TraceablePeerConnection.prototype, prop, {
+ get: function () {
+ return this.peerconnection[prop];
+ }
+ });
+});
- return parsed;
+TraceablePeerConnection.prototype.addStream = function (stream) {
+ this.trace('addStream', dumpStream(stream));
+ this.peerconnection.addStream(stream);
};
-exports.rtcpfb = function (line) {
- var parts = line.substr(10).split(' ');
- var parsed = {};
- parsed.id = parts.shift();
- parsed.type = parts.shift();
- if (parsed.type === 'trr-int') {
- parsed.value = parts.shift();
- } else {
- parsed.subtype = parts.shift() || '';
- }
- parsed.parameters = parts;
- return parsed;
+TraceablePeerConnection.prototype.removeStream = function (stream) {
+ this.trace('removeStream', dumpStream(stream));
+ this.peerconnection.removeStream(stream);
};
-exports.candidate = function (line) {
- var parts;
- if (line.indexOf('a=candidate:') === 0) {
- parts = line.substring(12).split(' ');
- } else { // no a=candidate
- parts = line.substring(10).split(' ');
- }
-
- var candidate = {
- foundation: parts[0],
- component: parts[1],
- protocol: parts[2].toLowerCase(),
- priority: parts[3],
- ip: parts[4],
- port: parts[5],
- // skip parts[6] == 'typ'
- type: parts[7],
- generation: '0'
- };
+TraceablePeerConnection.prototype.createDataChannel = function (label, opts) {
+ this.trace('createDataChannel', label, opts);
+ return this.peerconnection.createDataChannel(label, opts);
+};
- for (var i = 8; i < parts.length; i += 2) {
- if (parts[i] === 'raddr') {
- candidate.relAddr = parts[i + 1];
- } else if (parts[i] === 'rport') {
- candidate.relPort = parts[i + 1];
- } else if (parts[i] === 'generation') {
- candidate.generation = parts[i + 1];
- } else if (parts[i] === 'tcptype') {
- candidate.tcpType = parts[i + 1];
+TraceablePeerConnection.prototype.setLocalDescription = function (description, successCallback, failureCallback) {
+ var self = this;
+ this.trace('setLocalDescription', dumpSDP(description));
+ this.peerconnection.setLocalDescription(description,
+ function () {
+ self.trace('setLocalDescriptionOnSuccess');
+ if (successCallback) successCallback();
+ },
+ function (err) {
+ self.trace('setLocalDescriptionOnFailure', err);
+ if (failureCallback) failureCallback(err);
}
- }
-
- candidate.network = '1';
+ );
+};
- return candidate;
+TraceablePeerConnection.prototype.setRemoteDescription = function (description, successCallback, failureCallback) {
+ var self = this;
+ this.trace('setRemoteDescription', dumpSDP(description));
+ this.peerconnection.setRemoteDescription(description,
+ function () {
+ self.trace('setRemoteDescriptionOnSuccess');
+ if (successCallback) successCallback();
+ },
+ function (err) {
+ self.trace('setRemoteDescriptionOnFailure', err);
+ if (failureCallback) failureCallback(err);
+ }
+ );
};
-exports.sourceGroups = function (lines) {
- var parsed = [];
- for (var i = 0; i < lines.length; i++) {
- var parts = lines[i].substr(13).split(' ');
- parsed.push({
- semantics: parts.shift(),
- sources: parts
- });
+TraceablePeerConnection.prototype.close = function () {
+ this.trace('stop');
+ if (this.peerconnection.signalingState != 'closed') {
+ this.peerconnection.close();
}
- return parsed;
};
-exports.sources = function (lines) {
- // http://tools.ietf.org/html/rfc5576
- var parsed = [];
- var sources = {};
- for (var i = 0; i < lines.length; i++) {
- var parts = lines[i].substr(7).split(' ');
- var ssrc = parts.shift();
+TraceablePeerConnection.prototype.createOffer = function (successCallback, failureCallback, constraints) {
+ var self = this;
+ this.trace('createOffer', constraints);
+ this.peerconnection.createOffer(
+ function (offer) {
+ self.trace('createOfferOnSuccess', dumpSDP(offer));
+ if (successCallback) successCallback(offer);
+ },
+ function (err) {
+ self.trace('createOfferOnFailure', err);
+ if (failureCallback) failureCallback(err);
+ },
+ constraints
+ );
+};
- if (!sources[ssrc]) {
- var source = {
- ssrc: ssrc,
- parameters: []
- };
- parsed.push(source);
+TraceablePeerConnection.prototype.createAnswer = function (successCallback, failureCallback, constraints) {
+ var self = this;
+ this.trace('createAnswer', constraints);
+ this.peerconnection.createAnswer(
+ function (answer) {
+ self.trace('createAnswerOnSuccess', dumpSDP(answer));
+ if (successCallback) successCallback(answer);
+ },
+ function (err) {
+ self.trace('createAnswerOnFailure', err);
+ if (failureCallback) failureCallback(err);
+ },
+ constraints
+ );
+};
- // Keep an index
- sources[ssrc] = source;
+TraceablePeerConnection.prototype.addIceCandidate = function (candidate, successCallback, failureCallback) {
+ var self = this;
+ this.trace('addIceCandidate', candidate);
+ this.peerconnection.addIceCandidate(candidate,
+ function () {
+ //self.trace('addIceCandidateOnSuccess');
+ if (successCallback) successCallback();
+ },
+ function (err) {
+ self.trace('addIceCandidateOnFailure', err);
+ if (failureCallback) failureCallback(err);
}
-
- parts = parts.join(' ').split(':');
- var attribute = parts.shift();
- var value = parts.join(':') || null;
-
- sources[ssrc].parameters.push({
- key: attribute,
- value: value
- });
- }
-
- return parsed;
+ );
};
-exports.groups = function (lines) {
- // http://tools.ietf.org/html/rfc5888
- var parsed = [];
- var parts;
- for (var i = 0; i < lines.length; i++) {
- parts = lines[i].substr(8).split(' ');
- parsed.push({
- semantics: parts.shift(),
- contents: parts
- });
- }
- return parsed;
+TraceablePeerConnection.prototype.getStats = function () {
+ this.peerconnection.getStats.apply(this.peerconnection, arguments);
};
-exports.bandwidth = function (line) {
- var parts = line.substr(2).split(':');
- var parsed = {};
- parsed.type = parts.shift();
- parsed.bandwidth = parts.shift();
- return parsed;
-};
+module.exports = TraceablePeerConnection;
-},{}],28:[function(require,module,exports){
+},{"util":8,"webrtc-adapter-test":20,"wildemitter":4}],30:[function(require,module,exports){
/**
* lodash 3.0.4 (Custom Build)
* Build: `lodash modern modularize exports="npm" -o ./`
@@ -9455,7 +10597,88 @@ function isObject(value) {
module.exports = baseEach;
-},{"lodash.keys":37}],32:[function(require,module,exports){
+},{"lodash.keys":39}],40:[function(require,module,exports){
+/**
+ * lodash 3.0.0 (Custom Build)
+ * Build: `lodash modern modularize exports="npm" -o ./`
+ * Copyright 2012-2015 The Dojo Foundation
+ * Based on Underscore.js 1.7.0
+ * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
+ * Available under MIT license
+ */
+
+/**
+ * A specialized version of `_.map` for arrays without support for callback
+ * shorthands or `this` binding.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Array} Returns the new mapped array.
+ */
+function arrayMap(array, iteratee) {
+ var index = -1,
+ length = array.length,
+ result = Array(length);
+
+ while (++index < length) {
+ result[index] = iteratee(array[index], index, array);
+ }
+ return result;
+}
+
+module.exports = arrayMap;
+
+},{}],34:[function(require,module,exports){
+/**
+ * lodash 3.8.1 (Custom Build)
+ * Build: `lodash modern modularize exports="npm" -o ./`
+ * Copyright 2012-2015 The Dojo Foundation
+ * Based on Underscore.js 1.8.3
+ * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
+ * Available under MIT license
+ */
+var isArray = require('lodash.isarray');
+
+/** Used to match property names within property paths. */
+var rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\n\\]|\\.)*?)\2)\]/g;
+
+/** Used to match backslashes in property paths. */
+var reEscapeChar = /\\(\\)?/g;
+
+/**
+ * Converts `value` to a string if it's not one. An empty string is returned
+ * for `null` or `undefined` values.
+ *
+ * @private
+ * @param {*} value The value to process.
+ * @returns {string} Returns the string.
+ */
+function baseToString(value) {
+ return value == null ? '' : (value + '');
+}
+
+/**
+ * Converts `value` to property path array if it's not one.
+ *
+ * @private
+ * @param {*} value The value to process.
+ * @returns {Array} Returns the property path array.
+ */
+function toPath(value) {
+ if (isArray(value)) {
+ return value;
+ }
+ var result = [];
+ baseToString(value).replace(rePropName, function(match, number, quote, string) {
+ result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match));
+ });
+ return result;
+}
+
+module.exports = toPath;
+
+},{"lodash.isarray":35}],36:[function(require,module,exports){
/**
* lodash 3.1.4 (Custom Build)
* Build: `lodash modern modularize exports="npm" -o ./`
@@ -9592,108 +10815,24 @@ function isLength(value) {
*
* var users = [
* { 'user': 'barney' },
- * { 'user': 'fred' }
- * ];
- *
- * // using the `_.property` callback shorthand
- * _.map(users, 'user');
- * // => ['barney', 'fred']
- */
-function map(collection, iteratee, thisArg) {
- var func = isArray(collection) ? arrayMap : baseMap;
- iteratee = baseCallback(iteratee, thisArg, 3);
- return func(collection, iteratee);
-}
-
-module.exports = map;
-
-},{"lodash._arraymap":39,"lodash._basecallback":38,"lodash._baseeach":40,"lodash.isarray":31}],34:[function(require,module,exports){
-/**
- * lodash 3.8.0 (Custom Build)
- * Build: `lodash modern modularize exports="npm" -o ./`
- * Copyright 2012-2015 The Dojo Foundation
- * Based on Underscore.js 1.8.3
- * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
- * Available under MIT license
- */
-var isArray = require('lodash.isarray');
-
-/** Used to match property names within property paths. */
-var rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\n\\]|\\.)*?)\2)\]/g;
-
-/** Used to match backslashes in property paths. */
-var reEscapeChar = /\\(\\)?/g;
-
-/**
- * Converts `value` to a string if it is not one. An empty string is returned
- * for `null` or `undefined` values.
- *
- * @private
- * @param {*} value The value to process.
- * @returns {string} Returns the string.
- */
-function baseToString(value) {
- if (typeof value == 'string') {
- return value;
- }
- return value == null ? '' : (value + '');
-}
-
-/**
- * Converts `value` to property path array if it is not one.
- *
- * @private
- * @param {*} value The value to process.
- * @returns {Array} Returns the property path array.
- */
-function toPath(value) {
- if (isArray(value)) {
- return value;
- }
- var result = [];
- baseToString(value).replace(rePropName, function(match, number, quote, string) {
- result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match));
- });
- return result;
-}
-
-module.exports = toPath;
-
-},{"lodash.isarray":31}],39:[function(require,module,exports){
-/**
- * lodash 3.0.0 (Custom Build)
- * Build: `lodash modern modularize exports="npm" -o ./`
- * Copyright 2012-2015 The Dojo Foundation
- * Based on Underscore.js 1.7.0
- * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
- * Available under MIT license
- */
-
-/**
- * A specialized version of `_.map` for arrays without support for callback
- * shorthands or `this` binding.
+ * { 'user': 'fred' }
+ * ];
*
- * @private
- * @param {Array} array The array to iterate over.
- * @param {Function} iteratee The function invoked per iteration.
- * @returns {Array} Returns the new mapped array.
+ * // using the `_.property` callback shorthand
+ * _.map(users, 'user');
+ * // => ['barney', 'fred']
*/
-function arrayMap(array, iteratee) {
- var index = -1,
- length = array.length,
- result = Array(length);
-
- while (++index < length) {
- result[index] = iteratee(array[index], index, array);
- }
- return result;
+function map(collection, iteratee, thisArg) {
+ var func = isArray(collection) ? arrayMap : baseMap;
+ iteratee = baseCallback(iteratee, thisArg, 3);
+ return func(collection, iteratee);
}
-module.exports = arrayMap;
+module.exports = map;
-},{}],41:[function(require,module,exports){
+},{"lodash._arraymap":40,"lodash._basecallback":41,"lodash._baseeach":42,"lodash.isarray":35}],43:[function(require,module,exports){
/**
- * lodash 3.9.0 (Custom Build)
+ * lodash 3.9.1 (Custom Build)
* Build: `lodash modern modularize exports="npm" -o ./`
* Copyright 2012-2015 The Dojo Foundation
* Based on Underscore.js 1.8.3
@@ -9704,33 +10843,10 @@ module.exports = arrayMap;
/** `Object#toString` result references. */
var funcTag = '[object Function]';
-/**
- * Used to match `RegExp` [special characters](http://www.regular-expressions.info/characters.html#special).
- * In addition to special characters the forward slash is escaped to allow for
- * easier `eval` use and `Function` compilation.
- */
-var reRegExpChars = /[.*+?^${}()|[\]\/\\]/g,
- reHasRegExpChars = RegExp(reRegExpChars.source);
-
/** Used to detect host constructors (Safari > 5). */
var reIsHostCtor = /^\[object .+?Constructor\]$/;
/**
- * Converts `value` to a string if it's not one. An empty string is returned
- * for `null` or `undefined` values.
- *
- * @private
- * @param {*} value The value to process.
- * @returns {string} Returns the string.
- */
-function baseToString(value) {
- if (typeof value == 'string') {
- return value;
- }
- return value == null ? '' : (value + '');
-}
-
-/**
* Checks if `value` is object-like.
*
* @private
@@ -9751,14 +10867,14 @@ var fnToString = Function.prototype.toString;
var hasOwnProperty = objectProto.hasOwnProperty;
/**
- * Used to resolve the [`toStringTag`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring)
+ * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)
* of values.
*/
var objToString = objectProto.toString;
/** Used to detect if a method is native. */
var reIsNative = RegExp('^' +
- escapeRegExp(fnToString.call(hasOwnProperty))
+ fnToString.call(hasOwnProperty).replace(/[\\^$.*+?()[\]{}|]/g, '\\$&')
.replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
);
@@ -9776,6 +10892,56 @@ function getNative(object, key) {
}
/**
+ * Checks if `value` is classified as a `Function` object.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+ * @example
+ *
+ * _.isFunction(_);
+ * // => true
+ *
+ * _.isFunction(/abc/);
+ * // => false
+ */
+function isFunction(value) {
+ // The use of `Object#toString` avoids issues with the `typeof` operator
+ // in older versions of Chrome and Safari which return 'function' for regexes
+ // and Safari 8 equivalents which return 'object' for typed array constructors.
+ return isObject(value) && objToString.call(value) == funcTag;
+}
+
+/**
+ * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`.
+ * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is an object, else `false`.
+ * @example
+ *
+ * _.isObject({});
+ * // => true
+ *
+ * _.isObject([1, 2, 3]);
+ * // => true
+ *
+ * _.isObject(1);
+ * // => false
+ */
+function isObject(value) {
+ // Avoid a V8 JIT bug in Chrome 19-20.
+ // See https://code.google.com/p/v8/issues/detail?id=2291 for more details.
+ var type = typeof value;
+ return !!value && (type == 'object' || type == 'function');
+}
+
+/**
* Checks if `value` is a native function.
*
* @static
@@ -9795,38 +10961,17 @@ function isNative(value) {
if (value == null) {
return false;
}
- if (objToString.call(value) == funcTag) {
+ if (isFunction(value)) {
return reIsNative.test(fnToString.call(value));
}
return isObjectLike(value) && reIsHostCtor.test(value);
}
-/**
- * Escapes the `RegExp` special characters "\", "/", "^", "$", ".", "|", "?",
- * "*", "+", "(", ")", "[", "]", "{" and "}" in `string`.
- *
- * @static
- * @memberOf _
- * @category String
- * @param {string} [string=''] The string to escape.
- * @returns {string} Returns the escaped string.
- * @example
- *
- * _.escapeRegExp('[lodash](https://lodash.com/)');
- * // => '\[lodash\]\(https:\/\/lodash\.com\/\)'
- */
-function escapeRegExp(string) {
- string = baseToString(string);
- return (string && reHasRegExpChars.test(string))
- ? string.replace(reRegExpChars, '\\$&')
- : string;
-}
-
module.exports = getNative;
-},{}],42:[function(require,module,exports){
+},{}],44:[function(require,module,exports){
/**
- * lodash 3.0.3 (Custom Build)
+ * lodash 3.0.4 (Custom Build)
* Build: `lodash modern modularize exports="npm" -o ./`
* Copyright 2012-2015 The Dojo Foundation
* Based on Underscore.js 1.8.3
@@ -9834,9 +10979,6 @@ module.exports = getNative;
* Available under MIT license
*/
-/** `Object#toString` result references. */
-var argsTag = '[object Arguments]';
-
/**
* Checks if `value` is object-like.
*
@@ -9851,14 +10993,14 @@ function isObjectLike(value) {
/** Used for native method references. */
var objectProto = Object.prototype;
-/**
- * Used to resolve the [`toStringTag`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring)
- * of values.
- */
-var objToString = objectProto.toString;
+/** Used to check objects for own properties. */
+var hasOwnProperty = objectProto.hasOwnProperty;
+
+/** Native method references. */
+var propertyIsEnumerable = objectProto.propertyIsEnumerable;
/**
- * Used as the [maximum length](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.max_safe_integer)
+ * Used as the [maximum length](http://ecma-international.org/ecma-262/6.0/#sec-number.max_safe_integer)
* of an array-like value.
*/
var MAX_SAFE_INTEGER = 9007199254740991;
@@ -9902,7 +11044,7 @@ function isArrayLike(value) {
/**
* Checks if `value` is a valid array-like length.
*
- * **Note:** This function is based on [`ToLength`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength).
+ * **Note:** This function is based on [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength).
*
* @private
* @param {*} value The value to check.
@@ -9929,12 +11071,80 @@ function isLength(value) {
* // => false
*/
function isArguments(value) {
- return isObjectLike(value) && isArrayLike(value) && objToString.call(value) == argsTag;
+ return isObjectLike(value) && isArrayLike(value) &&
+ hasOwnProperty.call(value, 'callee') && !propertyIsEnumerable.call(value, 'callee');
}
module.exports = isArguments;
-},{}],40:[function(require,module,exports){
+},{}],45:[function(require,module,exports){
+/**
+ * lodash 3.0.1 (Custom Build)
+ * Build: `lodash modern modularize exports="npm" -o ./`
+ * Copyright 2012-2015 The Dojo Foundation
+ * Based on Underscore.js 1.8.3
+ * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
+ * Available under MIT license
+ */
+
+/**
+ * A specialized version of `baseCallback` which only supports `this` binding
+ * and specifying the number of arguments to provide to `func`.
+ *
+ * @private
+ * @param {Function} func The function to bind.
+ * @param {*} thisArg The `this` binding of `func`.
+ * @param {number} [argCount] The number of arguments to provide to `func`.
+ * @returns {Function} Returns the callback.
+ */
+function bindCallback(func, thisArg, argCount) {
+ if (typeof func != 'function') {
+ return identity;
+ }
+ if (thisArg === undefined) {
+ return func;
+ }
+ switch (argCount) {
+ case 1: return function(value) {
+ return func.call(thisArg, value);
+ };
+ case 3: return function(value, index, collection) {
+ return func.call(thisArg, value, index, collection);
+ };
+ case 4: return function(accumulator, value, index, collection) {
+ return func.call(thisArg, accumulator, value, index, collection);
+ };
+ case 5: return function(value, other, key, object, source) {
+ return func.call(thisArg, value, other, key, object, source);
+ };
+ }
+ return function() {
+ return func.apply(thisArg, arguments);
+ };
+}
+
+/**
+ * This method returns the first argument provided to it.
+ *
+ * @static
+ * @memberOf _
+ * @category Utility
+ * @param {*} value Any value.
+ * @returns {*} Returns `value`.
+ * @example
+ *
+ * var object = { 'user': 'fred' };
+ *
+ * _.identity(object) === object;
+ * // => true
+ */
+function identity(value) {
+ return value;
+}
+
+module.exports = bindCallback;
+
+},{}],42:[function(require,module,exports){
/**
* lodash 3.0.4 (Custom Build)
* Build: `lodash modern modularize exports="npm" -o ./`
@@ -10079,114 +11289,47 @@ function isLength(value) {
/**
* Converts `value` to an object if it's not one.
- *
- * @private
- * @param {*} value The value to process.
- * @returns {Object} Returns the object.
- */
-function toObject(value) {
- return isObject(value) ? value : Object(value);
-}
-
-/**
- * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`.
- * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
- *
- * @static
- * @memberOf _
- * @category Lang
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is an object, else `false`.
- * @example
- *
- * _.isObject({});
- * // => true
- *
- * _.isObject([1, 2, 3]);
- * // => true
- *
- * _.isObject(1);
- * // => false
- */
-function isObject(value) {
- // Avoid a V8 JIT bug in Chrome 19-20.
- // See https://code.google.com/p/v8/issues/detail?id=2291 for more details.
- var type = typeof value;
- return !!value && (type == 'object' || type == 'function');
-}
-
-module.exports = baseEach;
-
-},{"lodash.keys":43}],44:[function(require,module,exports){
-/**
- * lodash 3.0.1 (Custom Build)
- * Build: `lodash modern modularize exports="npm" -o ./`
- * Copyright 2012-2015 The Dojo Foundation
- * Based on Underscore.js 1.8.3
- * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
- * Available under MIT license
- */
-
-/**
- * A specialized version of `baseCallback` which only supports `this` binding
- * and specifying the number of arguments to provide to `func`.
- *
- * @private
- * @param {Function} func The function to bind.
- * @param {*} thisArg The `this` binding of `func`.
- * @param {number} [argCount] The number of arguments to provide to `func`.
- * @returns {Function} Returns the callback.
- */
-function bindCallback(func, thisArg, argCount) {
- if (typeof func != 'function') {
- return identity;
- }
- if (thisArg === undefined) {
- return func;
- }
- switch (argCount) {
- case 1: return function(value) {
- return func.call(thisArg, value);
- };
- case 3: return function(value, index, collection) {
- return func.call(thisArg, value, index, collection);
- };
- case 4: return function(accumulator, value, index, collection) {
- return func.call(thisArg, accumulator, value, index, collection);
- };
- case 5: return function(value, other, key, object, source) {
- return func.call(thisArg, value, other, key, object, source);
- };
- }
- return function() {
- return func.apply(thisArg, arguments);
- };
+ *
+ * @private
+ * @param {*} value The value to process.
+ * @returns {Object} Returns the object.
+ */
+function toObject(value) {
+ return isObject(value) ? value : Object(value);
}
/**
- * This method returns the first argument provided to it.
+ * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`.
+ * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
*
* @static
* @memberOf _
- * @category Utility
- * @param {*} value Any value.
- * @returns {*} Returns `value`.
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is an object, else `false`.
* @example
*
- * var object = { 'user': 'fred' };
+ * _.isObject({});
+ * // => true
*
- * _.identity(object) === object;
+ * _.isObject([1, 2, 3]);
* // => true
+ *
+ * _.isObject(1);
+ * // => false
*/
-function identity(value) {
- return value;
+function isObject(value) {
+ // Avoid a V8 JIT bug in Chrome 19-20.
+ // See https://code.google.com/p/v8/issues/detail?id=2291 for more details.
+ var type = typeof value;
+ return !!value && (type == 'object' || type == 'function');
}
-module.exports = bindCallback;
+module.exports = baseEach;
-},{}],37:[function(require,module,exports){
+},{"lodash.keys":46}],39:[function(require,module,exports){
/**
- * lodash 3.1.1 (Custom Build)
+ * lodash 3.1.2 (Custom Build)
* Build: `lodash modern modularize exports="npm" -o ./`
* Copyright 2012-2015 The Dojo Foundation
* Based on Underscore.js 1.8.3
@@ -10210,7 +11353,7 @@ var hasOwnProperty = objectProto.hasOwnProperty;
var nativeKeys = getNative(Object, 'keys');
/**
- * Used as the [maximum length](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.max_safe_integer)
+ * Used as the [maximum length](http://ecma-international.org/ecma-262/6.0/#sec-number.max_safe_integer)
* of an array-like value.
*/
var MAX_SAFE_INTEGER = 9007199254740991;
@@ -10268,7 +11411,7 @@ function isIndex(value, length) {
/**
* Checks if `value` is a valid array-like length.
*
- * **Note:** This function is based on [`ToLength`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength).
+ * **Note:** This function is based on [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength).
*
* @private
* @param {*} value The value to check.
@@ -10337,7 +11480,7 @@ function isObject(value) {
* Creates an array of the own enumerable property names of `object`.
*
* **Note:** Non-object values are coerced to objects. See the
- * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.keys)
+ * [ES spec](http://ecma-international.org/ecma-262/6.0/#sec-object.keys)
* for more details.
*
* @static
@@ -10361,7 +11504,7 @@ function isObject(value) {
* // => ['0', '1']
*/
var keys = !nativeKeys ? shimKeys : function(object) {
- var Ctor = object == null ? null : object.constructor;
+ var Ctor = object == null ? undefined : object.constructor;
if ((typeof Ctor == 'function' && Ctor.prototype === object) ||
(typeof object != 'function' && isArrayLike(object))) {
return shimKeys(object);
@@ -10422,9 +11565,9 @@ function keysIn(object) {
module.exports = keys;
-},{"lodash._getnative":41,"lodash.isarguments":42,"lodash.isarray":27}],38:[function(require,module,exports){
+},{"lodash._getnative":43,"lodash.isarguments":44,"lodash.isarray":32}],41:[function(require,module,exports){
/**
- * lodash 3.3.0 (Custom Build)
+ * lodash 3.3.1 (Custom Build)
* Build: `lodash modern modularize exports="npm" -o ./`
* Copyright 2012-2015 The Dojo Foundation
* Based on Underscore.js 1.8.3
@@ -10453,9 +11596,6 @@ var reEscapeChar = /\\(\\)?/g;
* @returns {string} Returns the string.
*/
function baseToString(value) {
- if (typeof value == 'string') {
- return value;
- }
return value == null ? '' : (value + '');
}
@@ -10587,8 +11727,7 @@ function baseMatches(source) {
}
/**
- * The base implementation of `_.matchesProperty` which does not which does
- * not clone `value`.
+ * The base implementation of `_.matchesProperty` which does not clone `srcValue`.
*
* @private
* @param {string} path The path of the property to get.
@@ -10823,7 +11962,7 @@ function identity(value) {
}
/**
- * Creates a function which returns the property value at `path` on a
+ * Creates a function that returns the property value at `path` on a
* given object.
*
* @static
@@ -10850,7 +11989,7 @@ function property(path) {
module.exports = baseCallback;
-},{"lodash._baseisequal":45,"lodash._bindcallback":44,"lodash.isarray":31,"lodash.pairs":46}],47:[function(require,module,exports){
+},{"lodash._baseisequal":47,"lodash._bindcallback":45,"lodash.isarray":35,"lodash.pairs":48}],49:[function(require,module,exports){
/**
* lodash 3.0.2 (Custom Build)
* Build: `lodash modern modularize exports="npm" -o ./`
@@ -10962,9 +12101,9 @@ function isTypedArray(value) {
module.exports = isTypedArray;
-},{}],48:[function(require,module,exports){
+},{}],50:[function(require,module,exports){
/**
- * lodash 3.0.3 (Custom Build)
+ * lodash 3.9.1 (Custom Build)
* Build: `lodash modern modularize exports="npm" -o ./`
* Copyright 2012-2015 The Dojo Foundation
* Based on Underscore.js 1.8.3
@@ -10973,7 +12112,10 @@ module.exports = isTypedArray;
*/
/** `Object#toString` result references. */
-var argsTag = '[object Arguments]';
+var funcTag = '[object Function]';
+
+/** Used to detect host constructors (Safari > 5). */
+var reIsHostCtor = /^\[object .+?Constructor\]$/;
/**
* Checks if `value` is object-like.
@@ -10989,92 +12131,118 @@ function isObjectLike(value) {
/** Used for native method references. */
var objectProto = Object.prototype;
+/** Used to resolve the decompiled source of functions. */
+var fnToString = Function.prototype.toString;
+
+/** Used to check objects for own properties. */
+var hasOwnProperty = objectProto.hasOwnProperty;
+
/**
- * Used to resolve the [`toStringTag`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring)
+ * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)
* of values.
*/
var objToString = objectProto.toString;
-/**
- * Used as the [maximum length](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.max_safe_integer)
- * of an array-like value.
- */
-var MAX_SAFE_INTEGER = 9007199254740991;
+/** Used to detect if a method is native. */
+var reIsNative = RegExp('^' +
+ fnToString.call(hasOwnProperty).replace(/[\\^$.*+?()[\]{}|]/g, '\\$&')
+ .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
+);
/**
- * The base implementation of `_.property` without support for deep paths.
+ * Gets the native function at `key` of `object`.
*
* @private
- * @param {string} key The key of the property to get.
- * @returns {Function} Returns the new function.
+ * @param {Object} object The object to query.
+ * @param {string} key The key of the method to get.
+ * @returns {*} Returns the function if it's native, else `undefined`.
*/
-function baseProperty(key) {
- return function(object) {
- return object == null ? undefined : object[key];
- };
+function getNative(object, key) {
+ var value = object == null ? undefined : object[key];
+ return isNative(value) ? value : undefined;
}
/**
- * Gets the "length" property value of `object`.
+ * Checks if `value` is classified as a `Function` object.
*
- * **Note:** This function is used to avoid a [JIT bug](https://bugs.webkit.org/show_bug.cgi?id=142792)
- * that affects Safari on at least iOS 8.1-8.3 ARM64.
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+ * @example
*
- * @private
- * @param {Object} object The object to query.
- * @returns {*} Returns the "length" value.
- */
-var getLength = baseProperty('length');
-
-/**
- * Checks if `value` is array-like.
+ * _.isFunction(_);
+ * // => true
*
- * @private
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
+ * _.isFunction(/abc/);
+ * // => false
*/
-function isArrayLike(value) {
- return value != null && isLength(getLength(value));
+function isFunction(value) {
+ // The use of `Object#toString` avoids issues with the `typeof` operator
+ // in older versions of Chrome and Safari which return 'function' for regexes
+ // and Safari 8 equivalents which return 'object' for typed array constructors.
+ return isObject(value) && objToString.call(value) == funcTag;
}
/**
- * Checks if `value` is a valid array-like length.
- *
- * **Note:** This function is based on [`ToLength`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength).
+ * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`.
+ * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
*
- * @private
+ * @static
+ * @memberOf _
+ * @category Lang
* @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
+ * @returns {boolean} Returns `true` if `value` is an object, else `false`.
+ * @example
+ *
+ * _.isObject({});
+ * // => true
+ *
+ * _.isObject([1, 2, 3]);
+ * // => true
+ *
+ * _.isObject(1);
+ * // => false
*/
-function isLength(value) {
- return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
+function isObject(value) {
+ // Avoid a V8 JIT bug in Chrome 19-20.
+ // See https://code.google.com/p/v8/issues/detail?id=2291 for more details.
+ var type = typeof value;
+ return !!value && (type == 'object' || type == 'function');
}
/**
- * Checks if `value` is classified as an `arguments` object.
+ * Checks if `value` is a native function.
*
* @static
* @memberOf _
* @category Lang
* @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+ * @returns {boolean} Returns `true` if `value` is a native function, else `false`.
* @example
*
- * _.isArguments(function() { return arguments; }());
+ * _.isNative(Array.prototype.push);
* // => true
*
- * _.isArguments([1, 2, 3]);
+ * _.isNative(_);
* // => false
*/
-function isArguments(value) {
- return isObjectLike(value) && isArrayLike(value) && objToString.call(value) == argsTag;
+function isNative(value) {
+ if (value == null) {
+ return false;
+ }
+ if (isFunction(value)) {
+ return reIsNative.test(fnToString.call(value));
+ }
+ return isObjectLike(value) && reIsHostCtor.test(value);
}
-module.exports = isArguments;
+module.exports = getNative;
-},{}],49:[function(require,module,exports){
+},{}],51:[function(require,module,exports){
/**
- * lodash 3.9.0 (Custom Build)
+ * lodash 3.0.4 (Custom Build)
* Build: `lodash modern modularize exports="npm" -o ./`
* Copyright 2012-2015 The Dojo Foundation
* Based on Underscore.js 1.8.3
@@ -11082,35 +12250,6 @@ module.exports = isArguments;
* Available under MIT license
*/
-/** `Object#toString` result references. */
-var funcTag = '[object Function]';
-
-/**
- * Used to match `RegExp` [special characters](http://www.regular-expressions.info/characters.html#special).
- * In addition to special characters the forward slash is escaped to allow for
- * easier `eval` use and `Function` compilation.
- */
-var reRegExpChars = /[.*+?^${}()|[\]\/\\]/g,
- reHasRegExpChars = RegExp(reRegExpChars.source);
-
-/** Used to detect host constructors (Safari > 5). */
-var reIsHostCtor = /^\[object .+?Constructor\]$/;
-
-/**
- * Converts `value` to a string if it's not one. An empty string is returned
- * for `null` or `undefined` values.
- *
- * @private
- * @param {*} value The value to process.
- * @returns {string} Returns the string.
- */
-function baseToString(value) {
- if (typeof value == 'string') {
- return value;
- }
- return value == null ? '' : (value + '');
-}
-
/**
* Checks if `value` is object-like.
*
@@ -11125,87 +12264,91 @@ function isObjectLike(value) {
/** Used for native method references. */
var objectProto = Object.prototype;
-/** Used to resolve the decompiled source of functions. */
-var fnToString = Function.prototype.toString;
-
/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;
+/** Native method references. */
+var propertyIsEnumerable = objectProto.propertyIsEnumerable;
+
/**
- * Used to resolve the [`toStringTag`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring)
- * of values.
+ * Used as the [maximum length](http://ecma-international.org/ecma-262/6.0/#sec-number.max_safe_integer)
+ * of an array-like value.
*/
-var objToString = objectProto.toString;
+var MAX_SAFE_INTEGER = 9007199254740991;
-/** Used to detect if a method is native. */
-var reIsNative = RegExp('^' +
- escapeRegExp(fnToString.call(hasOwnProperty))
- .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
-);
+/**
+ * The base implementation of `_.property` without support for deep paths.
+ *
+ * @private
+ * @param {string} key The key of the property to get.
+ * @returns {Function} Returns the new function.
+ */
+function baseProperty(key) {
+ return function(object) {
+ return object == null ? undefined : object[key];
+ };
+}
/**
- * Gets the native function at `key` of `object`.
+ * Gets the "length" property value of `object`.
+ *
+ * **Note:** This function is used to avoid a [JIT bug](https://bugs.webkit.org/show_bug.cgi?id=142792)
+ * that affects Safari on at least iOS 8.1-8.3 ARM64.
*
* @private
* @param {Object} object The object to query.
- * @param {string} key The key of the method to get.
- * @returns {*} Returns the function if it's native, else `undefined`.
+ * @returns {*} Returns the "length" value.
*/
-function getNative(object, key) {
- var value = object == null ? undefined : object[key];
- return isNative(value) ? value : undefined;
-}
+var getLength = baseProperty('length');
/**
- * Checks if `value` is a native function.
+ * Checks if `value` is array-like.
*
- * @static
- * @memberOf _
- * @category Lang
+ * @private
* @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is a native function, else `false`.
- * @example
+ * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
+ */
+function isArrayLike(value) {
+ return value != null && isLength(getLength(value));
+}
+
+/**
+ * Checks if `value` is a valid array-like length.
*
- * _.isNative(Array.prototype.push);
- * // => true
+ * **Note:** This function is based on [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength).
*
- * _.isNative(_);
- * // => false
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
*/
-function isNative(value) {
- if (value == null) {
- return false;
- }
- if (objToString.call(value) == funcTag) {
- return reIsNative.test(fnToString.call(value));
- }
- return isObjectLike(value) && reIsHostCtor.test(value);
+function isLength(value) {
+ return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
}
/**
- * Escapes the `RegExp` special characters "\", "/", "^", "$", ".", "|", "?",
- * "*", "+", "(", ")", "[", "]", "{" and "}" in `string`.
+ * Checks if `value` is classified as an `arguments` object.
*
* @static
* @memberOf _
- * @category String
- * @param {string} [string=''] The string to escape.
- * @returns {string} Returns the escaped string.
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
* @example
*
- * _.escapeRegExp('[lodash](https://lodash.com/)');
- * // => '\[lodash\]\(https:\/\/lodash\.com\/\)'
+ * _.isArguments(function() { return arguments; }());
+ * // => true
+ *
+ * _.isArguments([1, 2, 3]);
+ * // => false
*/
-function escapeRegExp(string) {
- string = baseToString(string);
- return (string && reHasRegExpChars.test(string))
- ? string.replace(reRegExpChars, '\\$&')
- : string;
+function isArguments(value) {
+ return isObjectLike(value) && isArrayLike(value) &&
+ hasOwnProperty.call(value, 'callee') && !propertyIsEnumerable.call(value, 'callee');
}
-module.exports = getNative;
+module.exports = isArguments;
-},{}],46:[function(require,module,exports){
+},{}],48:[function(require,module,exports){
/**
* lodash 3.0.1 (Custom Build)
* Build: `lodash modern modularize exports="npm" -o ./`
@@ -11285,7 +12428,7 @@ function pairs(object) {
module.exports = pairs;
-},{"lodash.keys":43}],45:[function(require,module,exports){
+},{"lodash.keys":46}],47:[function(require,module,exports){
/**
* lodash 3.0.7 (Custom Build)
* Build: `lodash modern modularize exports="npm" -o ./`
@@ -11629,9 +12772,9 @@ function isObject(value) {
module.exports = baseIsEqual;
-},{"lodash.isarray":31,"lodash.istypedarray":47,"lodash.keys":43}],43:[function(require,module,exports){
+},{"lodash.isarray":35,"lodash.istypedarray":49,"lodash.keys":46}],46:[function(require,module,exports){
/**
- * lodash 3.1.1 (Custom Build)
+ * lodash 3.1.2 (Custom Build)
* Build: `lodash modern modularize exports="npm" -o ./`
* Copyright 2012-2015 The Dojo Foundation
* Based on Underscore.js 1.8.3
@@ -11655,7 +12798,7 @@ var hasOwnProperty = objectProto.hasOwnProperty;
var nativeKeys = getNative(Object, 'keys');
/**
- * Used as the [maximum length](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.max_safe_integer)
+ * Used as the [maximum length](http://ecma-international.org/ecma-262/6.0/#sec-number.max_safe_integer)
* of an array-like value.
*/
var MAX_SAFE_INTEGER = 9007199254740991;
@@ -11713,7 +12856,7 @@ function isIndex(value, length) {
/**
* Checks if `value` is a valid array-like length.
*
- * **Note:** This function is based on [`ToLength`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength).
+ * **Note:** This function is based on [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength).
*
* @private
* @param {*} value The value to check.
@@ -11782,7 +12925,7 @@ function isObject(value) {
* Creates an array of the own enumerable property names of `object`.
*
* **Note:** Non-object values are coerced to objects. See the
- * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.keys)
+ * [ES spec](http://ecma-international.org/ecma-262/6.0/#sec-object.keys)
* for more details.
*
* @static
@@ -11806,7 +12949,7 @@ function isObject(value) {
* // => ['0', '1']
*/
var keys = !nativeKeys ? shimKeys : function(object) {
- var Ctor = object == null ? null : object.constructor;
+ var Ctor = object == null ? undefined : object.constructor;
if ((typeof Ctor == 'function' && Ctor.prototype === object) ||
(typeof object != 'function' && isArrayLike(object))) {
return shimKeys(object);
@@ -11867,6 +13010,6 @@ function keysIn(object) {
module.exports = keys;
-},{"lodash._getnative":49,"lodash.isarguments":48,"lodash.isarray":31}]},{},[1])(1)
+},{"lodash._getnative":50,"lodash.isarguments":51,"lodash.isarray":35}]},{},[1])(1)
});
;