diff --git a/index.html b/index.html
index 75e49a8eef..6dc0b78a30 100644
--- a/index.html
+++ b/index.html
@@ -22,7 +22,7 @@
-
+
diff --git a/libs/app.bundle.js b/libs/app.bundle.js
index f9eebd81af..86de0dc084 100644
--- a/libs/app.bundle.js
+++ b/libs/app.bundle.js
@@ -1,4 +1,4 @@
-!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.APP=e()}}(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= len) {
- return x; // missing argument
- }
- var arg = args[i];
- i += 1;
- switch (x) {
- case '%%':
- return '%';
- case '%s':
- return String(arg);
- case '%d':
- return Number(arg);
- case '%v':
- return '';
- }
- });
- // NB: we discard excess arguments - they are typically undefined from makeLine
-};
-
-var makeLine = function (type, obj, location) {
- var str = obj.format instanceof Function ?
- (obj.format(obj.push ? location : location[obj.name])) :
- obj.format;
-
- var args = [type + '=' + str];
- if (obj.names) {
- for (var i = 0; i < obj.names.length; i += 1) {
- var n = obj.names[i];
- if (obj.name) {
- args.push(location[obj.name][n]);
- }
- else { // for mLine and push attributes
- args.push(location[obj.names[i]]);
- }
- }
- }
- else {
- args.push(location[obj.name]);
- }
- return format.apply(null, args);
-};
-
-// RFC specified order
-// TODO: extend this with all the rest
-var defaultOuterOrder = [
- 'v', 'o', 's', 'i',
- 'u', 'e', 'p', 'c',
- 'b', 't', 'r', 'z', 'a'
-];
-var defaultInnerOrder = ['i', 'c', 'b', 'a'];
-
-
-module.exports = function (session, opts) {
- opts = opts || {};
- // ensure certain properties exist
- if (session.version == null) {
- session.version = 0; // "v=0" must be there (only defined version atm)
- }
- if (session.name == null) {
- session.name = " "; // "s= " must be there if no meaningful name set
- }
- session.media.forEach(function (mLine) {
- if (mLine.payloads == null) {
- mLine.payloads = "";
- }
- });
-
- var outerOrder = opts.outerOrder || defaultOuterOrder;
- var innerOrder = opts.innerOrder || defaultInnerOrder;
- var sdp = [];
-
- // loop through outerOrder for matching properties on session
- outerOrder.forEach(function (type) {
- grammar[type].forEach(function (obj) {
- if (obj.name in session && session[obj.name] != null) {
- sdp.push(makeLine(type, obj, session));
- }
- else if (obj.push in session && session[obj.push] != null) {
- session[obj.push].forEach(function (el) {
- sdp.push(makeLine(type, obj, el));
- });
- }
- });
- });
-
- // then for each media line, follow the innerOrder
- session.media.forEach(function (mLine) {
- sdp.push(makeLine('m', grammar.m[0], mLine));
-
- innerOrder.forEach(function (type) {
- grammar[type].forEach(function (obj) {
- if (obj.name in mLine && mLine[obj.name] != null) {
- sdp.push(makeLine(type, obj, mLine));
- }
- else if (obj.push in mLine && mLine[obj.push] != null) {
- mLine[obj.push].forEach(function (el) {
- sdp.push(makeLine(type, obj, el));
- });
- }
- });
- });
- });
-
- return sdp.join('\r\n') + '\r\n';
-};
-
-},{"./grammar":92}],96:[function(require,module,exports){
-var transform = require('sdp-transform');
-var transformUtils = require('./transform-utils');
-var parseSsrcs = transformUtils.parseSsrcs;
-var writeSsrcs = transformUtils.writeSsrcs;
-
-//region Constants
-
-var DEFAULT_NUM_OF_LAYERS = 3;
+var DEFAULT_NUM_OF_LAYERS = 3;
//endregion
@@ -29730,136 +29265,598 @@ Simulcast.prototype.isSupported = function () {
*/
Simulcast.prototype.mungeRemoteDescription = function (desc) {
- if (!validateDescription(desc)) {
- return desc;
+ if (!validateDescription(desc)) {
+ return desc;
+ }
+
+ var session = transform.parse(desc.sdp);
+
+ var self = this;
+ processVideo(session, function (mLine) {
+
+ // Handle simulcast reception.
+ if (self.options.explodeRemoteSimulcast) {
+ explodeRemoteSimulcast(mLine);
+ } else {
+ squeezeRemoteSimulcast(mLine);
+ }
+
+ // If native simulcast is enabled, we must append the x-goog-conference
+ // attribute to the SDP.
+ if (self.layers.length < 1) {
+ removeGoogConference(mLine);
+ } else {
+ assertGoogConference(mLine);
+ }
+ });
+
+ return new RTCSessionDescription({
+ type: desc.type,
+ sdp: transform.write(session)
+ });
+};
+
+/**
+ *
+ * @param desc
+ * @returns {RTCSessionDescription}
+ */
+Simulcast.prototype.mungeLocalDescription = function (desc) {
+
+ if (!validateDescription(desc) || !this.isSupported()) {
+ return desc;
+ }
+
+ var session = transform.parse(desc.sdp);
+
+ var self = this;
+ processVideo(session, function (mLine) {
+ // Initialize native simulcast layers, if not already done.
+ self._maybeInitializeLayers(mLine);
+
+ // Update the SDP with the simulcast layers.
+ self._restoreSimulcastView(mLine);
+ });
+
+ return new RTCSessionDescription({
+ type: desc.type,
+ sdp: transform.write(session)
+ });
+};
+
+//endregion
+
+module.exports = Simulcast;
+
+},{"./transform-utils":93,"sdp-transform":95}],93:[function(require,module,exports){
+exports.writeSsrcs = function(sources, order) {
+ var ssrcs = [];
+
+ // expand sources to ssrcs
+ if (typeof sources !== 'undefined' &&
+ Object.keys(sources).length !== 0) {
+
+ if (Array.isArray(order)) {
+ for (var i = 0; i < order.length; i++) {
+ var ssrc = order[i];
+ var source = sources[ssrc];
+ Object.keys(source).forEach(function (attribute) {
+ ssrcs.push({
+ id: ssrc,
+ attribute: attribute,
+ value: source[attribute]
+ });
+ });
+ }
+ } else {
+ Object.keys(sources).forEach(function (ssrc) {
+ var source = sources[ssrc];
+ Object.keys(source).forEach(function (attribute) {
+ ssrcs.push({
+ id: ssrc,
+ attribute: attribute,
+ value: source[attribute]
+ });
+ });
+ });
+ }
+ }
+
+ return ssrcs;
+};
+
+exports.parseSsrcs = function (mLine) {
+ var sources = {};
+ // group sources attributes by ssrc.
+ if (typeof mLine.ssrcs !== 'undefined' && Array.isArray(mLine.ssrcs)) {
+ mLine.ssrcs.forEach(function (ssrc) {
+ if (!sources[ssrc.id])
+ sources[ssrc.id] = {};
+ sources[ssrc.id][ssrc.attribute] = ssrc.value;
+ });
+ }
+ return sources;
+};
+
+
+},{}],94:[function(require,module,exports){
+var grammar = module.exports = {
+ v: [{
+ name: 'version',
+ reg: /^(\d*)$/
+ }],
+ o: [{ //o=- 20518 0 IN IP4 203.0.113.1
+ // NB: sessionId will be a String in most cases because it is huge
+ name: 'origin',
+ reg: /^(\S*) (\d*) (\d*) (\S*) IP(\d) (\S*)/,
+ names: ['username', 'sessionId', 'sessionVersion', 'netType', 'ipVer', 'address'],
+ format: "%s %s %d %s IP%d %s"
+ }],
+ // default parsing of these only (though some of these feel outdated)
+ s: [{ name: 'name' }],
+ i: [{ name: 'description' }],
+ u: [{ name: 'uri' }],
+ e: [{ name: 'email' }],
+ p: [{ name: 'phone' }],
+ z: [{ name: 'timezones' }], // TODO: this one can actually be parsed properly..
+ r: [{ name: 'repeats' }], // TODO: this one can also be parsed properly
+ //k: [{}], // outdated thing ignored
+ t: [{ //t=0 0
+ name: 'timing',
+ reg: /^(\d*) (\d*)/,
+ names: ['start', 'stop'],
+ format: "%d %d"
+ }],
+ c: [{ //c=IN IP4 10.47.197.26
+ name: 'connection',
+ reg: /^IN IP(\d) (\S*)/,
+ names: ['version', 'ip'],
+ format: "IN IP%d %s"
+ }],
+ b: [{ //b=AS:4000
+ push: 'bandwidth',
+ reg: /^(TIAS|AS|CT|RR|RS):(\d*)/,
+ names: ['type', 'limit'],
+ format: "%s:%s"
+ }],
+ m: [{ //m=video 51744 RTP/AVP 126 97 98 34 31
+ // NB: special - pushes to session
+ // TODO: rtp/fmtp should be filtered by the payloads found here?
+ reg: /^(\w*) (\d*) ([\w\/]*)(?: (.*))?/,
+ names: ['type', 'port', 'protocol', 'payloads'],
+ format: "%s %d %s %s"
+ }],
+ a: [
+ { //a=rtpmap:110 opus/48000/2
+ push: 'rtp',
+ reg: /^rtpmap:(\d*) ([\w\-]*)\/(\d*)(?:\s*\/(\S*))?/,
+ names: ['payload', 'codec', 'rate', 'encoding'],
+ format: function (o) {
+ return (o.encoding) ?
+ "rtpmap:%d %s/%s/%s":
+ "rtpmap:%d %s/%s";
+ }
+ },
+ { //a=fmtp:108 profile-level-id=24;object=23;bitrate=64000
+ push: 'fmtp',
+ reg: /^fmtp:(\d*) (\S*)/,
+ names: ['payload', 'config'],
+ format: "fmtp:%d %s"
+ },
+ { //a=control:streamid=0
+ name: 'control',
+ reg: /^control:(.*)/,
+ format: "control:%s"
+ },
+ { //a=rtcp:65179 IN IP4 193.84.77.194
+ name: 'rtcp',
+ reg: /^rtcp:(\d*)(?: (\S*) IP(\d) (\S*))?/,
+ names: ['port', 'netType', 'ipVer', 'address'],
+ format: function (o) {
+ return (o.address != null) ?
+ "rtcp:%d %s IP%d %s":
+ "rtcp:%d";
+ }
+ },
+ { //a=rtcp-fb:98 trr-int 100
+ push: 'rtcpFbTrrInt',
+ reg: /^rtcp-fb:(\*|\d*) trr-int (\d*)/,
+ names: ['payload', 'value'],
+ format: "rtcp-fb:%d trr-int %d"
+ },
+ { //a=rtcp-fb:98 nack rpsi
+ push: 'rtcpFb',
+ reg: /^rtcp-fb:(\*|\d*) ([\w-_]*)(?: ([\w-_]*))?/,
+ names: ['payload', 'type', 'subtype'],
+ format: function (o) {
+ return (o.subtype != null) ?
+ "rtcp-fb:%s %s %s":
+ "rtcp-fb:%s %s";
+ }
+ },
+ { //a=extmap:2 urn:ietf:params:rtp-hdrext:toffset
+ //a=extmap:1/recvonly URI-gps-string
+ push: 'ext',
+ reg: /^extmap:([\w_\/]*) (\S*)(?: (\S*))?/,
+ names: ['value', 'uri', 'config'], // value may include "/direction" suffix
+ format: function (o) {
+ return (o.config != null) ?
+ "extmap:%s %s %s":
+ "extmap:%s %s";
+ }
+ },
+ {
+ //a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:PS1uQCVeeCFCanVmcjkpPywjNWhcYD0mXXtxaVBR|2^20|1:32
+ push: 'crypto',
+ reg: /^crypto:(\d*) ([\w_]*) (\S*)(?: (\S*))?/,
+ names: ['id', 'suite', 'config', 'sessionConfig'],
+ format: function (o) {
+ return (o.sessionConfig != null) ?
+ "crypto:%d %s %s %s":
+ "crypto:%d %s %s";
+ }
+ },
+ { //a=setup:actpass
+ name: 'setup',
+ reg: /^setup:(\w*)/,
+ format: "setup:%s"
+ },
+ { //a=mid:1
+ name: 'mid',
+ reg: /^mid:([^\s]*)/,
+ format: "mid:%s"
+ },
+ { //a=msid:0c8b064d-d807-43b4-b434-f92a889d8587 98178685-d409-46e0-8e16-7ef0db0db64a
+ name: 'msid',
+ reg: /^msid:(.*)/,
+ format: "msid:%s"
+ },
+ { //a=ptime:20
+ name: 'ptime',
+ reg: /^ptime:(\d*)/,
+ format: "ptime:%d"
+ },
+ { //a=maxptime:60
+ name: 'maxptime',
+ reg: /^maxptime:(\d*)/,
+ format: "maxptime:%d"
+ },
+ { //a=sendrecv
+ name: 'direction',
+ reg: /^(sendrecv|recvonly|sendonly|inactive)/
+ },
+ { //a=ice-lite
+ name: 'icelite',
+ reg: /^(ice-lite)/
+ },
+ { //a=ice-ufrag:F7gI
+ name: 'iceUfrag',
+ reg: /^ice-ufrag:(\S*)/,
+ format: "ice-ufrag:%s"
+ },
+ { //a=ice-pwd:x9cml/YzichV2+XlhiMu8g
+ name: 'icePwd',
+ reg: /^ice-pwd:(\S*)/,
+ format: "ice-pwd:%s"
+ },
+ { //a=fingerprint:SHA-1 00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF:00:11:22:33
+ name: 'fingerprint',
+ reg: /^fingerprint:(\S*) (\S*)/,
+ names: ['type', 'hash'],
+ format: "fingerprint:%s %s"
+ },
+ {
+ //a=candidate:0 1 UDP 2113667327 203.0.113.1 54400 typ host
+ //a=candidate:1162875081 1 udp 2113937151 192.168.34.75 60017 typ host generation 0
+ //a=candidate:3289912957 2 udp 1845501695 193.84.77.194 60017 typ srflx raddr 192.168.34.75 rport 60017 generation 0
+ push:'candidates',
+ reg: /^candidate:(\S*) (\d*) (\S*) (\d*) (\S*) (\d*) typ (\S*)(?: raddr (\S*) rport (\d*))?(?: generation (\d*))?/,
+ names: ['foundation', 'component', 'transport', 'priority', 'ip', 'port', 'type', 'raddr', 'rport', 'generation'],
+ format: function (o) {
+ var str = "candidate:%s %d %s %d %s %d typ %s";
+ // NB: candidate has two optional chunks, so %void middle one if it's missing
+ str += (o.raddr != null) ? " raddr %s rport %d" : "%v%v";
+ if (o.generation != null) {
+ str += " generation %d";
+ }
+ return str;
+ }
+ },
+ { //a=end-of-candidates (keep after the candidates line for readability)
+ name: 'endOfCandidates',
+ reg: /^(end-of-candidates)/
+ },
+ { //a=remote-candidates:1 203.0.113.1 54400 2 203.0.113.1 54401 ...
+ name: 'remoteCandidates',
+ reg: /^remote-candidates:(.*)/,
+ format: "remote-candidates:%s"
+ },
+ { //a=ice-options:google-ice
+ name: 'iceOptions',
+ reg: /^ice-options:(\S*)/,
+ format: "ice-options:%s"
+ },
+ { //a=ssrc:2566107569 cname:t9YU8M1UxTF8Y1A1
+ push: "ssrcs",
+ reg: /^ssrc:(\d*) ([\w_]*):(.*)/,
+ names: ['id', 'attribute', 'value'],
+ format: "ssrc:%d %s:%s"
+ },
+ { //a=ssrc-group:FEC 1 2
+ push: "ssrcGroups",
+ reg: /^ssrc-group:(\w*) (.*)/,
+ names: ['semantics', 'ssrcs'],
+ format: "ssrc-group:%s %s"
+ },
+ { //a=msid-semantic: WMS Jvlam5X3SX1OP6pn20zWogvaKJz5Hjf9OnlV
+ name: "msidSemantic",
+ reg: /^msid-semantic:\s?(\w*) (\S*)/,
+ names: ['semantic', 'token'],
+ format: "msid-semantic: %s %s" // space after ":" is not accidental
+ },
+ { //a=group:BUNDLE audio video
+ push: 'groups',
+ reg: /^group:(\w*) (.*)/,
+ names: ['type', 'mids'],
+ format: "group:%s %s"
+ },
+ { //a=rtcp-mux
+ 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"]
+ }
+ ]
+};
+
+// set sensible defaults to avoid polluting the grammar with boring details
+Object.keys(grammar).forEach(function (key) {
+ var objs = grammar[key];
+ objs.forEach(function (obj) {
+ if (!obj.reg) {
+ obj.reg = /(.*)/;
+ }
+ if (!obj.format) {
+ obj.format = "%s";
+ }
+ });
+});
+
+},{}],95:[function(require,module,exports){
+var parser = require('./parser');
+var writer = require('./writer');
+
+exports.write = writer;
+exports.parse = parser.parse;
+exports.parseFmtpConfig = parser.parseFmtpConfig;
+exports.parsePayloads = parser.parsePayloads;
+exports.parseRemoteCandidates = parser.parseRemoteCandidates;
+
+},{"./parser":96,"./writer":97}],96:[function(require,module,exports){
+var toIntIfInt = function (v) {
+ return String(Number(v)) === v ? Number(v) : v;
+};
+
+var attachProperties = function (match, location, names, rawName) {
+ if (rawName && !names) {
+ location[rawName] = toIntIfInt(match[1]);
+ }
+ else {
+ for (var i = 0; i < names.length; i += 1) {
+ if (match[i+1] != null) {
+ location[names[i]] = toIntIfInt(match[i+1]);
+ }
+ }
+ }
+};
+
+var parseReg = function (obj, location, content) {
+ var needsBlank = obj.name && obj.names;
+ if (obj.push && !location[obj.push]) {
+ location[obj.push] = [];
+ }
+ else if (needsBlank && !location[obj.name]) {
+ location[obj.name] = {};
+ }
+ var keyLocation = obj.push ?
+ {} : // blank object that will be pushed
+ needsBlank ? location[obj.name] : location; // otherwise, named location or root
+
+ attachProperties(content.match(obj.reg), keyLocation, obj.names, obj.name);
+
+ if (obj.push) {
+ location[obj.push].push(keyLocation);
+ }
+};
+
+var grammar = require('./grammar');
+var validLine = RegExp.prototype.test.bind(/^([a-z])=(.*)/);
+
+exports.parse = function (sdp) {
+ var session = {}
+ , media = []
+ , location = session; // points at where properties go under (one of the above)
+
+ // parse lines we understand
+ sdp.split(/(\r\n|\r|\n)/).filter(validLine).forEach(function (l) {
+ var type = l[0];
+ var content = l.slice(2);
+ if (type === 'm') {
+ media.push({rtp: [], fmtp: []});
+ location = media[media.length-1]; // point at latest media line
}
- var session = transform.parse(desc.sdp);
+ for (var j = 0; j < (grammar[type] || []).length; j += 1) {
+ var obj = grammar[type][j];
+ if (obj.reg.test(content)) {
+ return parseReg(obj, location, content);
+ }
+ }
+ });
- var self = this;
- processVideo(session, function (mLine) {
+ session.media = media; // link it up
+ return session;
+};
- // Handle simulcast reception.
- if (self.options.explodeRemoteSimulcast) {
- explodeRemoteSimulcast(mLine);
- } else {
- squeezeRemoteSimulcast(mLine);
- }
+var fmtpReducer = function (acc, expr) {
+ var s = expr.split('=');
+ if (s.length === 2) {
+ acc[s[0]] = toIntIfInt(s[1]);
+ }
+ return acc;
+};
- // If native simulcast is enabled, we must append the x-goog-conference
- // attribute to the SDP.
- if (self.layers.length < 1) {
- removeGoogConference(mLine);
- } else {
- assertGoogConference(mLine);
- }
- });
+exports.parseFmtpConfig = function (str) {
+ return str.split(';').reduce(fmtpReducer, {});
+};
- return new RTCSessionDescription({
- type: desc.type,
- sdp: transform.write(session)
+exports.parsePayloads = function (str) {
+ return str.split(' ').map(Number);
+};
+
+exports.parseRemoteCandidates = function (str) {
+ var candidates = [];
+ var parts = str.split(' ').map(toIntIfInt);
+ for (var i = 0; i < parts.length; i += 3) {
+ candidates.push({
+ component: parts[i],
+ ip: parts[i + 1],
+ port: parts[i + 2]
});
+ }
+ return candidates;
};
-/**
- *
- * @param desc
- * @returns {RTCSessionDescription}
- */
-Simulcast.prototype.mungeLocalDescription = function (desc) {
+},{"./grammar":94}],97:[function(require,module,exports){
+var grammar = require('./grammar');
- if (!validateDescription(desc) || !this.isSupported()) {
- return desc;
+// customized util.format - discards excess arguments and can void middle ones
+var formatRegExp = /%[sdv%]/g;
+var format = function (formatStr) {
+ var i = 1;
+ var args = arguments;
+ var len = args.length;
+ return formatStr.replace(formatRegExp, function (x) {
+ if (i >= len) {
+ return x; // missing argument
}
+ var arg = args[i];
+ i += 1;
+ switch (x) {
+ case '%%':
+ return '%';
+ case '%s':
+ return String(arg);
+ case '%d':
+ return Number(arg);
+ case '%v':
+ return '';
+ }
+ });
+ // NB: we discard excess arguments - they are typically undefined from makeLine
+};
- var session = transform.parse(desc.sdp);
-
- var self = this;
- processVideo(session, function (mLine) {
- // Initialize native simulcast layers, if not already done.
- self._maybeInitializeLayers(mLine);
-
- // Update the SDP with the simulcast layers.
- self._restoreSimulcastView(mLine);
- });
+var makeLine = function (type, obj, location) {
+ var str = obj.format instanceof Function ?
+ (obj.format(obj.push ? location : location[obj.name])) :
+ obj.format;
- return new RTCSessionDescription({
- type: desc.type,
- sdp: transform.write(session)
- });
+ var args = [type + '=' + str];
+ if (obj.names) {
+ for (var i = 0; i < obj.names.length; i += 1) {
+ var n = obj.names[i];
+ if (obj.name) {
+ args.push(location[obj.name][n]);
+ }
+ else { // for mLine and push attributes
+ args.push(location[obj.names[i]]);
+ }
+ }
+ }
+ else {
+ args.push(location[obj.name]);
+ }
+ return format.apply(null, args);
};
-//endregion
+// RFC specified order
+// TODO: extend this with all the rest
+var defaultOuterOrder = [
+ 'v', 'o', 's', 'i',
+ 'u', 'e', 'p', 'c',
+ 'b', 't', 'r', 'z', 'a'
+];
+var defaultInnerOrder = ['i', 'c', 'b', 'a'];
-module.exports = Simulcast;
-},{"./transform-utils":97,"sdp-transform":99}],97:[function(require,module,exports){
-exports.writeSsrcs = function(sources, order) {
- var ssrcs = [];
+module.exports = function (session, opts) {
+ opts = opts || {};
+ // ensure certain properties exist
+ if (session.version == null) {
+ session.version = 0; // "v=0" must be there (only defined version atm)
+ }
+ if (session.name == null) {
+ session.name = " "; // "s= " must be there if no meaningful name set
+ }
+ session.media.forEach(function (mLine) {
+ if (mLine.payloads == null) {
+ mLine.payloads = "";
+ }
+ });
- // expand sources to ssrcs
- if (typeof sources !== 'undefined' &&
- Object.keys(sources).length !== 0) {
+ var outerOrder = opts.outerOrder || defaultOuterOrder;
+ var innerOrder = opts.innerOrder || defaultInnerOrder;
+ var sdp = [];
- if (Array.isArray(order)) {
- for (var i = 0; i < order.length; i++) {
- var ssrc = order[i];
- var source = sources[ssrc];
- Object.keys(source).forEach(function (attribute) {
- ssrcs.push({
- id: ssrc,
- attribute: attribute,
- value: source[attribute]
- });
- });
+ // loop through outerOrder for matching properties on session
+ outerOrder.forEach(function (type) {
+ grammar[type].forEach(function (obj) {
+ if (obj.name in session && session[obj.name] != null) {
+ sdp.push(makeLine(type, obj, session));
}
- } else {
- Object.keys(sources).forEach(function (ssrc) {
- var source = sources[ssrc];
- Object.keys(source).forEach(function (attribute) {
- ssrcs.push({
- id: ssrc,
- attribute: attribute,
- value: source[attribute]
- });
+ else if (obj.push in session && session[obj.push] != null) {
+ session[obj.push].forEach(function (el) {
+ sdp.push(makeLine(type, obj, el));
});
- });
- }
- }
+ }
+ });
+ });
- return ssrcs;
-};
+ // then for each media line, follow the innerOrder
+ session.media.forEach(function (mLine) {
+ sdp.push(makeLine('m', grammar.m[0], mLine));
-exports.parseSsrcs = function (mLine) {
- var sources = {};
- // group sources attributes by ssrc.
- if (typeof mLine.ssrcs !== 'undefined' && Array.isArray(mLine.ssrcs)) {
- mLine.ssrcs.forEach(function (ssrc) {
- if (!sources[ssrc.id])
- sources[ssrc.id] = {};
- sources[ssrc.id][ssrc.attribute] = ssrc.value;
+ innerOrder.forEach(function (type) {
+ grammar[type].forEach(function (obj) {
+ if (obj.name in mLine && mLine[obj.name] != null) {
+ sdp.push(makeLine(type, obj, mLine));
+ }
+ else if (obj.push in mLine && mLine[obj.push] != null) {
+ mLine[obj.push].forEach(function (el) {
+ sdp.push(makeLine(type, obj, el));
+ });
+ }
+ });
});
- }
- return sources;
-};
+ });
+ return sdp.join('\r\n') + '\r\n';
+};
-},{}],98:[function(require,module,exports){
-arguments[4][92][0].apply(exports,arguments)
-},{"dup":92}],99:[function(require,module,exports){
-arguments[4][93][0].apply(exports,arguments)
-},{"./parser":100,"./writer":101,"dup":93}],100:[function(require,module,exports){
-arguments[4][94][0].apply(exports,arguments)
-},{"./grammar":98,"dup":94}],101:[function(require,module,exports){
-arguments[4][95][0].apply(exports,arguments)
-},{"./grammar":98,"dup":95}],102:[function(require,module,exports){
+},{"./grammar":94}],98:[function(require,module,exports){
var MediaStreamType = {
VIDEO_TYPE: "Video",
AUDIO_TYPE: "Audio"
};
module.exports = MediaStreamType;
-},{}],103:[function(require,module,exports){
+},{}],99:[function(require,module,exports){
var RTCEvents = {
RTC_READY: "rtc.ready",
LASTN_CHANGED: "rtc.lastn_changed",
@@ -29871,7 +29868,7 @@ var RTCEvents = {
};
module.exports = RTCEvents;
-},{}],104:[function(require,module,exports){
+},{}],100:[function(require,module,exports){
var Resolutions = {
"1080": {
width: 1920,
@@ -29925,7 +29922,7 @@ var Resolutions = {
}
};
module.exports = Resolutions;
-},{}],105:[function(require,module,exports){
+},{}],101:[function(require,module,exports){
var StreamEventTypes = {
EVENT_TYPE_LOCAL_CREATED: "stream.local_created",
@@ -29941,14 +29938,14 @@ var StreamEventTypes = {
};
module.exports = StreamEventTypes;
-},{}],106:[function(require,module,exports){
+},{}],102:[function(require,module,exports){
var UIEvents = {
NICKNAME_CHANGED: "UI.nickname_changed",
SELECTED_ENDPOINT: "UI.selected_endpoint",
PINNED_ENDPOINT: "UI.pinned_endpoint"
};
module.exports = UIEvents;
-},{}],107:[function(require,module,exports){
+},{}],103:[function(require,module,exports){
var AuthenticationEvents = {
/**
* Event callback arguments:
@@ -29962,7 +29959,7 @@ var AuthenticationEvents = {
};
module.exports = AuthenticationEvents;
-},{}],108:[function(require,module,exports){
+},{}],104:[function(require,module,exports){
var CQEvents = {
LOCALSTATS_UPDATED: "cq.localstats_updated",
REMOTESTATS_UPDATED: "cq.remotestats_updated",
@@ -29970,7 +29967,7 @@ var CQEvents = {
};
module.exports = CQEvents;
-},{}],109:[function(require,module,exports){
+},{}],105:[function(require,module,exports){
var DesktopSharingEventTypes = {
INIT: "ds.init",
@@ -29980,14 +29977,14 @@ var DesktopSharingEventTypes = {
};
module.exports = DesktopSharingEventTypes;
-},{}],110:[function(require,module,exports){
+},{}],106:[function(require,module,exports){
var Events = {
DTMF_SUPPORT_CHANGED: "members.dtmf_support_changed"
};
module.exports = Events;
-},{}],111:[function(require,module,exports){
+},{}],107:[function(require,module,exports){
module.exports = {
getLanguages : function () {
var languages = [];
@@ -30004,7 +30001,7 @@ module.exports = {
TR: "tr",
FR: "fr"
}
-},{}],112:[function(require,module,exports){
+},{}],108:[function(require,module,exports){
var XMPPEvents = {
CONNECTION_FAILED: "xmpp.connection.failed",
CONFERENCE_CREATED: "xmpp.conferenceCreated.jingle",
@@ -30042,7 +30039,7 @@ var XMPPEvents = {
VIDEO_MUTED: "xmpp.video_muted"
};
module.exports = XMPPEvents;
-},{}],113:[function(require,module,exports){
+},{}],109:[function(require,module,exports){
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
@@ -30345,43 +30342,76 @@ function isUndefined(arg) {
return arg === void 0;
}
-},{}],114:[function(require,module,exports){
+},{}],110:[function(require,module,exports){
// shim for using process in browser
var process = module.exports = {};
var queue = [];
var draining = false;
+var currentQueue;
+var queueIndex = -1;
+
+function cleanUpNextTick() {
+ draining = false;
+ if (currentQueue.length) {
+ queue = currentQueue.concat(queue);
+ } else {
+ queueIndex = -1;
+ }
+ if (queue.length) {
+ drainQueue();
+ }
+}
function drainQueue() {
if (draining) {
return;
}
+ var timeout = setTimeout(cleanUpNextTick);
draining = true;
- var currentQueue;
+
var len = queue.length;
while(len) {
currentQueue = queue;
queue = [];
- var i = -1;
- while (++i < len) {
- currentQueue[i]();
+ while (++queueIndex < len) {
+ currentQueue[queueIndex].run();
}
+ queueIndex = -1;
len = queue.length;
}
+ currentQueue = null;
draining = false;
+ clearTimeout(timeout);
}
+
process.nextTick = function (fun) {
- queue.push(fun);
- if (!draining) {
+ var args = new Array(arguments.length - 1);
+ if (arguments.length > 1) {
+ for (var i = 1; i < arguments.length; i++) {
+ args[i - 1] = arguments[i];
+ }
+ }
+ queue.push(new Item(fun, args));
+ if (queue.length === 1 && !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() {}