From 21fef57bc4d1ab6a33336ac6a8f5a1ed3f392547 Mon Sep 17 00:00:00 2001 From: hristoterezov Date: Wed, 20 May 2015 15:10:09 +0300 Subject: [PATCH] Adds config property that disables hiding of toolbar. --- index.html | 2 +- libs/app.bundle.js | 1558 ++++++++++++------------- modules/UI/toolbars/ToolbarToggler.js | 3 + 3 files changed, 742 insertions(+), 821 deletions(-) diff --git a/index.html b/index.html index f8d10c785..670a48dbc 100644 --- a/index.html +++ b/index.html @@ -19,7 +19,7 @@ - + diff --git a/libs/app.bundle.js b/libs/app.bundle.js index 1030b3000..514737391 100644 --- a/libs/app.bundle.js +++ b/libs/app.bundle.js @@ -1,4 +1,63 @@ -(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.APP = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 1) { - for (var i = 1; i < arguments.length; i++) { - args[i - 1] = arguments[i]; - } - } - queue.push(new Item(fun, args)); - if (!draining) { - setTimeout(drainQueue, 0); - } -}; - -// v8 likes predictible objects -function Item(fun, array) { - this.fun = fun; - this.array = array; -} -Item.prototype.run = function () { - this.fun.apply(null, this.array); -}; -process.title = 'browser'; -process.browser = true; -process.env = {}; -process.argv = []; -process.version = ''; // empty string to avoid regexp issues -process.versions = {}; - -function noop() {} - -process.on = noop; -process.addListener = noop; -process.once = noop; -process.off = noop; -process.removeListener = noop; -process.removeAllListeners = noop; -process.emit = noop; - -process.binding = function (name) { - throw new Error('process.binding is not supported'); -}; - -// TODO(shtylman) -process.cwd = function () { return '/' }; -process.chdir = function (dir) { - throw new Error('process.chdir is not supported'); -}; -process.umask = function() { return 0; }; - -},{}],65:[function(require,module,exports){ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -function EventEmitter() { - this._events = this._events || {}; - this._maxListeners = this._maxListeners || undefined; -} -module.exports = EventEmitter; - -// Backwards-compat with node 0.10.x -EventEmitter.EventEmitter = EventEmitter; - -EventEmitter.prototype._events = undefined; -EventEmitter.prototype._maxListeners = undefined; - -// By default EventEmitters will print a warning if more than 10 listeners are -// added to it. This is a useful default which helps finding memory leaks. -EventEmitter.defaultMaxListeners = 10; - -// Obviously not all Emitters should be limited to 10. This function allows -// that to be increased. Set to zero for unlimited. -EventEmitter.prototype.setMaxListeners = function(n) { - if (!isNumber(n) || n < 0 || isNaN(n)) - throw TypeError('n must be a positive number'); - this._maxListeners = n; - return this; -}; - -EventEmitter.prototype.emit = function(type) { - var er, handler, len, args, i, listeners; - - if (!this._events) - this._events = {}; - - // If there is no 'error' event listener then throw. - if (type === 'error') { - if (!this._events.error || - (isObject(this._events.error) && !this._events.error.length)) { - er = arguments[1]; - if (er instanceof Error) { - throw er; // Unhandled 'error' event - } - throw TypeError('Uncaught, unspecified "error" event.'); - } - } - - handler = this._events[type]; - - if (isUndefined(handler)) - return false; - - if (isFunction(handler)) { - switch (arguments.length) { - // fast cases - case 1: - handler.call(this); - break; - case 2: - handler.call(this, arguments[1]); - break; - case 3: - handler.call(this, arguments[1], arguments[2]); - break; - // slower - default: - len = arguments.length; - args = new Array(len - 1); - for (i = 1; i < len; i++) - args[i - 1] = arguments[i]; - handler.apply(this, args); - } - } else if (isObject(handler)) { - len = arguments.length; - args = new Array(len - 1); - for (i = 1; i < len; i++) - args[i - 1] = arguments[i]; - - listeners = handler.slice(); - len = listeners.length; - for (i = 0; i < len; i++) - listeners[i].apply(this, args); - } - - return true; -}; - -EventEmitter.prototype.addListener = function(type, listener) { - var m; - - if (!isFunction(listener)) - throw TypeError('listener must be a function'); - - if (!this._events) - this._events = {}; - - // To avoid recursion in the case that type === "newListener"! Before - // adding it to the listeners, first emit "newListener". - if (this._events.newListener) - this.emit('newListener', type, - isFunction(listener.listener) ? - listener.listener : listener); - - if (!this._events[type]) - // Optimize the case of one listener. Don't need the extra array object. - this._events[type] = listener; - else if (isObject(this._events[type])) - // If we've already got an array, just append. - this._events[type].push(listener); - else - // Adding the second element, need to change to array. - this._events[type] = [this._events[type], listener]; - - // Check for listener leak - if (isObject(this._events[type]) && !this._events[type].warned) { - var m; - if (!isUndefined(this._maxListeners)) { - m = this._maxListeners; - } else { - m = EventEmitter.defaultMaxListeners; - } - - if (m && m > 0 && this._events[type].length > m) { - this._events[type].warned = true; - console.error('(node) warning: possible EventEmitter memory ' + - 'leak detected. %d listeners added. ' + - 'Use emitter.setMaxListeners() to increase limit.', - this._events[type].length); - if (typeof console.trace === 'function') { - // not supported in IE 10 - console.trace(); - } - } - } - - return this; -}; - -EventEmitter.prototype.on = EventEmitter.prototype.addListener; - -EventEmitter.prototype.once = function(type, listener) { - if (!isFunction(listener)) - throw TypeError('listener must be a function'); - - var fired = false; - - function g() { - this.removeListener(type, g); - - if (!fired) { - fired = true; - listener.apply(this, arguments); - } - } - - g.listener = listener; - this.on(type, g); - - return this; -}; - -// emits a 'removeListener' event iff the listener was removed -EventEmitter.prototype.removeListener = function(type, listener) { - var list, position, length, i; - - if (!isFunction(listener)) - throw TypeError('listener must be a function'); - - if (!this._events || !this._events[type]) - return this; - - list = this._events[type]; - length = list.length; - position = -1; - - if (list === listener || - (isFunction(list.listener) && list.listener === listener)) { - delete this._events[type]; - if (this._events.removeListener) - this.emit('removeListener', type, listener); - - } else if (isObject(list)) { - for (i = length; i-- > 0;) { - if (list[i] === listener || - (list[i].listener && list[i].listener === listener)) { - position = i; - break; - } - } - - if (position < 0) - return this; - - if (list.length === 1) { - list.length = 0; - delete this._events[type]; - } else { - list.splice(position, 1); - } - - if (this._events.removeListener) - this.emit('removeListener', type, listener); - } - - return this; -}; - -EventEmitter.prototype.removeAllListeners = function(type) { - var key, listeners; - - if (!this._events) - return this; - - // not listening for removeListener, no need to emit - if (!this._events.removeListener) { - if (arguments.length === 0) - this._events = {}; - else if (this._events[type]) - delete this._events[type]; - return this; - } - - // emit removeListener for all listeners on all events - if (arguments.length === 0) { - for (key in this._events) { - if (key === 'removeListener') continue; - this.removeAllListeners(key); - } - this.removeAllListeners('removeListener'); - this._events = {}; - return this; - } - - listeners = this._events[type]; - - if (isFunction(listeners)) { - this.removeListener(type, listeners); - } else { - // LIFO order - while (listeners.length) - this.removeListener(type, listeners[listeners.length - 1]); - } - delete this._events[type]; - - return this; -}; - -EventEmitter.prototype.listeners = function(type) { - var ret; - if (!this._events || !this._events[type]) - ret = []; - else if (isFunction(this._events[type])) - ret = [this._events[type]]; - else - ret = this._events[type].slice(); - return ret; -}; - -EventEmitter.listenerCount = function(emitter, type) { - var ret; - if (!emitter._events || !emitter._events[type]) - ret = 0; - else if (isFunction(emitter._events[type])) - ret = 1; - else - ret = emitter._events[type].length; - return ret; -}; - -function isFunction(arg) { - return typeof arg === 'function'; -} - -function isNumber(arg) { - return typeof arg === 'number'; -} - -function isObject(arg) { - return typeof arg === 'object' && arg !== null; -} - -function isUndefined(arg) { - return arg === void 0; -} - -},{}],66:[function(require,module,exports){ +},{"_process":106}],65:[function(require,module,exports){ // i18next, v1.7.7 // Copyright (c)2014 Jan Mühlemann (jamuhl). // Distributed under MIT license @@ -21595,7 +21262,7 @@ function isUndefined(arg) { i18n.options = o; })(); -},{"jquery":"jquery"}],67:[function(require,module,exports){ +},{"jquery":"jquery"}],66:[function(require,module,exports){ // Top level file is just a mixin of submodules & constants 'use strict'; @@ -21610,7 +21277,7 @@ var pako = {}; assign(pako, deflate, inflate, constants); module.exports = pako; -},{"./lib/deflate":68,"./lib/inflate":69,"./lib/utils/common":70,"./lib/zlib/constants":73}],68:[function(require,module,exports){ +},{"./lib/deflate":67,"./lib/inflate":68,"./lib/utils/common":69,"./lib/zlib/constants":72}],67:[function(require,module,exports){ 'use strict'; @@ -21975,7 +21642,7 @@ exports.Deflate = Deflate; exports.deflate = deflate; exports.deflateRaw = deflateRaw; exports.gzip = gzip; -},{"./utils/common":70,"./utils/strings":71,"./zlib/deflate.js":75,"./zlib/messages":80,"./zlib/zstream":82}],69:[function(require,module,exports){ +},{"./utils/common":69,"./utils/strings":70,"./zlib/deflate.js":74,"./zlib/messages":79,"./zlib/zstream":81}],68:[function(require,module,exports){ 'use strict'; @@ -22344,7 +22011,7 @@ exports.inflate = inflate; exports.inflateRaw = inflateRaw; exports.ungzip = inflate; -},{"./utils/common":70,"./utils/strings":71,"./zlib/constants":73,"./zlib/gzheader":76,"./zlib/inflate.js":78,"./zlib/messages":80,"./zlib/zstream":82}],70:[function(require,module,exports){ +},{"./utils/common":69,"./utils/strings":70,"./zlib/constants":72,"./zlib/gzheader":75,"./zlib/inflate.js":77,"./zlib/messages":79,"./zlib/zstream":81}],69:[function(require,module,exports){ 'use strict'; @@ -22447,7 +22114,7 @@ exports.setTyped = function (on) { }; exports.setTyped(TYPED_OK); -},{}],71:[function(require,module,exports){ +},{}],70:[function(require,module,exports){ // String encode/decode helpers 'use strict'; @@ -22634,7 +22301,7 @@ exports.utf8border = function(buf, max) { return (pos + _utf8len[buf[pos]] > max) ? pos : max; }; -},{"./common":70}],72:[function(require,module,exports){ +},{"./common":69}],71:[function(require,module,exports){ 'use strict'; // Note: adler32 takes 12% for level 0 and 2% for level 6. @@ -22667,7 +22334,7 @@ function adler32(adler, buf, len, pos) { module.exports = adler32; -},{}],73:[function(require,module,exports){ +},{}],72:[function(require,module,exports){ module.exports = { /* Allowed flush values; see deflate() and inflate() below for details */ @@ -22715,7 +22382,7 @@ module.exports = { Z_DEFLATED: 8 //Z_NULL: null // Use -1 or null inline, depending on var type }; -},{}],74:[function(require,module,exports){ +},{}],73:[function(require,module,exports){ 'use strict'; // Note: we can't get significant speed boost here. @@ -22757,7 +22424,7 @@ function crc32(crc, buf, len, pos) { module.exports = crc32; -},{}],75:[function(require,module,exports){ +},{}],74:[function(require,module,exports){ 'use strict'; var utils = require('../utils/common'); @@ -24523,7 +24190,7 @@ exports.deflatePending = deflatePending; exports.deflatePrime = deflatePrime; exports.deflateTune = deflateTune; */ -},{"../utils/common":70,"./adler32":72,"./crc32":74,"./messages":80,"./trees":81}],76:[function(require,module,exports){ +},{"../utils/common":69,"./adler32":71,"./crc32":73,"./messages":79,"./trees":80}],75:[function(require,module,exports){ 'use strict'; @@ -24564,7 +24231,7 @@ function GZheader() { } module.exports = GZheader; -},{}],77:[function(require,module,exports){ +},{}],76:[function(require,module,exports){ 'use strict'; // See state defs from inflate.js @@ -24891,7 +24558,7 @@ module.exports = function inflate_fast(strm, start) { return; }; -},{}],78:[function(require,module,exports){ +},{}],77:[function(require,module,exports){ 'use strict'; @@ -26395,7 +26062,7 @@ exports.inflateSync = inflateSync; exports.inflateSyncPoint = inflateSyncPoint; exports.inflateUndermine = inflateUndermine; */ -},{"../utils/common":70,"./adler32":72,"./crc32":74,"./inffast":77,"./inftrees":79}],79:[function(require,module,exports){ +},{"../utils/common":69,"./adler32":71,"./crc32":73,"./inffast":76,"./inftrees":78}],78:[function(require,module,exports){ 'use strict'; @@ -26722,7 +26389,7 @@ module.exports = function inflate_table(type, lens, lens_index, codes, table, ta return 0; }; -},{"../utils/common":70}],80:[function(require,module,exports){ +},{"../utils/common":69}],79:[function(require,module,exports){ 'use strict'; module.exports = { @@ -26736,7 +26403,7 @@ module.exports = { '-5': 'buffer error', /* Z_BUF_ERROR (-5) */ '-6': 'incompatible version' /* Z_VERSION_ERROR (-6) */ }; -},{}],81:[function(require,module,exports){ +},{}],80:[function(require,module,exports){ 'use strict'; @@ -27936,7 +27603,7 @@ exports._tr_stored_block = _tr_stored_block; exports._tr_flush_block = _tr_flush_block; exports._tr_tally = _tr_tally; exports._tr_align = _tr_align; -},{"../utils/common":70}],82:[function(require,module,exports){ +},{"../utils/common":69}],81:[function(require,module,exports){ 'use strict'; @@ -27966,9 +27633,9 @@ function ZStream() { } module.exports = ZStream; -},{}],83:[function(require,module,exports){ +},{}],82:[function(require,module,exports){ module.exports = require('./lib/retry'); -},{"./lib/retry":84}],84:[function(require,module,exports){ +},{"./lib/retry":83}],83:[function(require,module,exports){ var RetryOperation = require('./retry_operation'); exports.operation = function(options) { @@ -28019,7 +27686,7 @@ exports._createTimeout = function(attempt, opts) { return timeout; }; -},{"./retry_operation":85}],85:[function(require,module,exports){ +},{"./retry_operation":84}],84:[function(require,module,exports){ function RetryOperation(timeouts) { this._timeouts = timeouts; this._fn = null; @@ -28129,7 +27796,7 @@ RetryOperation.prototype.mainError = function() { return mainError; }; -},{}],86:[function(require,module,exports){ +},{}],85:[function(require,module,exports){ module.exports = function arrayEquals(array) { // if the other array is a falsy value, return if (!array) @@ -28155,32 +27822,27 @@ module.exports = function arrayEquals(array) { } -},{}],87:[function(require,module,exports){ +},{}],86:[function(require,module,exports){ exports.Interop = require('./interop'); -},{"./interop":88}],88:[function(require,module,exports){ -"use strict"; - +},{"./interop":87}],87:[function(require,module,exports){ var transform = require('./transform'); var arrayEquals = require('./array-equals'); -function Interop() { - - /** - * This map holds the most recent Unified Plan offer/answer SDP that was - * converted to Plan B, with the SDP type ('offer' or 'answer') as keys and - * the SDP string as values. - * - * @type {{}} - */ - this.cache = {}; -} - +function Interop() { } module.exports = Interop; +/** + * This map holds the most recent Plan A offer/answer SDP that was converted + * to Plan B, with the SDP type ('offer' or 'answer') as keys and the SDP + * string as values. + * + * @type {{}} + */ +var cache = {}; /** - * This method transforms a Unified Plan SDP to an equivalent Plan B SDP. A + * This method transforms a Plan A SDP to an equivalent Plan B SDP. A * PeerConnection wrapper transforms the SDP to Plan B before passing it to the * application. * @@ -28207,116 +27869,110 @@ Interop.prototype.toPlanB = function(desc) { return desc; } - // Try some heuristics to "make sure" this is a Unified Plan SDP. Plan B - // SDP has a video, an audio and a data "channel" at most. + // Try some heuristics to "make sure" this is a Plan A SDP. Plan B SDP has + // a video, an audio and a data "channel" at most. if (session.media.length <= 3 && session.media.every(function(m) { return ['video', 'audio', 'data'].indexOf(m.mid) !== -1; })) { - console.warn('This description does not look like Unified Plan.'); + console.warn('This description does not look like Plan A.'); return desc; } //#endregion - // Unified Plan SDP is our "precious". Cache it for later use in the Plan B - // -> Unified Plan transformation. - this.cache[desc.type] = desc.sdp; + // Plan A SDP is our "precious". Cache it for later use in the Plan B -> + // Plan A transformation. + cache[desc.type] = desc.sdp; - //#region Convert from Unified Plan to Plan B. + //#region Convert from Plan A to Plan B. // We rebuild the session.media array. var media = session.media; session.media = []; // Associative array that maps channel types to channel objects for fast - // access to channel objects by their type, e.g. type2bl['audio']->channel + // access to channel objects by their type, e.g. channels['audio']->channel // obj. - var type2bl = {}; + var channels = {}; // Used to build the group:BUNDLE value after the channels construction // loop. var types = []; - // Implode the Unified Plan m-lines/tracks into Plan B channels. - media.forEach(function(unifiedLine) { + // Implode the Plan A m-lines/tracks into Plan B "channels". + media.forEach(function(mLine) { // rtcp-mux is required in the Plan B SDP. - if ((typeof unifiedLine.rtcpMux !== 'string' || - unifiedLine.rtcpMux !== 'rtcp-mux') && - unifiedLine.direction !== 'inactive') { + if (typeof mLine.rtcpMux !== 'string' || + mLine.rtcpMux !== 'rtcp-mux') { throw new Error('Cannot convert to Plan B because m-lines ' + 'without the rtcp-mux attribute were found.'); } - // If we don't have a channel for this unifiedLine.type, then use this unifiedLine + // If we don't have a channel for this mLine.type, then use this mLine // as the channel basis. - if (typeof type2bl[unifiedLine.type] === 'undefined') { - type2bl[unifiedLine.type] = unifiedLine; + if (typeof channels[mLine.type] === 'undefined') { + channels[mLine.type] = mLine; } // Add sources to the channel and handle a=msid. - if (typeof unifiedLine.sources === 'object') { - Object.keys(unifiedLine.sources).forEach(function(ssrc) { - if (typeof type2bl[unifiedLine.type].sources !== 'object') - type2bl[unifiedLine.type].sources = {}; - + if (typeof mLine.sources === 'object') { + Object.keys(mLine.sources).forEach(function(ssrc) { // Assign the sources to the channel. - type2bl[unifiedLine.type].sources[ssrc] = unifiedLine.sources[ssrc]; + channels[mLine.type].sources[ssrc] = mLine.sources[ssrc]; + + // In Plan B the msid is an SSRC attribute. Also, we don't care + // about the obsolete label and mslabel attributes. + channels[mLine.type].sources[ssrc].msid = mLine.msid; - if (typeof unifiedLine.msid !== 'undefined') { - // In Plan B the msid is an SSRC attribute. Also, we don't - // care about the obsolete label and mslabel attributes. - // - // Note that it is not guaranteed that the unifiedLine will have - // an msid. recvonly channels in particular don't have one. - type2bl[unifiedLine.type].sources[ssrc].msid = unifiedLine.msid; - } // NOTE ssrcs in ssrc groups will share msids, as // draft-uberti-rtcweb-plan-00 mandates. }); } // Add ssrc groups to the channel. - if (typeof unifiedLine.ssrcGroups !== 'undefined' && - Array.isArray(unifiedLine.ssrcGroups)) { + if (typeof mLine.ssrcGroups !== 'undefined' && + Array.isArray(mLine.ssrcGroups)) { // Create the ssrcGroups array, if it's not defined. - if (typeof type2bl[unifiedLine.type].ssrcGroups === 'undefined' || - !Array.isArray(type2bl[unifiedLine.type].ssrcGroups)) { - type2bl[unifiedLine.type].ssrcGroups = []; + if (typeof channel.ssrcGroups === 'undefined' || + !Array.isArray(channel.ssrcGroups)) { + channel.ssrcGroups = []; } - type2bl[unifiedLine.type].ssrcGroups = type2bl[unifiedLine.type].ssrcGroups.concat(unifiedLine.ssrcGroups); + channel.ssrcGroups = channel.ssrcGroups.concat(mLine.ssrcGroups); } - if (type2bl[unifiedLine.type] === unifiedLine) { + if (channels[mLine.type] === mLine) { // Copy ICE related stuff from the principal media line. - unifiedLine.candidates = media[0].candidates; - unifiedLine.iceUfrag = media[0].iceUfrag; - unifiedLine.icePwd = media[0].icePwd; - unifiedLine.fingerprint = media[0].fingerprint; + mLine.candidates = media[0].candidates; + mLine.iceUfrag = media[0].iceUfrag; + mLine.icePwd = media[0].icePwd; + mLine.fingerprint = media[0].fingerprint; // Plan B mids are in ['audio', 'video', 'data'] - unifiedLine.mid = unifiedLine.type; + mLine.mid = mLine.type; // Plan B doesn't support/need the bundle-only attribute. - delete unifiedLine.bundleOnly; + delete mLine.bundleOnly; // In Plan B the msid is an SSRC attribute. - delete unifiedLine.msid; + delete mLine.msid; // Used to build the group:BUNDLE value after this loop. - types.push(unifiedLine.type); + types.push(mLine.type); // Add the channel to the new media array. - session.media.push(unifiedLine); + session.media.push(mLine); } }); // We regenerate the BUNDLE group with the new mids. - session.groups.some(function(group) { + session.groups.every(function(group) { if (group.type === 'BUNDLE') { group.mids = types.join(' '); + return false; + } else { return true; } }); @@ -28338,14 +27994,13 @@ Interop.prototype.toPlanB = function(desc) { }; /** - * This method transforms a Plan B SDP to an equivalent Unified Plan SDP. A - * PeerConnection wrapper transforms the SDP to Unified Plan before passing it - * to FF. + * This method transforms a Plan B SDP to an equivalent Plan A SDP. A + * PeerConnection wrapper transforms the SDP to Plan A before passing it to FF. * * @param desc * @returns {*} */ -Interop.prototype.toUnifiedPlan = function(desc) { +Interop.prototype.toPlanA = function(desc) { //#region Preliminary input validation. @@ -28373,7 +28028,7 @@ Interop.prototype.toUnifiedPlan = function(desc) { return desc; } - // Make sure this Plan B SDP can be converted to a Unified Plan SDP. + // Make sure this Plan B SDP can be converted to a Plan A SDP. var mids = []; session.media.forEach(function(m) { mids.push(m.mid); @@ -28389,74 +28044,73 @@ Interop.prototype.toUnifiedPlan = function(desc) { } if (!hasBundle) { - throw new Error("Cannot convert to Unified Plan because m-lines that" + - " are not bundled were found."); + throw new Error("Cannot convert to Plan A because m-lines that are " + + "not bundled were found."); } //#endregion - //#region Convert from Plan B to Unified Plan. + //#region Convert from Plan B to Plan A. // Unfortunately, a Plan B offer/answer doesn't have enough information to - // rebuild an equivalent Unified Plan offer/answer. + // rebuild an equivalent Plan A offer/answer. // - // For example, if this is a local answer (in Unified Plan style) that we - // convert to Plan B prior to handing it over to the application (the + // For example, if this is a local answer (in Plan A style) that we convert + // to Plan B prior to handing it over to the application (the // PeerConnection wrapper called us, for instance, after a successful // createAnswer), we want to remember the m-line at which we've seen the // (local) SSRC. That's because when the application wants to do call the // SLD method, forcing us to do the inverse transformation (from Plan B to - // Unified Plan), we need to know to which m-line to assign the (local) - // SSRC. We also need to know all the other m-lines that the original - // answer had and include them in the transformed answer as well. + // Plan A), we need to know to which m-line to assign the (local) SSRC. We + // also need to know all the other m-lines that the original answer had and + // include them in the transformed answer as well. // // Another example is if this is a remote offer that we convert to Plan B // prior to giving it to the application, we want to remember the mid at // which we've seen the (remote) SSRC. // - // In the iteration that follows, we use the cached Unified Plan (if it - // exists) to assign mids to ssrcs. + // In the iteration that follows, we use the cached Plan A (if it exists) + // to assign mids to ssrcs. var cached; - if (typeof this.cache[desc.type] !== 'undefined') { - cached = transform.parse(this.cache[desc.type]); + if (typeof cache[desc.type] !== 'undefined') { + cached = transform.parse(cache[desc.type]); } // A helper map that sends mids to m-line objects. We use it later to - // rebuild the Unified Plan style session.media array. - var mid2ul = {}; - session.media.forEach(function(bLine) { - if ((typeof bLine.rtcpMux !== 'string' || - bLine.rtcpMux !== 'rtcp-mux') && - bLine.direction !== 'inactive') { - throw new Error("Cannot convert to Unified Plan because m-lines " + + // rebuild the Plan A style session.media array. + var media = {}; + session.media.forEach(function(channel) { + if (typeof channel.rtcpMux !== 'string' || + channel.rtcpMux !== 'rtcp-mux') { + throw new Error("Cannot convert to Plan A because m-lines " + "without the rtcp-mux attribute were found."); } // With rtcp-mux and bundle all the channels should have the same ICE // stuff. - var sources = bLine.sources; - var ssrcGroups = bLine.ssrcGroups; - var candidates = bLine.candidates; - var iceUfrag = bLine.iceUfrag; - var icePwd = bLine.icePwd; - var fingerprint = bLine.fingerprint; - var port = bLine.port; + var sources = channel.sources; + var ssrcGroups = channel.ssrcGroups; + var candidates = channel.candidates; + var iceUfrag = channel.iceUfrag; + var icePwd = channel.icePwd; + var fingerprint = channel.fingerprint; + var port = channel.port; - // We'll use the "bLine" object as a prototype for each new "mLine" + // We'll use the "channel" object as a prototype for each new "mLine" // that we create, but first we need to clean it up a bit. - delete bLine.sources; - delete bLine.ssrcGroups; - delete bLine.candidates; - delete bLine.iceUfrag; - delete bLine.icePwd; - delete bLine.fingerprint; - delete bLine.port; - delete bLine.mid; + delete channel.sources; + delete channel.ssrcGroups; + delete channel.candidates; + delete channel.iceUfrag; + delete channel.icePwd; + delete channel.fingerprint; + delete channel.port; + delete channel.mid; // inverted ssrc group map - var ssrc2group = {}; + var invertedGroups = {}; if (typeof ssrcGroups !== 'undefined' && Array.isArray(ssrcGroups)) { ssrcGroups.forEach(function (ssrcGroup) { @@ -28469,114 +28123,105 @@ Interop.prototype.toUnifiedPlan = function(desc) { if (typeof ssrcGroup.ssrcs !== 'undefined' && Array.isArray(ssrcGroup.ssrcs)) { ssrcGroup.ssrcs.forEach(function (ssrc) { - if (typeof ssrc2group[ssrc] === 'undefined') { - ssrc2group[ssrc] = []; + if (typeof invertedGroups[ssrc] === 'undefined') { + invertedGroups[ssrc] = []; } - ssrc2group[ssrc].push(ssrcGroup); + invertedGroups[ssrc].push(ssrcGroup); }); } }); } // ssrc to m-line index. - var ssrc2ml = {}; + var mLines = {}; if (typeof sources === 'object') { // Explode the Plan B channel sources with one m-line per source. Object.keys(sources).forEach(function(ssrc) { - // The (unified) m-line for this SSRC. We either create it from - // scratch or, if it's a grouped SSRC, we re-use a related - // mline. In other words, if the source is grouped with another - // source, put the two together in the same m-line. - var unifiedLine; - if (typeof ssrc2group[ssrc] !== 'undefined' && - Array.isArray(ssrc2group[ssrc])) { - ssrc2group[ssrc].some(function (ssrcGroup) { + var mLine; + if (typeof invertedGroups[ssrc] !== 'undefined' && + Array.isArray(invertedGroups[ssrc])) { + invertedGroups[ssrc].every(function (ssrcGroup) { // ssrcGroup.ssrcs *is* an Array, no need to check // again here. - return ssrcGroup.ssrcs.some(function (related) { - if (typeof ssrc2ml[related] === 'object') { - unifiedLine = ssrc2ml[related]; + return ssrcGroup.ssrcs.every(function (related) { + if (typeof mLines[related] === 'object') { + mLine = mLines[related]; + return false; + } else { return true; } }); }); } - if (typeof unifiedLine === 'object') { + if (typeof mLine === 'object') { // the m-line already exists. Just add the source. - unifiedLine.sources[ssrc] = sources[ssrc]; + mLine.sources[ssrc] = sources[ssrc]; delete sources[ssrc].msid; } else { - // Use the "bLine" as a prototype for the "unifiedLine". - unifiedLine = Object.create(bLine); - ssrc2ml[ssrc] = unifiedLine; + // Use the "channel" as a prototype for the "mLine". + mLine = Object.create(channel); + mLines[ssrc] = mLine; - if (typeof sources[ssrc].msid !== 'undefined') { - // Assign the msid of the source to the m-line. Note - // that it is not guaranteed that the source will have - // msid. In particular "recvonly" sources don't have an - // msid. Note that "recvonly" is a term only defined - // for m-lines. - unifiedLine.msid = sources[ssrc].msid; - delete sources[ssrc].msid; - } + // Assign the msid of the source to the m-line. + mLine.msid = sources[ssrc].msid; + delete sources[ssrc].msid; - // We assign one SSRC per media line. - unifiedLine.sources = {}; - unifiedLine.sources[ssrc] = sources[ssrc]; - unifiedLine.ssrcGroups = ssrc2group[ssrc]; + // We assign one SSRC per media line. + mLine.sources = {}; + mLine.sources[ssrc] = sources[ssrc]; + mLine.ssrcGroups = invertedGroups[ssrc]; - // Use the cached Unified Plan SDP (if it exists) to assign - // SSRCs to mids. - if (typeof cached !== 'undefined' && - typeof cached.media !== 'undefined' && - Array.isArray(cached.media)) { + // Use the cached Plan A SDP (if it exists) to assign SSRCs to + // mids. + if (typeof cached !== 'undefined' && + typeof cached.media !== 'undefined' && + Array.isArray(cached.media)) { - cached.media.forEach(function (m) { - if (typeof m.sources === 'object') { - Object.keys(m.sources).forEach(function (s) { - if (s === ssrc) { - unifiedLine.mid = m.mid; - } - }); - } - }); - } - - if (typeof unifiedLine.mid === 'undefined') { - - // If this is an SSRC that we see for the first time - // assign it a new mid. This is typically the case when - // this method is called to transform a remote - // description for the first time or when there is a - // new SSRC in the remote description because a new - // peer has joined the conference. Local SSRCs should - // have already been added to the map in the toPlanB - // method. - // - // Because FF generates answers in Unified Plan style, - // we MUST already have a cached answer with all the - // local SSRCs mapped to some m-line/mid. - - if (desc.type === 'answer') { - throw new Error("An unmapped SSRC was found."); + cached.media.forEach(function(m) { + if (typeof m.sources === 'object') { + Object.keys(m.sources).forEach(function(s) { + if (s === ssrc) { + mLine.mid = m.mid; + } + }); } + }); + } - unifiedLine.mid = [bLine.type, '-', ssrc].join(''); + if (typeof mLine.mid === 'undefined') { + + // If this is an SSRC that we see for the first time assign + // it a new mid. This is typically the case when this + // method is called to transform a remote description for + // the first time or when there is a new SSRC in the remote + // description because a new peer has joined the + // conference. Local SSRCs should have already been added + // to the map in the toPlanB method. + // + // Because FF generates answers in Plan A style, we MUST + // already have a cached answer with all the local SSRCs + // mapped to some mLine/mid. + + if (desc.type === 'answer') { + throw new Error("An unmapped SSRC was found."); } - // Include the candidates in the 1st media line. - unifiedLine.candidates = candidates; - unifiedLine.iceUfrag = iceUfrag; - unifiedLine.icePwd = icePwd; - unifiedLine.fingerprint = fingerprint; - unifiedLine.port = port; + mLine.mid = [channel.type, '-', ssrc].join(''); + } - mid2ul[unifiedLine.mid] = unifiedLine; + // Include the candidates in the 1st media line. + mLine.candidates = candidates; + mLine.iceUfrag = iceUfrag; + mLine.icePwd = icePwd; + mLine.fingerprint = fingerprint; + mLine.port = port; + + media[mLine.mid] = mLine; } }); } @@ -28590,57 +28235,54 @@ Interop.prototype.toUnifiedPlan = function(desc) { if (desc.type === 'answer') { // The media lines in the answer must match the media lines in the - // offer. The order is important too. Here we assume that Firefox is the - // answerer, so we merely have to use the reconstructed (unified) answer - // to update the cached (unified) answer accordingly. - // - // In the general case, one would have to use the cached (unified) offer - // to find the m-lines that are missing from the reconstructed answer, - // potentially grabbing them from the cached (unified) answer. One has - // to be carefull with this approach because inactive m-lines do not - // always have an mid, making it tricky (impossible?) to find where - // exactly and which m-lines are missing from the reconstructed answer. + // offer. The order is important too. Here we use the cached offer to + // find the m-lines that are missing (from the converted answer), and + // use the cached answer to complete the converted answer. - for (var i = 0; i < cached.media.length; i++) { - var unifiedLine = cached.media[i]; - - if (typeof mid2ul[unifiedLine.mid] === 'undefined') { - - // The mid isn't in the reconstructed (unified) answer. - // This is either a (unified) m-line containing a remote - // track only, or a (unified) m-line containing a remote - // track and a local track that has been removed. - // In either case, it MUST exist in the cached - // (unified) answer. - // - // In case this is a removed local track, clean-up - // the (unified) m-line and make sure it's 'recvonly' or - // 'inactive'. - - delete unifiedLine.msid; - delete unifiedLine.sources; - delete unifiedLine.ssrcGroups; - if (!unifiedLine.direction - || unifiedLine.direction === 'sendrecv') - unifiedLine.direction = 'recvonly'; - if (!unifiedLine.direction - || unifiedLine.direction === 'sendonly') - unifiedLine.direction = 'inactive'; - } else { - // This is an (unified) m-line/channel that contains a local - // track (sendrecv or sendonly channel) or it's a unified - // recvonly m-line/channel. In either case, since we're - // going from PlanB -> Unified Plan this m-line MUST - // exist in the cached answer. - } - - session.media.push(unifiedLine); - - if (typeof unifiedLine.mid === 'string') { - // inactive lines don't/may not have an mid. - mids.push(unifiedLine.mid); - } + if (typeof cache['offer'] === 'undefined') { + throw new Error("An answer is being processed but we couldn't " + + "find a cached offer."); } + + var cachedOffer = transform.parse(cache['offer']); + + if (typeof cachedOffer === 'undefined' || + typeof cachedOffer.media === 'undefined' || + !Array.isArray(cachedOffer.media)) { + // FIXME(gp) is this really a problem in the general case? + throw new Error("The cached offer has no media."); + } + + cachedOffer.media.forEach(function(mo) { + + var mLine; + if (typeof media[mo.mid] === 'undefined') { + + // This is probably an m-line containing a remote track only. + // It MUST exist in the cached answer as a remote track only + // mLine. + + cached.media.every(function(ma) { + if (mo.mid == ma.mid) { + mLine = ma; + return false; + } else { + return true; + } + }); + } else { + mLine = media[mo.mid]; + } + + if (typeof mLine === 'undefined') { + throw new Error("The cached offer contains an m-line that " + + "doesn't exist neither in the cached answer nor in " + + "the converted answer."); + } + + session.media.push(mLine); + mids.push(mLine.mid); + }); } else { // SDP offer/answer (and the JSEP spec) forbids removing an m-section @@ -28654,57 +28296,35 @@ Interop.prototype.toUnifiedPlan = function(desc) { if (typeof cached !== 'undefined' && typeof cached.media !== 'undefined' && Array.isArray(cached.media)) { - cached.media.forEach(function(unifiedLine) { - mids.push(unifiedLine.mid); - if (typeof mid2ul[unifiedLine.mid] !== 'undefined') { - session.media.push(mid2ul[unifiedLine.mid]); + cached.media.forEach(function(pm) { + mids.push(pm.mid); + if (typeof media[pm.mid] !== 'undefined') { + session.media.push(media[pm.mid]); } else { - delete unifiedLine.msid; - delete unifiedLine.sources; - delete unifiedLine.ssrcGroups; - if (!unifiedLine.direction - || unifiedLine.direction === 'sendrecv') - unifiedLine.direction = 'recvonly'; - if (!unifiedLine.direction - || unifiedLine.direction === 'sendonly') - unifiedLine.direction = 'inactive'; - session.media.push(unifiedLine); + delete pm.msid; + delete pm.sources; + delete pm.ssrcGroups; + pm.direction = 'recvonly'; + session.media.push(pm); } }); } // Add all the remaining (new) m-lines of the transformed SDP. - Object.keys(mid2ul).forEach(function(mid) { + Object.keys(media).forEach(function(mid) { if (mids.indexOf(mid) === -1) { mids.push(mid); - if (typeof mid2ul[mid].direction === 'recvonly') { - // This is a remote recvonly channel. Add its SSRC to the - // appropriate sendrecv or sendonly channel. - // TODO(gp) what if we don't have sendrecv/sendonly channel? - session.media.some(function (unifiedLine) { - if ((unifiedLine.direction === 'sendrecv' || - unifiedLine.direction === 'sendonly') && - unifiedLine.type === mid2ul[mid].type) { - - // mid2ul[mid] shouldn't have any ssrc-groups - Object.keys(mid2ul[mid].sources).forEach(function (ssrc) { - unifiedLine.sources[ssrc] = mid2ul[mid].sources[ssrc]; - }); - - return true; - } - }); - } else { - session.media.push(mid2ul[mid]); - } + session.media.push(media[mid]); } }); } // We regenerate the BUNDLE group (since we regenerated the mids) - session.groups.some(function(group) { + session.groups.every(function(group) { if (group.type === 'BUNDLE') { group.mids = mids.join(' '); + return false; + } else { return true; } }); @@ -28717,9 +28337,8 @@ Interop.prototype.toUnifiedPlan = function(desc) { var resStr = transform.write(session); - // Cache the transformed SDP (Unified Plan) for later re-use in this - // function. - this.cache[desc.type] = resStr; + // Cache the transformed SDP (Plan A) for later re-use in this function. + cache[desc.type] = resStr; return new RTCSessionDescription({ type: desc.type, @@ -28729,7 +28348,7 @@ Interop.prototype.toUnifiedPlan = function(desc) { //#endregion }; -},{"./array-equals":86,"./transform":89}],89:[function(require,module,exports){ +},{"./array-equals":85,"./transform":88}],88:[function(require,module,exports){ var transform = require('sdp-transform'); exports.write = function(session, opts) { @@ -28828,7 +28447,7 @@ exports.parse = function(sdp) { }; -},{"sdp-transform":91}],90:[function(require,module,exports){ +},{"sdp-transform":90}],89:[function(require,module,exports){ var grammar = module.exports = { v: [{ name: 'version', @@ -29053,10 +28672,6 @@ var grammar = module.exports = { name: 'rtcpMux', reg: /^(rtcp-mux)/ }, - { //a=rtcp-rsize - name: 'rtcpRsize', - reg: /^(rtcp-rsize)/ - }, { // any a= that we don't understand is kepts verbatim on media.invalid push: 'invalid', names: ["value"] @@ -29077,7 +28692,7 @@ Object.keys(grammar).forEach(function (key) { }); }); -},{}],91:[function(require,module,exports){ +},{}],90:[function(require,module,exports){ var parser = require('./parser'); var writer = require('./writer'); @@ -29087,7 +28702,7 @@ exports.parseFmtpConfig = parser.parseFmtpConfig; exports.parsePayloads = parser.parsePayloads; exports.parseRemoteCandidates = parser.parseRemoteCandidates; -},{"./parser":92,"./writer":93}],92:[function(require,module,exports){ +},{"./parser":91,"./writer":92}],91:[function(require,module,exports){ var toIntIfInt = function (v) { return String(Number(v)) === v ? Number(v) : v; }; @@ -29182,7 +28797,7 @@ exports.parseRemoteCandidates = function (str) { return candidates; }; -},{"./grammar":90}],93:[function(require,module,exports){ +},{"./grammar":89}],92:[function(require,module,exports){ var grammar = require('./grammar'); // customized util.format - discards excess arguments and can void middle ones @@ -29298,14 +28913,14 @@ module.exports = function (session, opts) { return sdp.join('\r\n') + '\r\n'; }; -},{"./grammar":90}],94:[function(require,module,exports){ +},{"./grammar":89}],93:[function(require,module,exports){ var MediaStreamType = { VIDEO_TYPE: "Video", AUDIO_TYPE: "Audio" }; module.exports = MediaStreamType; -},{}],95:[function(require,module,exports){ +},{}],94:[function(require,module,exports){ var RTCBrowserType = { RTC_BROWSER_CHROME: "rtc_browser.chrome", @@ -29313,7 +28928,7 @@ var RTCBrowserType = { }; module.exports = RTCBrowserType; -},{}],96:[function(require,module,exports){ +},{}],95:[function(require,module,exports){ var RTCEvents = { LASTN_CHANGED: "rtc.lastn_changed", DOMINANTSPEAKER_CHANGED: "rtc.dominantspeaker_changed", @@ -29326,7 +28941,7 @@ var RTCEvents = { }; module.exports = RTCEvents; -},{}],97:[function(require,module,exports){ +},{}],96:[function(require,module,exports){ var Resolutions = { "1080": { width: 1920, @@ -29380,7 +28995,7 @@ var Resolutions = { } }; module.exports = Resolutions; -},{}],98:[function(require,module,exports){ +},{}],97:[function(require,module,exports){ var StreamEventTypes = { EVENT_TYPE_LOCAL_CREATED: "stream.local_created", @@ -29396,14 +29011,14 @@ var StreamEventTypes = { }; module.exports = StreamEventTypes; -},{}],99:[function(require,module,exports){ +},{}],98:[function(require,module,exports){ var UIEvents = { NICKNAME_CHANGED: "UI.nickname_changed", SELECTED_ENDPOINT: "UI.selected_endpoint", PINNED_ENDPOINT: "UI.pinned_endpoint" }; module.exports = UIEvents; -},{}],100:[function(require,module,exports){ +},{}],99:[function(require,module,exports){ var AuthenticationEvents = { /** * Event callback arguments: @@ -29417,7 +29032,7 @@ var AuthenticationEvents = { }; module.exports = AuthenticationEvents; -},{}],101:[function(require,module,exports){ +},{}],100:[function(require,module,exports){ var CQEvents = { LOCALSTATS_UPDATED: "cq.localstats_updated", REMOTESTATS_UPDATED: "cq.remotestats_updated", @@ -29425,7 +29040,7 @@ var CQEvents = { }; module.exports = CQEvents; -},{}],102:[function(require,module,exports){ +},{}],101:[function(require,module,exports){ var DesktopSharingEventTypes = { INIT: "ds.init", @@ -29435,14 +29050,14 @@ var DesktopSharingEventTypes = { }; module.exports = DesktopSharingEventTypes; -},{}],103:[function(require,module,exports){ +},{}],102:[function(require,module,exports){ var Events = { DTMF_SUPPORT_CHANGED: "members.dtmf_support_changed" }; module.exports = Events; -},{}],104:[function(require,module,exports){ +},{}],103:[function(require,module,exports){ module.exports = { getLanguages : function () { var languages = []; @@ -29458,7 +29073,7 @@ module.exports = { DE: "de", TR: "tr" } -},{}],105:[function(require,module,exports){ +},{}],104:[function(require,module,exports){ var XMPPEvents = { CONNECTION_FAILED: "xmpp.connection.failed", CONFERENCE_CREATED: "xmpp.conferenceCreated.jingle", @@ -29494,64 +29109,367 @@ var XMPPEvents = { START_MUTED: "xmpp.start_muted" }; module.exports = XMPPEvents; -},{}],106:[function(require,module,exports){ -/* jshint -W117 */ -/* application specific logic */ +},{}],105:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. -var APP = -{ - init: function () { - this.UI = require("./modules/UI/UI"); - this.API = require("./modules/API/API"); - this.connectionquality = require("./modules/connectionquality/connectionquality"); - this.statistics = require("./modules/statistics/statistics"); - this.RTC = require("./modules/RTC/RTC"); - this.simulcast = require("./modules/simulcast/simulcast"); - this.desktopsharing = require("./modules/desktopsharing/desktopsharing"); - this.xmpp = require("./modules/xmpp/xmpp"); - this.keyboardshortcut = require("./modules/keyboardshortcut/keyboardshortcut"); - this.translation = require("./modules/translation/translation"); - this.settings = require("./modules/settings/Settings"); - this.DTMF = require("./modules/DTMF/DTMF"); - this.members = require("./modules/members/MemberList"); +function EventEmitter() { + this._events = this._events || {}; + this._maxListeners = this._maxListeners || undefined; +} +module.exports = EventEmitter; + +// Backwards-compat with node 0.10.x +EventEmitter.EventEmitter = EventEmitter; + +EventEmitter.prototype._events = undefined; +EventEmitter.prototype._maxListeners = undefined; + +// By default EventEmitters will print a warning if more than 10 listeners are +// added to it. This is a useful default which helps finding memory leaks. +EventEmitter.defaultMaxListeners = 10; + +// Obviously not all Emitters should be limited to 10. This function allows +// that to be increased. Set to zero for unlimited. +EventEmitter.prototype.setMaxListeners = function(n) { + if (!isNumber(n) || n < 0 || isNaN(n)) + throw TypeError('n must be a positive number'); + this._maxListeners = n; + return this; +}; + +EventEmitter.prototype.emit = function(type) { + var er, handler, len, args, i, listeners; + + if (!this._events) + this._events = {}; + + // If there is no 'error' event listener then throw. + if (type === 'error') { + if (!this._events.error || + (isObject(this._events.error) && !this._events.error.length)) { + er = arguments[1]; + if (er instanceof Error) { + throw er; // Unhandled 'error' event + } + throw TypeError('Uncaught, unspecified "error" event.'); + } + } + + handler = this._events[type]; + + if (isUndefined(handler)) + return false; + + if (isFunction(handler)) { + switch (arguments.length) { + // fast cases + case 1: + handler.call(this); + break; + case 2: + handler.call(this, arguments[1]); + break; + case 3: + handler.call(this, arguments[1], arguments[2]); + break; + // slower + default: + len = arguments.length; + args = new Array(len - 1); + for (i = 1; i < len; i++) + args[i - 1] = arguments[i]; + handler.apply(this, args); + } + } else if (isObject(handler)) { + len = arguments.length; + args = new Array(len - 1); + for (i = 1; i < len; i++) + args[i - 1] = arguments[i]; + + listeners = handler.slice(); + len = listeners.length; + for (i = 0; i < len; i++) + listeners[i].apply(this, args); + } + + return true; +}; + +EventEmitter.prototype.addListener = function(type, listener) { + var m; + + if (!isFunction(listener)) + throw TypeError('listener must be a function'); + + if (!this._events) + this._events = {}; + + // To avoid recursion in the case that type === "newListener"! Before + // adding it to the listeners, first emit "newListener". + if (this._events.newListener) + this.emit('newListener', type, + isFunction(listener.listener) ? + listener.listener : listener); + + if (!this._events[type]) + // Optimize the case of one listener. Don't need the extra array object. + this._events[type] = listener; + else if (isObject(this._events[type])) + // If we've already got an array, just append. + this._events[type].push(listener); + else + // Adding the second element, need to change to array. + this._events[type] = [this._events[type], listener]; + + // Check for listener leak + if (isObject(this._events[type]) && !this._events[type].warned) { + var m; + if (!isUndefined(this._maxListeners)) { + m = this._maxListeners; + } else { + m = EventEmitter.defaultMaxListeners; + } + + if (m && m > 0 && this._events[type].length > m) { + this._events[type].warned = true; + console.error('(node) warning: possible EventEmitter memory ' + + 'leak detected. %d listeners added. ' + + 'Use emitter.setMaxListeners() to increase limit.', + this._events[type].length); + if (typeof console.trace === 'function') { + // not supported in IE 10 + console.trace(); + } + } + } + + return this; +}; + +EventEmitter.prototype.on = EventEmitter.prototype.addListener; + +EventEmitter.prototype.once = function(type, listener) { + if (!isFunction(listener)) + throw TypeError('listener must be a function'); + + var fired = false; + + function g() { + this.removeListener(type, g); + + if (!fired) { + fired = true; + listener.apply(this, arguments); + } + } + + g.listener = listener; + this.on(type, g); + + return this; +}; + +// emits a 'removeListener' event iff the listener was removed +EventEmitter.prototype.removeListener = function(type, listener) { + var list, position, length, i; + + if (!isFunction(listener)) + throw TypeError('listener must be a function'); + + if (!this._events || !this._events[type]) + return this; + + list = this._events[type]; + length = list.length; + position = -1; + + if (list === listener || + (isFunction(list.listener) && list.listener === listener)) { + delete this._events[type]; + if (this._events.removeListener) + this.emit('removeListener', type, listener); + + } else if (isObject(list)) { + for (i = length; i-- > 0;) { + if (list[i] === listener || + (list[i].listener && list[i].listener === listener)) { + position = i; + break; + } + } + + if (position < 0) + return this; + + if (list.length === 1) { + list.length = 0; + delete this._events[type]; + } else { + list.splice(position, 1); + } + + if (this._events.removeListener) + this.emit('removeListener', type, listener); + } + + return this; +}; + +EventEmitter.prototype.removeAllListeners = function(type) { + var key, listeners; + + if (!this._events) + return this; + + // not listening for removeListener, no need to emit + if (!this._events.removeListener) { + if (arguments.length === 0) + this._events = {}; + else if (this._events[type]) + delete this._events[type]; + return this; + } + + // emit removeListener for all listeners on all events + if (arguments.length === 0) { + for (key in this._events) { + if (key === 'removeListener') continue; + this.removeAllListeners(key); + } + this.removeAllListeners('removeListener'); + this._events = {}; + return this; + } + + listeners = this._events[type]; + + if (isFunction(listeners)) { + this.removeListener(type, listeners); + } else { + // LIFO order + while (listeners.length) + this.removeListener(type, listeners[listeners.length - 1]); + } + delete this._events[type]; + + return this; +}; + +EventEmitter.prototype.listeners = function(type) { + var ret; + if (!this._events || !this._events[type]) + ret = []; + else if (isFunction(this._events[type])) + ret = [this._events[type]]; + else + ret = this._events[type].slice(); + return ret; +}; + +EventEmitter.listenerCount = function(emitter, type) { + var ret; + if (!emitter._events || !emitter._events[type]) + ret = 0; + else if (isFunction(emitter._events[type])) + ret = 1; + else + ret = emitter._events[type].length; + return ret; +}; + +function isFunction(arg) { + return typeof arg === 'function'; +} + +function isNumber(arg) { + return typeof arg === 'number'; +} + +function isObject(arg) { + return typeof arg === 'object' && arg !== null; +} + +function isUndefined(arg) { + return arg === void 0; +} + +},{}],106:[function(require,module,exports){ +// shim for using process in browser + +var process = module.exports = {}; +var queue = []; +var draining = false; + +function drainQueue() { + if (draining) { + return; + } + draining = true; + var currentQueue; + var len = queue.length; + while(len) { + currentQueue = queue; + queue = []; + var i = -1; + while (++i < len) { + currentQueue[i](); + } + len = queue.length; + } + draining = false; +} +process.nextTick = function (fun) { + queue.push(fun); + if (!draining) { + setTimeout(drainQueue, 0); } }; -function init() { +process.title = 'browser'; +process.browser = true; +process.env = {}; +process.argv = []; +process.version = ''; // empty string to avoid regexp issues - APP.RTC.start(); - APP.xmpp.start(); - APP.statistics.start(); - APP.connectionquality.init(); +function noop() {} - // Set default desktop sharing method - APP.desktopsharing.init(); +process.on = noop; +process.addListener = noop; +process.once = noop; +process.off = noop; +process.removeListener = noop; +process.removeAllListeners = noop; +process.emit = noop; - APP.keyboardshortcut.init(); - APP.members.start(); -} +process.binding = function (name) { + throw new Error('process.binding is not supported'); +}; +// TODO(shtylman) +process.cwd = function () { return '/' }; +process.chdir = function (dir) { + throw new Error('process.chdir is not supported'); +}; +process.umask = function() { return 0; }; -$(document).ready(function () { - - APP.init(); - - APP.translation.init(); - - if(APP.API.isEnabled()) - APP.API.init(); - - APP.UI.start(init); - -}); - -$(window).bind('beforeunload', function () { - if(APP.API.isEnabled()) - APP.API.dispose(); -}); - -module.exports = APP; - - -},{"./modules/API/API":1,"./modules/DTMF/DTMF":2,"./modules/RTC/RTC":6,"./modules/UI/UI":8,"./modules/connectionquality/connectionquality":35,"./modules/desktopsharing/desktopsharing":36,"./modules/keyboardshortcut/keyboardshortcut":37,"./modules/members/MemberList":38,"./modules/settings/Settings":39,"./modules/simulcast/simulcast":44,"./modules/statistics/statistics":47,"./modules/translation/translation":48,"./modules/xmpp/xmpp":62}]},{},[106])(106) +},{}]},{},[1])(1) }); \ No newline at end of file diff --git a/modules/UI/toolbars/ToolbarToggler.js b/modules/UI/toolbars/ToolbarToggler.js index df9760d61..22244c45e 100644 --- a/modules/UI/toolbars/ToolbarToggler.js +++ b/modules/UI/toolbars/ToolbarToggler.js @@ -15,6 +15,9 @@ function showDesktopSharingButton() { * Hides the toolbar. */ function hideToolbar() { + if(config.alwaysVisibleToolbar) + return; + var header = $("#header"), bottomToolbar = $("#bottomToolbar"); var isToolbarHover = false;