- *
- * jquery.verto.js - Main interface
- *
- */
-
-(function($) {
- var sources = [];
-
- var generateGUID = (typeof(window.crypto) !== 'undefined' && typeof(window.crypto.getRandomValues) !== 'undefined') ?
- function() {
- // If we have a cryptographically secure PRNG, use that
- // http://stackoverflow.com/questions/6906916/collisions-when-generating-uuids-in-javascript
- var buf = new Uint16Array(8);
- window.crypto.getRandomValues(buf);
- var S4 = function(num) {
- var ret = num.toString(16);
- while (ret.length < 4) {
- ret = "0" + ret;
- }
- return ret;
- };
- return (S4(buf[0]) + S4(buf[1]) + "-" + S4(buf[2]) + "-" + S4(buf[3]) + "-" + S4(buf[4]) + "-" + S4(buf[5]) + S4(buf[6]) + S4(buf[7]));
- }
-
- :
-
- function() {
- // Otherwise, just use Math.random
- // http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#2117523
- return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
- var r = Math.random() * 16 | 0,
- v = c == 'x' ? r : (r & 0x3 | 0x8);
- return v.toString(16);
- });
- };
-
- /// MASTER OBJ
- $.verto = function(options, callbacks) {
- var verto = this;
-
- $.verto.saved.push(verto);
-
- verto.options = $.extend({
- login: null,
- passwd: null,
- socketUrl: null,
- tag: null,
- localTag: null,
- videoParams: {},
- audioParams: {},
- loginParams: {},
- deviceParams: {onResCheck: null},
- userVariables: {},
- iceServers: false,
- ringSleep: 6000,
- sessid: null,
- useStream: null
- }, options);
-
- if (verto.options.deviceParams.useCamera) {
- $.FSRTC.getValidRes(verto.options.deviceParams.useCamera, verto.options.deviceParams.onResCheck);
- }
-
- if (!verto.options.deviceParams.useMic) {
- verto.options.deviceParams.useMic = "any";
- }
-
- if (!verto.options.deviceParams.useSpeak) {
- verto.options.deviceParams.useSpeak = "any";
- }
-
- if (verto.options.sessid) {
- verto.sessid = verto.options.sessid;
- } else {
- verto.sessid = localStorage.getItem("verto_session_uuid") || generateGUID();
- localStorage.setItem("verto_session_uuid", verto.sessid);
- }
-
- verto.dialogs = {};
- verto.callbacks = callbacks || {};
- verto.eventSUBS = {};
-
- verto.rpcClient = new $.JsonRpcClient({
- login: verto.options.login,
- passwd: verto.options.passwd,
- socketUrl: verto.options.socketUrl,
- wsFallbackURL: verto.options.wsFallbackURL,
- turnServer: verto.options.turnServer,
- loginParams: verto.options.loginParams,
- userVariables: verto.options.userVariables,
- sessid: verto.sessid,
- onmessage: function(e) {
- return verto.handleMessage(e.eventData);
- },
- onWSConnect: function(o) {
- o.call('login', {});
- },
- onWSLogin: function(success) {
- if (verto.callbacks.onWSLogin) {
- verto.callbacks.onWSLogin(verto, success);
- }
- },
- onWSClose: function(success) {
- if (verto.callbacks.onWSClose) {
- verto.callbacks.onWSClose(verto, success);
- }
- verto.purge();
- }
- });
-
- var tag = verto.options.tag;
- if (typeof(tag) === "function") {
- tag = tag();
- }
-
- if (verto.options.ringFile && verto.options.tag) {
- verto.ringer = $("#" + tag);
- }
-
- verto.rpcClient.call('login', {});
-
- };
-
-
- $.verto.prototype.deviceParams = function(obj) {
- var verto = this;
-
- for (var i in obj) {
- verto.options.deviceParams[i] = obj[i];
- }
-
- if (obj.useCamera) {
- $.FSRTC.getValidRes(verto.options.deviceParams.useCamera, obj ? obj.onResCheck : undefined);
- }
- };
-
- $.verto.prototype.videoParams = function(obj) {
- var verto = this;
-
- for (var i in obj) {
- verto.options.videoParams[i] = obj[i];
- }
- };
-
- $.verto.prototype.iceServers = function(obj) {
- var verto = this;
- verto.options.iceServers = obj;
- };
-
- $.verto.prototype.loginData = function(params) {
- var verto = this;
- verto.options.login = params.login;
- verto.options.passwd = params.passwd;
- verto.rpcClient.loginData(params);
- };
-
- $.verto.prototype.logout = function(msg) {
- var verto = this;
- verto.rpcClient.closeSocket();
- if (verto.callbacks.onWSClose) {
- verto.callbacks.onWSClose(verto, false);
- }
- verto.purge();
- };
-
- $.verto.prototype.login = function(msg) {
- var verto = this;
- verto.logout();
- verto.rpcClient.call('login', {});
- };
-
- $.verto.prototype.message = function(msg) {
- var verto = this;
- var err = 0;
-
- if (!msg.to) {
- console.error("Missing To");
- err++;
- }
-
- if (!msg.body) {
- console.error("Missing Body");
- err++;
- }
-
- if (err) {
- return false;
- }
-
- verto.sendMethod("verto.info", {
- msg: msg
- });
-
- return true;
- };
-
- $.verto.prototype.processReply = function(method, success, e) {
- var verto = this;
- var i;
-
- //console.log("Response: " + method, success, e);
-
- switch (method) {
- case "verto.subscribe":
- for (i in e.unauthorizedChannels) {
- drop_bad(verto, e.unauthorizedChannels[i]);
- }
- for (i in e.subscribedChannels) {
- mark_ready(verto, e.subscribedChannels[i]);
- }
-
- break;
- case "verto.unsubscribe":
- //console.error(e);
- break;
- }
- };
-
- $.verto.prototype.sendMethod = function(method, params) {
- var verto = this;
-
- verto.rpcClient.call(method, params,
-
- function(e) {
- /* Success */
- verto.processReply(method, true, e);
- },
-
- function(e) {
- /* Error */
- verto.processReply(method, false, e);
- });
- };
-
- function do_sub(verto, channel, obj) {
-
- }
-
- function drop_bad(verto, channel) {
- console.error("drop unauthorized channel: " + channel);
- delete verto.eventSUBS[channel];
- }
-
- function mark_ready(verto, channel) {
- for (var j in verto.eventSUBS[channel]) {
- verto.eventSUBS[channel][j].ready = true;
- console.log("subscribed to channel: " + channel);
- if (verto.eventSUBS[channel][j].readyHandler) {
- verto.eventSUBS[channel][j].readyHandler(verto, channel);
- }
- }
- }
-
- var SERNO = 1;
-
- function do_subscribe(verto, channel, subChannels, sparams) {
- var params = sparams || {};
-
- var local = params.local;
-
- var obj = {
- eventChannel: channel,
- userData: params.userData,
- handler: params.handler,
- ready: false,
- readyHandler: params.readyHandler,
- serno: SERNO++
- };
-
- var isnew = false;
-
- if (!verto.eventSUBS[channel]) {
- verto.eventSUBS[channel] = [];
- subChannels.push(channel);
- isnew = true;
- }
-
- verto.eventSUBS[channel].push(obj);
-
- if (local) {
- obj.ready = true;
- obj.local = true;
- }
-
- if (!isnew && verto.eventSUBS[channel][0].ready) {
- obj.ready = true;
- if (obj.readyHandler) {
- obj.readyHandler(verto, channel);
- }
- }
-
- return {
- serno: obj.serno,
- eventChannel: channel
- };
-
- }
-
- $.verto.prototype.subscribe = function(channel, sparams) {
- var verto = this;
- var r = [];
- var subChannels = [];
- var params = sparams || {};
-
- if (typeof(channel) === "string") {
- r.push(do_subscribe(verto, channel, subChannels, params));
- } else {
- for (var i in channel) {
- r.push(do_subscribe(verto, channel, subChannels, params));
- }
- }
-
- if (subChannels.length) {
- verto.sendMethod("verto.subscribe", {
- eventChannel: subChannels.length == 1 ? subChannels[0] : subChannels,
- subParams: params.subParams
- });
- }
-
- return r;
- };
-
- $.verto.prototype.unsubscribe = function(handle) {
- var verto = this;
- var i;
-
- if (!handle) {
- for (i in verto.eventSUBS) {
- if (verto.eventSUBS[i]) {
- verto.unsubscribe(verto.eventSUBS[i]);
- }
- }
- } else {
- var unsubChannels = {};
- var sendChannels = [];
- var channel;
-
- if (typeof(handle) == "string") {
- delete verto.eventSUBS[handle];
- unsubChannels[handle]++;
- } else {
- for (i in handle) {
- if (typeof(handle[i]) == "string") {
- channel = handle[i];
- delete verto.eventSUBS[channel];
- unsubChannels[channel]++;
- } else {
- var repl = [];
- channel = handle[i].eventChannel;
-
- for (var j in verto.eventSUBS[channel]) {
- if (verto.eventSUBS[channel][j].serno == handle[i].serno) {} else {
- repl.push(verto.eventSUBS[channel][j]);
- }
- }
-
- verto.eventSUBS[channel] = repl;
-
- if (verto.eventSUBS[channel].length === 0) {
- delete verto.eventSUBS[channel];
- unsubChannels[channel]++;
- }
- }
- }
- }
-
- for (var u in unsubChannels) {
- console.log("Sending Unsubscribe for: ", u);
- sendChannels.push(u);
- }
-
- if (sendChannels.length) {
- verto.sendMethod("verto.unsubscribe", {
- eventChannel: sendChannels.length == 1 ? sendChannels[0] : sendChannels
- });
- }
- }
- };
-
- $.verto.prototype.broadcast = function(channel, params) {
- var verto = this;
- var msg = {
- eventChannel: channel,
- data: {}
- };
- for (var i in params) {
- msg.data[i] = params[i];
- }
- verto.sendMethod("verto.broadcast", msg);
- };
-
- $.verto.prototype.purge = function(callID) {
- var verto = this;
- var x = 0;
- var i;
-
- for (i in verto.dialogs) {
- if (!x) {
- console.log("purging dialogs");
- }
- x++;
- verto.dialogs[i].setState($.verto.enum.state.purge);
- }
-
- for (i in verto.eventSUBS) {
- if (verto.eventSUBS[i]) {
- console.log("purging subscription: " + i);
- delete verto.eventSUBS[i];
- }
- }
- };
-
- $.verto.prototype.hangup = function(callID) {
- var verto = this;
- if (callID) {
- var dialog = verto.dialogs[callID];
-
- if (dialog) {
- dialog.hangup();
- }
- } else {
- for (var i in verto.dialogs) {
- verto.dialogs[i].hangup();
- }
- }
- };
-
- $.verto.prototype.newCall = function(args, callbacks) {
- var verto = this;
-
- if (!verto.rpcClient.socketReady()) {
- console.error("Not Connected...");
- return;
- }
-
- if (args["useCamera"]) {
- verto.options.deviceParams["useCamera"] = args["useCamera"];
- }
-
- var dialog = new $.verto.dialog($.verto.enum.direction.outbound, this, args);
-
- if (callbacks) {
- dialog.callbacks = callbacks;
- }
-
- dialog.invite();
-
- return dialog;
- };
-
- $.verto.prototype.handleMessage = function(data) {
- var verto = this;
-
- if (!(data && data.method)) {
- console.error("Invalid Data", data);
- return;
- }
-
- if (data.params.callID) {
- var dialog = verto.dialogs[data.params.callID];
-
- if (data.method === "verto.attach" && dialog) {
- delete dialog.verto.dialogs[dialog.callID];
- dialog.rtc.stop();
- dialog = null;
- }
-
- if (dialog) {
-
- switch (data.method) {
- case 'verto.bye':
- dialog.hangup(data.params);
- break;
- case 'verto.answer':
- dialog.handleAnswer(data.params);
- break;
- case 'verto.media':
- dialog.handleMedia(data.params);
- break;
- case 'verto.display':
- dialog.handleDisplay(data.params);
- break;
- case 'verto.info':
- dialog.handleInfo(data.params);
- break;
- default:
- console.debug("INVALID METHOD OR NON-EXISTANT CALL REFERENCE IGNORED", dialog, data.method);
- break;
- }
- } else {
-
- switch (data.method) {
- case 'verto.attach':
- data.params.attach = true;
-
- if (data.params.sdp && data.params.sdp.indexOf("m=video") > 0) {
- data.params.useVideo = true;
- }
-
- if (data.params.sdp && data.params.sdp.indexOf("stereo=1") > 0) {
- data.params.useStereo = true;
- }
-
- dialog = new $.verto.dialog($.verto.enum.direction.inbound, verto, data.params);
- dialog.setState($.verto.enum.state.recovering);
-
- break;
- case 'verto.invite':
-
- if (data.params.sdp && data.params.sdp.indexOf("m=video") > 0) {
- data.params.wantVideo = true;
- }
-
- if (data.params.sdp && data.params.sdp.indexOf("stereo=1") > 0) {
- data.params.useStereo = true;
- }
-
- dialog = new $.verto.dialog($.verto.enum.direction.inbound, verto, data.params);
- break;
- default:
- console.debug("INVALID METHOD OR NON-EXISTANT CALL REFERENCE IGNORED");
- break;
- }
- }
-
- return {
- method: data.method
- };
- } else {
- switch (data.method) {
- case 'verto.punt':
- verto.purge();
- verto.logout();
- break;
- case 'verto.event':
- var list = null;
- var key = null;
-
- if (data.params) {
- key = data.params.eventChannel;
- }
-
- if (key) {
- list = verto.eventSUBS[key];
-
- if (!list) {
- list = verto.eventSUBS[key.split(".")[0]];
- }
- }
-
- if (!list && key && key === verto.sessid) {
- if (verto.callbacks.onMessage) {
- verto.callbacks.onMessage(verto, null, $.verto.enum.message.pvtEvent, data.params);
- }
- } else if (!list && key && verto.dialogs[key]) {
- verto.dialogs[key].sendMessage($.verto.enum.message.pvtEvent, data.params);
- } else if (!list) {
- if (!key) {
- key = "UNDEFINED";
- }
- console.error("UNSUBBED or invalid EVENT " + key + " IGNORED");
- } else {
- for (var i in list) {
- var sub = list[i];
-
- if (!sub || !sub.ready) {
- console.error("invalid EVENT for " + key + " IGNORED");
- } else if (sub.handler) {
- sub.handler(verto, data.params, sub.userData);
- } else if (verto.callbacks.onEvent) {
- verto.callbacks.onEvent(verto, data.params, sub.userData);
- } else {
- console.log("EVENT:", data.params);
- }
- }
- }
-
- break;
-
- case "verto.info":
- if (verto.callbacks.onMessage) {
- verto.callbacks.onMessage(verto, null, $.verto.enum.message.info, data.params.msg);
- }
- //console.error(data);
- console.debug("MESSAGE from: " + data.params.msg.from, data.params.msg.body);
-
- break;
-
- case 'verto.clientReady':
- if (verto.callbacks.onMessage) {
- verto.callbacks.onMessage(verto, null, $.verto.enum.message.clientReady, data.params);
- }
- console.debug("CLIENT READY", data.params);
- break;
-
- default:
- console.error("INVALID METHOD OR NON-EXISTANT CALL REFERENCE IGNORED", data.method);
- break;
- }
- }
- };
-
- var del_array = function(array, name) {
- var r = [];
- var len = array.length;
-
- for (var i = 0; i < len; i++) {
- if (array[i] != name) {
- r.push(array[i]);
- }
- }
-
- return r;
- };
-
- var hashArray = function() {
- var vha = this;
-
- var hash = {};
- var array = [];
-
- vha.reorder = function(a) {
- array = a;
- var h = hash;
- hash = {};
-
- var len = array.length;
-
- for (var i = 0; i < len; i++) {
- var key = array[i];
- if (h[key]) {
- hash[key] = h[key];
- delete h[key];
- }
- }
- h = undefined;
- };
-
- vha.clear = function() {
- hash = undefined;
- array = undefined;
- hash = {};
- array = [];
- };
-
- vha.add = function(name, val, insertAt) {
- var redraw = false;
-
- if (!hash[name]) {
- if (insertAt === undefined || insertAt < 0 || insertAt >= array.length) {
- array.push(name);
- } else {
- var x = 0;
- var n = [];
- var len = array.length;
-
- for (var i = 0; i < len; i++) {
- if (x++==insertAt) {
- n.push(name);
- }
- n.push(array[i]);
- }
-
- array = undefined;
- array = n;
- n = undefined;
- redraw = true;
- }
- }
-
- hash[name] = val;
-
- return redraw;
- };
-
- vha.del = function(name) {
- var r = false;
-
- if (hash[name]) {
- array = del_array(array, name);
- delete hash[name];
- r = true;
- } else {
- console.error("can't del nonexistant key " + name);
- }
-
- return r;
- };
-
- vha.get = function(name) {
- return hash[name];
- };
-
- vha.order = function() {
- return array;
- };
-
- vha.hash = function() {
- return hash;
- };
-
- vha.indexOf = function(name) {
- var len = array.length;
-
- for (var i = 0; i < len; i++) {
- if (array[i] == name) {
- return i;
- }
- }
- };
-
- vha.arrayLen = function() {
- return array.length;
- };
-
- vha.asArray = function() {
- var r = [];
-
- var len = array.length;
-
- for (var i = 0; i < len; i++) {
- var key = array[i];
- r.push(hash[key]);
- }
-
- return r;
- };
-
- vha.each = function(cb) {
- var len = array.length;
-
- for (var i = 0; i < len; i++) {
- cb(array[i], hash[array[i]]);
- }
- };
-
- vha.dump = function(html) {
- var str = "";
-
- vha.each(function(name, val) {
- str += "name: " + name + " val: " + JSON.stringify(val) + (html ? " " : "\n");
- });
-
- return str;
- };
-
- };
-
- $.verto.liveArray = function(verto, context, name, config) {
- var la = this;
- var lastSerno = 0;
- var binding = null;
- var user_obj = config.userObj;
- var local = false;
-
- // Inherit methods of hashArray
- hashArray.call(la);
-
- // Save the hashArray add, del, reorder, clear methods so we can make our own.
- la._add = la.add;
- la._del = la.del;
- la._reorder = la.reorder;
- la._clear = la.clear;
-
- la.context = context;
- la.name = name;
- la.user_obj = user_obj;
-
- la.verto = verto;
- la.broadcast = function(channel, obj) {
- verto.broadcast(channel, obj);
- };
- la.errs = 0;
-
- la.clear = function() {
- la._clear();
- lastSerno = 0;
-
- if (la.onChange) {
- la.onChange(la, {
- action: "clear"
- });
- }
- };
-
- la.checkSerno = function(serno) {
- if (serno < 0) {
- return true;
- }
-
- if (lastSerno > 0 && serno != (lastSerno + 1)) {
- if (la.onErr) {
- la.onErr(la, {
- lastSerno: lastSerno,
- serno: serno
- });
- }
- la.errs++;
- console.debug(la.errs);
- if (la.errs < 3) {
- la.bootstrap(la.user_obj);
- }
- return false;
- } else {
- lastSerno = serno;
- return true;
- }
- };
-
- la.reorder = function(serno, a) {
- if (la.checkSerno(serno)) {
- la._reorder(a);
- if (la.onChange) {
- la.onChange(la, {
- serno: serno,
- action: "reorder"
- });
- }
- }
- };
-
- la.init = function(serno, val, key, index) {
- if (key === null || key === undefined) {
- key = serno;
- }
- if (la.checkSerno(serno)) {
- if (la.onChange) {
- la.onChange(la, {
- serno: serno,
- action: "init",
- index: index,
- key: key,
- data: val
- });
- }
- }
- };
-
- la.bootObj = function(serno, val) {
- if (la.checkSerno(serno)) {
-
- //la.clear();
- for (var i in val) {
- la._add(val[i][0], val[i][1]);
- }
-
- if (la.onChange) {
- la.onChange(la, {
- serno: serno,
- action: "bootObj",
- data: val,
- redraw: true
- });
- }
- }
- };
-
- // @param serno La is the serial number for la particular request.
- // @param key If looking at it as a hash table, la represents the key in the hashArray object where you want to store the val object.
- // @param index If looking at it as an array, la represents the position in the array where you want to store the val object.
- // @param val La is the object you want to store at the key or index location in the hash table / array.
- la.add = function(serno, val, key, index) {
- if (key === null || key === undefined) {
- key = serno;
- }
- if (la.checkSerno(serno)) {
- var redraw = la._add(key, val, index);
- if (la.onChange) {
- la.onChange(la, {
- serno: serno,
- action: "add",
- index: index,
- key: key,
- data: val,
- redraw: redraw
- });
- }
- }
- };
-
- la.modify = function(serno, val, key, index) {
- if (key === null || key === undefined) {
- key = serno;
- }
- if (la.checkSerno(serno)) {
- la._add(key, val, index);
- if (la.onChange) {
- la.onChange(la, {
- serno: serno,
- action: "modify",
- key: key,
- data: val,
- index: index
- });
- }
- }
- };
-
- la.del = function(serno, key, index) {
- if (key === null || key === undefined) {
- key = serno;
- }
- if (la.checkSerno(serno)) {
- if (index === null || index < 0 || index === undefined) {
- index = la.indexOf(key);
- }
- var ok = la._del(key);
-
- if (ok && la.onChange) {
- la.onChange(la, {
- serno: serno,
- action: "del",
- key: key,
- index: index
- });
- }
- }
- };
-
- var eventHandler = function(v, e, la) {
- var packet = e.data;
-
- //console.error("READ:", packet);
-
- if (packet.name != la.name) {
- return;
- }
-
- switch (packet.action) {
-
- case "init":
- la.init(packet.wireSerno, packet.data, packet.hashKey, packet.arrIndex);
- break;
-
- case "bootObj":
- la.bootObj(packet.wireSerno, packet.data);
- break;
- case "add":
- la.add(packet.wireSerno, packet.data, packet.hashKey, packet.arrIndex);
- break;
-
- case "modify":
- if (! (packet.arrIndex || packet.hashKey)) {
- console.error("Invalid Packet", packet);
- } else {
- la.modify(packet.wireSerno, packet.data, packet.hashKey, packet.arrIndex);
- }
- break;
- case "del":
- if (! (packet.arrIndex || packet.hashKey)) {
- console.error("Invalid Packet", packet);
- } else {
- la.del(packet.wireSerno, packet.hashKey, packet.arrIndex);
- }
- break;
-
- case "clear":
- la.clear();
- break;
-
- case "reorder":
- la.reorder(packet.wireSerno, packet.order);
- break;
-
- default:
- if (la.checkSerno(packet.wireSerno)) {
- if (la.onChange) {
- la.onChange(la, {
- serno: packet.wireSerno,
- action: packet.action,
- data: packet.data
- });
- }
- }
- break;
- }
- };
-
- if (la.context) {
- binding = la.verto.subscribe(la.context, {
- handler: eventHandler,
- userData: la,
- subParams: config.subParams
- });
- }
-
- la.destroy = function() {
- la._clear();
- la.verto.unsubscribe(binding);
- };
-
- la.sendCommand = function(cmd, obj) {
- var self = la;
- self.broadcast(self.context, {
- liveArray: {
- command: cmd,
- context: self.context,
- name: self.name,
- obj: obj
- }
- });
- };
-
- la.bootstrap = function(obj) {
- var self = la;
- la.sendCommand("bootstrap", obj);
- //self.heartbeat();
- };
-
- la.changepage = function(obj) {
- var self = la;
- self.clear();
- self.broadcast(self.context, {
- liveArray: {
- command: "changepage",
- context: la.context,
- name: la.name,
- obj: obj
- }
- });
- };
-
- la.heartbeat = function(obj) {
- var self = la;
-
- var callback = function() {
- self.heartbeat.call(self, obj);
- };
- self.broadcast(self.context, {
- liveArray: {
- command: "heartbeat",
- context: self.context,
- name: self.name,
- obj: obj
- }
- });
- self.hb_pid = setTimeout(callback, 30000);
- };
-
- la.bootstrap(la.user_obj);
- };
-
- $.verto.liveTable = function(verto, context, name, jq, config) {
- var dt;
- var la = new $.verto.liveArray(verto, context, name, {
- subParams: config.subParams
- });
- var lt = this;
-
- lt.liveArray = la;
- lt.dataTable = dt;
- lt.verto = verto;
-
- lt.destroy = function() {
- if (dt) {
- dt.fnDestroy();
- }
- if (la) {
- la.destroy();
- }
-
- dt = null;
- la = null;
- };
-
- la.onErr = function(obj, args) {
- console.error("Error: ", obj, args);
- };
-
- /* back compat so jsonstatus can always be enabled */
- function genRow(data) {
- if (typeof(data[4]) === "string" && data[4].indexOf("{") > -1) {
- var tmp = $.parseJSON(data[4]);
- data[4] = tmp.oldStatus;
- data[5] = null;
- }
- return data;
- }
-
- function genArray(obj) {
- var data = obj.asArray();
-
- for (var i in data) {
- data[i] = genRow(data[i]);
- }
-
- return data;
- }
-
-
- la.onChange = function(obj, args) {
- var index = 0;
- var iserr = 0;
-
- if (!dt) {
- if (!config.aoColumns) {
- if (args.action != "init") {
- return;
- }
-
- config.aoColumns = [];
-
- for (var i in args.data) {
- config.aoColumns.push({
- "sTitle": args.data[i]
- });
- }
- }
-
- dt = jq.dataTable(config);
- }
-
- if (dt && (args.action == "del" || args.action == "modify")) {
- index = args.index;
-
- if (index === undefined && args.key) {
- index = la.indexOf(args.key);
- }
-
- if (index === undefined) {
- console.error("INVALID PACKET Missing INDEX\n", args);
- return;
- }
- }
-
- if (config.onChange) {
- config.onChange(obj, args);
- }
-
- try {
- switch (args.action) {
- case "bootObj":
- if (!args.data) {
- console.error("missing data");
- return;
- }
- dt.fnClearTable();
- dt.fnAddData(genArray(obj));
- dt.fnAdjustColumnSizing();
- break;
- case "add":
- if (!args.data) {
- console.error("missing data");
- return;
- }
- if (args.redraw > -1) {
- // specific position, more costly
- dt.fnClearTable();
- dt.fnAddData(genArray(obj));
- } else {
- dt.fnAddData(genRow(args.data));
- }
- dt.fnAdjustColumnSizing();
- break;
- case "modify":
- if (!args.data) {
- return;
- }
- //console.debug(args, index);
- dt.fnUpdate(genRow(args.data), index);
- dt.fnAdjustColumnSizing();
- break;
- case "del":
- dt.fnDeleteRow(index);
- dt.fnAdjustColumnSizing();
- break;
- case "clear":
- dt.fnClearTable();
- break;
- case "reorder":
- // specific position, more costly
- dt.fnClearTable();
- dt.fnAddData(genArray(obj));
- break;
- case "hide":
- jq.hide();
- break;
-
- case "show":
- jq.show();
- break;
-
- }
- } catch(err) {
- console.error("ERROR: " + err);
- iserr++;
- }
-
- if (iserr) {
- obj.errs++;
- if (obj.errs < 3) {
- obj.bootstrap(obj.user_obj);
- }
- } else {
- obj.errs = 0;
- }
-
- };
-
- la.onChange(la, {
- action: "init"
- });
-
- };
-
- var CONFMAN_SERNO = 1;
-
- /*
- Conference Manager without jQuery table.
- */
-
- $.verto.conf = function(verto, params) {
- var conf = this;
-
- conf.params = $.extend({
- dialog: null,
- hasVid: false,
- laData: null,
- onBroadcast: null,
- onLaChange: null,
- onLaRow: null
- }, params);
-
- conf.verto = verto;
- conf.serno = CONFMAN_SERNO++;
-
- createMainModeratorMethods();
-
- verto.subscribe(conf.params.laData.modChannel, {
- handler: function(v, e) {
- if (conf.params.onBroadcast) {
- conf.params.onBroadcast(verto, conf, e.data);
- }
- }
- });
-
- verto.subscribe(conf.params.laData.infoChannel, {
- handler: function(v, e) {
- if (typeof(conf.params.infoCallback) === "function") {
- conf.params.infoCallback(v,e);
- }
- }
- });
-
- verto.subscribe(conf.params.laData.chatChannel, {
- handler: function(v, e) {
- if (typeof(conf.params.chatCallback) === "function") {
- conf.params.chatCallback(v,e);
- }
- }
- });
- };
-
- $.verto.conf.prototype.modCommand = function(cmd, id, value) {
- var conf = this;
-
- conf.verto.rpcClient.call("verto.broadcast", {
- "eventChannel": conf.params.laData.modChannel,
- "data": {
- "application": "conf-control",
- "command": cmd,
- "id": id,
- "value": value
- }
- });
- };
-
- $.verto.conf.prototype.destroy = function() {
- var conf = this;
-
- conf.destroyed = true;
- conf.params.onBroadcast(conf.verto, conf, 'destroy');
-
- if (conf.params.laData.modChannel) {
- conf.verto.unsubscribe(conf.params.laData.modChannel);
- }
-
- if (conf.params.laData.chatChannel) {
- conf.verto.unsubscribe(conf.params.laData.chatChannel);
- }
-
- if (conf.params.laData.infoChannel) {
- conf.verto.unsubscribe(conf.params.laData.infoChannel);
- }
- };
-
- function createMainModeratorMethods() {
- $.verto.conf.prototype.listVideoLayouts = function() {
- this.modCommand("list-videoLayouts", null, null);
- };
-
- $.verto.conf.prototype.play = function(file) {
- this.modCommand("play", null, file);
- };
-
- $.verto.conf.prototype.stop = function() {
- this.modCommand("stop", null, "all");
- };
-
- $.verto.conf.prototype.deaf = function(memberID) {
- this.modCommand("deaf", parseInt(memberID));
- };
-
- $.verto.conf.prototype.undeaf = function(memberID) {
- this.modCommand("undeaf", parseInt(memberID));
- };
-
- $.verto.conf.prototype.record = function(file) {
- this.modCommand("recording", null, ["start", file]);
- };
-
- $.verto.conf.prototype.stopRecord = function() {
- this.modCommand("recording", null, ["stop", "all"]);
- };
-
- $.verto.conf.prototype.snapshot = function(file) {
- if (!this.params.hasVid) {
- throw 'Conference has no video';
- }
- this.modCommand("vid-write-png", null, file);
- };
-
- $.verto.conf.prototype.setVideoLayout = function(layout, canvasID) {
- if (!this.params.hasVid) {
- throw 'Conference has no video';
- }
- if (canvasID) {
- this.modCommand("vid-layout", null, [layout, canvasID]);
- } else {
- this.modCommand("vid-layout", null, layout);
- }
- };
-
- $.verto.conf.prototype.kick = function(memberID) {
- this.modCommand("kick", parseInt(memberID));
- };
-
- $.verto.conf.prototype.muteMic = function(memberID) {
- this.modCommand("tmute", parseInt(memberID));
- };
-
- $.verto.conf.prototype.muteVideo = function(memberID) {
- if (!this.params.hasVid) {
- throw 'Conference has no video';
- }
- this.modCommand("tvmute", parseInt(memberID));
- };
-
- $.verto.conf.prototype.presenter = function(memberID) {
- if (!this.params.hasVid) {
- throw 'Conference has no video';
- }
- this.modCommand("vid-res-id", parseInt(memberID), "presenter");
- };
-
- $.verto.conf.prototype.videoFloor = function(memberID) {
- if (!this.params.hasVid) {
- throw 'Conference has no video';
- }
- this.modCommand("vid-floor", parseInt(memberID), "force");
- };
-
- $.verto.conf.prototype.banner = function(memberID, text) {
- if (!this.params.hasVid) {
- throw 'Conference has no video';
- }
- this.modCommand("vid-banner", parseInt(memberID), escape(text));
- };
-
- $.verto.conf.prototype.volumeDown = function(memberID) {
- this.modCommand("volume_out", parseInt(memberID), "down");
- };
-
- $.verto.conf.prototype.volumeUp = function(memberID) {
- this.modCommand("volume_out", parseInt(memberID), "up");
- };
-
- $.verto.conf.prototype.gainDown = function(memberID) {
- this.modCommand("volume_in", parseInt(memberID), "down");
- };
-
- $.verto.conf.prototype.gainUp = function(memberID) {
- this.modCommand("volume_in", parseInt(memberID), "up");
- };
-
- $.verto.conf.prototype.transfer = function(memberID, exten) {
- this.modCommand("transfer", parseInt(memberID), exten);
- };
-
- $.verto.conf.prototype.sendChat = function(message, type) {
- var conf = this;
- conf.verto.rpcClient.call("verto.broadcast", {
- "eventChannel": conf.params.laData.chatChannel,
- "data": {
- "action": "send",
- "message": message,
- "type": type
- }
- });
- };
-
- }
-
- $.verto.modfuncs = {};
-
- $.verto.confMan = function(verto, params) {
- var confMan = this;
-
- confMan.params = $.extend({
- tableID: null,
- statusID: null,
- mainModID: null,
- dialog: null,
- hasVid: false,
- laData: null,
- onBroadcast: null,
- onLaChange: null,
- onLaRow: null
- }, params);
-
- confMan.verto = verto;
- confMan.serno = CONFMAN_SERNO++;
- confMan.canvasCount = confMan.params.laData.canvasCount;
-
- function genMainMod(jq) {
- var play_id = "play_" + confMan.serno;
- var stop_id = "stop_" + confMan.serno;
- var recording_id = "recording_" + confMan.serno;
- var snapshot_id = "snapshot_" + confMan.serno;
- var rec_stop_id = "recording_stop" + confMan.serno;
- var div_id = "confman_" + confMan.serno;
-
- var html = " " +
- "Play " +
- "Stop " +
- "Record " +
- "Record Stop " +
- (confMan.params.hasVid ? "PNG Snapshot " : "") +
- "
";
-
- jq.html(html);
-
- $.verto.modfuncs.change_video_layout = function(id, canvas_id) {
- var val = $("#" + id + " option:selected").text();
- if (val !== "none") {
- confMan.modCommand("vid-layout", null, [val, canvas_id]);
- }
- };
-
- if (confMan.params.hasVid) {
- for (var j = 0; j < confMan.canvasCount; j++) {
- var vlayout_id = "confman_vid_layout_" + j + "_" + confMan.serno;
- var vlselect_id = "confman_vl_select_" + j + "_" + confMan.serno;
-
-
- var vlhtml = " " +
- "Video Layout Canvas " + (j+1) +
- " " +
- "
";
- jq.append(vlhtml);
- }
-
- $("#" + snapshot_id).click(function() {
- var file = prompt("Please enter file name", "");
- if (file) {
- confMan.modCommand("vid-write-png", null, file);
- }
- });
- }
-
- $("#" + play_id).click(function() {
- var file = prompt("Please enter file name", "");
- if (file) {
- confMan.modCommand("play", null, file);
- }
- });
-
- $("#" + stop_id).click(function() {
- confMan.modCommand("stop", null, "all");
- });
-
- $("#" + recording_id).click(function() {
- var file = prompt("Please enter file name", "");
- if (file) {
- confMan.modCommand("recording", null, ["start", file]);
- }
- });
-
- $("#" + rec_stop_id).click(function() {
- confMan.modCommand("recording", null, ["stop", "all"]);
- });
-
- }
-
- function genControls(jq, rowid) {
- var x = parseInt(rowid);
- var kick_id = "kick_" + x;
- var canvas_in_next_id = "canvas_in_next_" + x;
- var canvas_in_prev_id = "canvas_in_prev_" + x;
- var canvas_out_next_id = "canvas_out_next_" + x;
- var canvas_out_prev_id = "canvas_out_prev_" + x;
-
- var canvas_in_set_id = "canvas_in_set_" + x;
- var canvas_out_set_id = "canvas_out_set_" + x;
-
- var layer_set_id = "layer_set_" + x;
- var layer_next_id = "layer_next_" + x;
- var layer_prev_id = "layer_prev_" + x;
-
- var tmute_id = "tmute_" + x;
- var tvmute_id = "tvmute_" + x;
- var vbanner_id = "vbanner_" + x;
- var tvpresenter_id = "tvpresenter_" + x;
- var tvfloor_id = "tvfloor_" + x;
- var box_id = "box_" + x;
- var gainup_id = "gain_in_up" + x;
- var gaindn_id = "gain_in_dn" + x;
- var volup_id = "vol_in_up" + x;
- var voldn_id = "vol_in_dn" + x;
- var transfer_id = "transfer" + x;
-
-
- var html = "";
-
- html += "General Controls
";
-
- html += "Kick " +
- "Mute " +
- "Gain - " +
- "Gain + " +
- "Vol - " +
- "Vol + " +
- "Transfer ";
-
- if (confMan.params.hasVid) {
- html += "Video Controls ";
-
-
- html += "VMute " +
- "Presenter " +
- "Vid Floor " +
- "Banner ";
-
- if (confMan.canvasCount > 1) {
- html += "Canvas Controls " +
- "Set Input Canvas " +
- "Prev Input Canvas " +
- "Next Input Canvas " +
-
- " " +
-
- "Set Watching Canvas " +
- "Prev Watching Canvas " +
- "Next Watching Canvas ";
- }
-
- html += " " +
-
- "Set Layer " +
- "Prev Layer " +
- "Next Layer " +
-
-
-
- "";
- }
-
- jq.html(html);
-
-
- if (!jq.data("mouse")) {
- $("#" + box_id).hide();
- }
-
- jq.mouseover(function(e) {
- jq.data({"mouse": true});
- $("#" + box_id).show();
- });
-
- jq.mouseout(function(e) {
- jq.data({"mouse": false});
- $("#" + box_id).hide();
- });
-
- $("#" + transfer_id).click(function() {
- var xten = prompt("Enter Extension");
- if (xten) {
- confMan.modCommand("transfer", x, xten);
- }
- });
-
- $("#" + kick_id).click(function() {
- confMan.modCommand("kick", x);
- });
-
-
- $("#" + layer_set_id).click(function() {
- var cid = prompt("Please enter layer ID", "");
- if (cid) {
- confMan.modCommand("vid-layer", x, cid);
- }
- });
-
- $("#" + layer_next_id).click(function() {
- confMan.modCommand("vid-layer", x, "next");
- });
- $("#" + layer_prev_id).click(function() {
- confMan.modCommand("vid-layer", x, "prev");
- });
-
- $("#" + canvas_in_set_id).click(function() {
- var cid = prompt("Please enter canvas ID", "");
- if (cid) {
- confMan.modCommand("vid-canvas", x, cid);
- }
- });
-
- $("#" + canvas_out_set_id).click(function() {
- var cid = prompt("Please enter canvas ID", "");
- if (cid) {
- confMan.modCommand("vid-watching-canvas", x, cid);
- }
- });
-
- $("#" + canvas_in_next_id).click(function() {
- confMan.modCommand("vid-canvas", x, "next");
- });
- $("#" + canvas_in_prev_id).click(function() {
- confMan.modCommand("vid-canvas", x, "prev");
- });
-
-
- $("#" + canvas_out_next_id).click(function() {
- confMan.modCommand("vid-watching-canvas", x, "next");
- });
- $("#" + canvas_out_prev_id).click(function() {
- confMan.modCommand("vid-watching-canvas", x, "prev");
- });
-
- $("#" + tmute_id).click(function() {
- confMan.modCommand("tmute", x);
- });
-
- if (confMan.params.hasVid) {
- $("#" + tvmute_id).click(function() {
- confMan.modCommand("tvmute", x);
- });
- $("#" + tvpresenter_id).click(function() {
- confMan.modCommand("vid-res-id", x, "presenter");
- });
- $("#" + tvfloor_id).click(function() {
- confMan.modCommand("vid-floor", x, "force");
- });
- $("#" + vbanner_id).click(function() {
- var text = prompt("Please enter text", "");
- if (text) {
- confMan.modCommand("vid-banner", x, escape(text));
- }
- });
- }
-
- $("#" + gainup_id).click(function() {
- confMan.modCommand("volume_in", x, "up");
- });
-
- $("#" + gaindn_id).click(function() {
- confMan.modCommand("volume_in", x, "down");
- });
-
- $("#" + volup_id).click(function() {
- confMan.modCommand("volume_out", x, "up");
- });
-
- $("#" + voldn_id).click(function() {
- confMan.modCommand("volume_out", x, "down");
- });
-
- return html;
- }
-
- var atitle = "";
- var awidth = 0;
-
- //$(".jsDataTable").width(confMan.params.hasVid ? "900px" : "800px");
-
- verto.subscribe(confMan.params.laData.infoChannel, {
- handler: function(v, e) {
- if (typeof(confMan.params.infoCallback) === "function") {
- confMan.params.infoCallback(v,e);
- }
- }
- });
-
- verto.subscribe(confMan.params.laData.chatChannel, {
- handler: function(v, e) {
- if (typeof(confMan.params.chatCallback) === "function") {
- confMan.params.chatCallback(v,e);
- }
- }
- });
-
- if (confMan.params.laData.role === "moderator") {
- atitle = "Action";
- awidth = 600;
-
- if (confMan.params.mainModID) {
- genMainMod($(confMan.params.mainModID));
- $(confMan.params.displayID).html("Moderator Controls Ready ");
- } else {
- $(confMan.params.mainModID).html("");
- }
-
- verto.subscribe(confMan.params.laData.modChannel, {
- handler: function(v, e) {
- //console.error("MODDATA:", e.data);
- if (confMan.params.onBroadcast) {
- confMan.params.onBroadcast(verto, confMan, e.data);
- }
-
- if (e.data["conf-command"] === "list-videoLayouts") {
- for (var j = 0; j < confMan.canvasCount; j++) {
- var vlselect_id = "#confman_vl_select_" + j + "_" + confMan.serno;
- var vlayout_id = "#confman_vid_layout_" + j + "_" + confMan.serno;
-
- var x = 0;
- var options;
-
- $(vlselect_id).selectmenu({});
- $(vlselect_id).selectmenu("enable");
- $(vlselect_id).empty();
-
- $(vlselect_id).append(new Option("Choose a Layout", "none"));
-
- if (e.data.responseData) {
- var rdata = [];
-
- for (var i in e.data.responseData) {
- rdata.push(e.data.responseData[i].name);
- }
-
- options = rdata.sort(function(a, b) {
- var ga = a.substring(0, 6) == "group:" ? true : false;
- var gb = b.substring(0, 6) == "group:" ? true : false;
-
- if ((ga || gb) && ga != gb) {
- return ga ? -1 : 1;
- }
-
- return ( ( a == b ) ? 0 : ( ( a > b ) ? 1 : -1 ) );
- });
-
- for (var i in options) {
- $(vlselect_id).append(new Option(options[i], options[i]));
- x++;
- }
- }
-
- if (x) {
- $(vlselect_id).selectmenu('refresh', true);
- } else {
- $(vlayout_id).hide();
- }
- }
- } else {
-
- if (!confMan.destroyed && confMan.params.displayID) {
- $(confMan.params.displayID).html(e.data.response + " ");
- if (confMan.lastTimeout) {
- clearTimeout(confMan.lastTimeout);
- confMan.lastTimeout = 0;
- }
- confMan.lastTimeout = setTimeout(function() { $(confMan.params.displayID).html(confMan.destroyed ? "" : "Moderator Controls Ready ");}, 4000);
- }
- }
- }
- });
-
-
- if (confMan.params.hasVid) {
- confMan.modCommand("list-videoLayouts", null, null);
- }
- }
-
- var row_callback = null;
-
- if (confMan.params.laData.role === "moderator") {
- row_callback = function(nRow, aData, iDisplayIndex, iDisplayIndexFull) {
- if (!aData[5]) {
- var $row = $('td:eq(5)', nRow);
- genControls($row, aData);
-
- if (confMan.params.onLaRow) {
- confMan.params.onLaRow(verto, confMan, $row, aData);
- }
- }
- };
- }
-
- confMan.lt = new $.verto.liveTable(verto, confMan.params.laData.laChannel, confMan.params.laData.laName, $(confMan.params.tableID), {
- subParams: {
- callID: confMan.params.dialog ? confMan.params.dialog.callID : null
- },
-
- "onChange": function(obj, args) {
- $(confMan.params.statusID).text("Conference Members: " + " (" + obj.arrayLen() + " Total)");
- if (confMan.params.onLaChange) {
- confMan.params.onLaChange(verto, confMan, $.verto.enum.confEvent.laChange, obj, args);
- }
- },
-
- "aaData": [],
- "aoColumns": [
- {
- "sTitle": "ID",
- "sWidth": "50"
- },
- {
- "sTitle": "Number",
- "sWidth": "250"
- },
- {
- "sTitle": "Name",
- "sWidth": "250"
- },
- {
- "sTitle": "Codec",
- "sWidth": "100"
- },
- {
- "sTitle": "Status",
- "sWidth": confMan.params.hasVid ? "200px" : "150px"
- },
- {
- "sTitle": atitle,
- "sWidth": awidth,
- }
- ],
- "bAutoWidth": true,
- "bDestroy": true,
- "bSort": false,
- "bInfo": false,
- "bFilter": false,
- "bLengthChange": false,
- "bPaginate": false,
- "iDisplayLength": 1400,
-
- "oLanguage": {
- "sEmptyTable": "The Conference is Empty....."
- },
-
- "fnRowCallback": row_callback
-
- });
- };
-
- $.verto.confMan.prototype.modCommand = function(cmd, id, value) {
- var confMan = this;
-
- confMan.verto.rpcClient.call("verto.broadcast", {
- "eventChannel": confMan.params.laData.modChannel,
- "data": {
- "application": "conf-control",
- "command": cmd,
- "id": id,
- "value": value
- }
- });
- };
-
- $.verto.confMan.prototype.sendChat = function(message, type) {
- var confMan = this;
- confMan.verto.rpcClient.call("verto.broadcast", {
- "eventChannel": confMan.params.laData.chatChannel,
- "data": {
- "action": "send",
- "message": message,
- "type": type
- }
- });
- };
-
-
- $.verto.confMan.prototype.destroy = function() {
- var confMan = this;
-
- confMan.destroyed = true;
-
- if (confMan.lt) {
- confMan.lt.destroy();
- }
-
- if (confMan.params.laData.chatChannel) {
- confMan.verto.unsubscribe(confMan.params.laData.chatChannel);
- }
-
- if (confMan.params.laData.modChannel) {
- confMan.verto.unsubscribe(confMan.params.laData.modChannel);
- }
-
- if (confMan.params.mainModID) {
- $(confMan.params.mainModID).html("");
- }
- };
-
- $.verto.dialog = function(direction, verto, params) {
- var dialog = this;
-
- dialog.params = $.extend({
- useVideo: verto.options.useVideo,
- useStereo: verto.options.useStereo,
- screenShare: false,
- useCamera: false,
- useMic: verto.options.deviceParams.useMic,
- useSpeak: verto.options.deviceParams.useSpeak,
- tag: verto.options.tag,
- localTag: verto.options.localTag,
- login: verto.options.login,
- videoParams: verto.options.videoParams,
- useStream: verto.options.useStream,
- }, params);
-
-
- if (!dialog.params.screenShare) {
- dialog.params.useCamera = verto.options.deviceParams.useCamera;
- }
-
- dialog.verto = verto;
- dialog.direction = direction;
- dialog.lastState = null;
- dialog.state = dialog.lastState = $.verto.enum.state.new;
- dialog.callbacks = verto.callbacks;
- dialog.answered = false;
- dialog.attach = params.attach || false;
- dialog.screenShare = params.screenShare || false;
- dialog.useCamera = dialog.params.useCamera;
- dialog.useMic = dialog.params.useMic;
- dialog.useSpeak = dialog.params.useSpeak;
-
- if (dialog.params.callID) {
- dialog.callID = dialog.params.callID;
- } else {
- dialog.callID = dialog.params.callID = generateGUID();
- }
-
- if (typeof(dialog.params.tag) === "function") {
- dialog.params.tag = dialog.params.tag();
- }
-
- if (dialog.params.tag) {
- dialog.audioStream = document.getElementById(dialog.params.tag);
-
- if (dialog.params.useVideo) {
- dialog.videoStream = dialog.audioStream;
- }
- } //else conjure one TBD
-
- if (dialog.params.localTag) {
- dialog.localVideo = document.getElementById(dialog.params.localTag);
- }
-
- dialog.verto.dialogs[dialog.callID] = dialog;
-
- var RTCcallbacks = {};
-
- if (dialog.direction == $.verto.enum.direction.inbound) {
- if (dialog.params.display_direction === "outbound") {
- dialog.params.remote_caller_id_name = dialog.params.caller_id_name;
- dialog.params.remote_caller_id_number = dialog.params.caller_id_number;
- } else {
- dialog.params.remote_caller_id_name = dialog.params.callee_id_name;
- dialog.params.remote_caller_id_number = dialog.params.callee_id_number;
- }
-
- if (!dialog.params.remote_caller_id_name) {
- dialog.params.remote_caller_id_name = "Nobody";
- }
-
- if (!dialog.params.remote_caller_id_number) {
- dialog.params.remote_caller_id_number = "UNKNOWN";
- }
-
- RTCcallbacks.onMessage = function(rtc, msg) {
- console.debug(msg);
- };
-
- RTCcallbacks.onAnswerSDP = function(rtc, sdp) {
- console.error("answer sdp", sdp);
- };
- } else {
- dialog.params.remote_caller_id_name = "Outbound Call";
- dialog.params.remote_caller_id_number = dialog.params.destination_number;
- }
-
- RTCcallbacks.onICESDP = function(rtc) {
- console.log("RECV " + rtc.type + " SDP", rtc.mediaData.SDP);
-
- if (dialog.state == $.verto.enum.state.requesting || dialog.state == $.verto.enum.state.answering || dialog.state == $.verto.enum.state.active) {
- location.reload();
- return;
- }
-
- if (rtc.type == "offer") {
- if (dialog.state == $.verto.enum.state.active) {
- dialog.setState($.verto.enum.state.requesting);
- dialog.sendMethod("verto.attach", {
- sdp: rtc.mediaData.SDP
- });
- } else {
- dialog.setState($.verto.enum.state.requesting);
-
- dialog.sendMethod("verto.invite", {
- sdp: rtc.mediaData.SDP
- });
- }
- } else { //answer
- dialog.setState($.verto.enum.state.answering);
-
- dialog.sendMethod(dialog.attach ? "verto.attach" : "verto.answer", {
- sdp: dialog.rtc.mediaData.SDP
- });
- }
- };
-
- RTCcallbacks.onICE = function(rtc) {
- //console.log("cand", rtc.mediaData.candidate);
- if (rtc.type == "offer") {
- console.log("offer", rtc.mediaData.candidate);
- return;
- }
- };
-
- RTCcallbacks.onStream = function(rtc, stream) {
- if (dialog.callbacks.permissionCallback &&
- typeof dialog.callbacks.permissionCallback.onGranted === 'function') {
- dialog.callbacks.permissionCallback.onGranted(stream);
- }
- else if (dialog.verto.options.permissionCallback &&
- typeof dialog.verto.options.permissionCallback.onGranted === 'function'){
- dialog.verto.options.permissionCallback.onGranted(stream);
- }
- console.log("stream started");
- };
-
- RTCcallbacks.onRemoteStream = function(rtc, stream) {
- if (typeof dialog.callbacks.onRemoteStream === 'function') {
- dialog.callbacks.onRemoteStream(stream, dialog);
- }
- console.log("remote stream started");
- };
-
- RTCcallbacks.onError = function(e) {
- if (dialog.callbacks.permissionCallback &&
- typeof dialog.callbacks.permissionCallback.onDenied === 'function') {
- dialog.callbacks.permissionCallback.onDenied();
- }
- else if (dialog.verto.options.permissionCallback &&
- typeof dialog.verto.options.permissionCallback.onDenied === 'function'){
- dialog.verto.options.permissionCallback.onDenied();
- }
- console.error("ERROR:", e);
- dialog.hangup({cause: "Device or Permission Error"});
- };
-
- dialog.rtc = new $.FSRTC({
- callbacks: RTCcallbacks,
- localVideo: dialog.screenShare ? null : dialog.localVideo,
- useVideo: dialog.params.useVideo ? dialog.videoStream : null,
- useAudio: dialog.audioStream,
- useStereo: dialog.params.useStereo,
- videoParams: dialog.params.videoParams,
- audioParams: verto.options.audioParams,
- iceServers: verto.options.iceServers,
- screenShare: dialog.screenShare,
- useCamera: dialog.useCamera,
- useMic: dialog.useMic,
- useSpeak: dialog.useSpeak,
- turnServer: verto.options.turnServer,
- useStream: dialog.params.useStream
- });
-
- dialog.rtc.verto = dialog.verto;
-
- if (dialog.direction == $.verto.enum.direction.inbound) {
- if (dialog.attach) {
- dialog.answer();
- } else {
- dialog.ring();
- }
- }
- };
-
- $.verto.dialog.prototype.invite = function() {
- var dialog = this;
- dialog.rtc.call();
- };
-
- $.verto.dialog.prototype.sendMethod = function(method, obj) {
- var dialog = this;
- obj.dialogParams = {};
-
- for (var i in dialog.params) {
- if (i == "sdp" && method != "verto.invite" && method != "verto.attach") {
- continue;
- }
-
- if ((obj.noDialogParams && i != "callID")) {
- continue;
- }
-
- obj.dialogParams[i] = dialog.params[i];
- }
-
- delete obj.noDialogParams;
-
- dialog.verto.rpcClient.call(method, obj,
-
- function(e) {
- /* Success */
- dialog.processReply(method, true, e);
- },
-
- function(e) {
- /* Error */
- dialog.processReply(method, false, e);
- });
- };
-
- function checkStateChange(oldS, newS) {
-
- if (newS == $.verto.enum.state.purge || $.verto.enum.states[oldS.name][newS.name]) {
- return true;
- }
-
- return false;
- }
-
-
- // Attach audio output device to video element using device/sink ID.
- function find_name(id) {
- for (var i in $.verto.audioOutDevices) {
- var source = $.verto.audioOutDevices[i];
- if (source.id === id) {
- return(source.label);
- }
- }
-
- return id;
- }
-
- $.verto.dialog.prototype.setAudioPlaybackDevice = function(sinkId, callback, arg) {
- var dialog = this;
- var element = dialog.audioStream;
-
- if (typeof element.sinkId !== 'undefined') {
- var devname = find_name(sinkId);
- console.info("Dialog: " + dialog.callID + " Setting speaker:", element, devname);
-
- element.setSinkId(sinkId)
- .then(function() {
- console.log("Dialog: " + dialog.callID + ' Success, audio output device attached: ' + sinkId);
- if (callback) {
- callback(true, devname, arg);
- }
- })
- .catch(function(error) {
- var errorMessage = error;
- if (error.name === 'SecurityError') {
- errorMessage = "Dialog: " + dialog.callID + ' You need to use HTTPS for selecting audio output ' +
- 'device: ' + error;
- }
- if (callback) {
- callback(false, null, arg);
- }
- console.error(errorMessage);
- });
- } else {
- console.warn("Dialog: " + dialog.callID + ' Browser does not support output device selection.');
- if (callback) {
- callback(false, null, arg);
- }
- }
- }
-
- $.verto.dialog.prototype.setState = function(state) {
- var dialog = this;
-
- if (dialog.state == $.verto.enum.state.ringing) {
- dialog.stopRinging();
- }
-
- if (dialog.state == state || !checkStateChange(dialog.state, state)) {
- console.error("Dialog " + dialog.callID + ": INVALID state change from " + dialog.state.name + " to " + state.name);
- dialog.hangup();
- return false;
- }
-
- console.log("Dialog " + dialog.callID + ": state change from " + dialog.state.name + " to " + state.name);
-
- dialog.lastState = dialog.state;
- dialog.state = state;
-
- if (dialog.callbacks.onDialogState) {
- dialog.callbacks.onDialogState(this);
- }
-
- switch (dialog.state) {
-
- case $.verto.enum.state.early:
- case $.verto.enum.state.active:
-
- var speaker = dialog.useSpeak;
- console.info("Using Speaker: ", speaker);
-
- if (speaker && speaker !== "any" && speaker !== "none") {
- setTimeout(function() {
- dialog.setAudioPlaybackDevice(speaker);
- }, 500);
- }
-
- break;
-
- case $.verto.enum.state.trying:
- setTimeout(function() {
- if (dialog.state == $.verto.enum.state.trying) {
- dialog.setState($.verto.enum.state.hangup);
- }
- }, 30000);
- break;
- case $.verto.enum.state.purge:
- dialog.setState($.verto.enum.state.destroy);
- break;
- case $.verto.enum.state.hangup:
-
- if (dialog.lastState.val > $.verto.enum.state.requesting.val && dialog.lastState.val < $.verto.enum.state.hangup.val) {
- dialog.sendMethod("verto.bye", {});
- }
-
- dialog.setState($.verto.enum.state.destroy);
- break;
- case $.verto.enum.state.destroy:
-
- if (typeof(dialog.verto.options.tag) === "function") {
- $('#' + dialog.params.tag).remove();
- }
-
- delete dialog.verto.dialogs[dialog.callID];
- if (dialog.params.screenShare) {
- dialog.rtc.stopPeer();
- } else {
- dialog.rtc.stop();
- }
- break;
- }
-
- return true;
- };
-
- $.verto.dialog.prototype.processReply = function(method, success, e) {
- var dialog = this;
-
- //console.log("Response: " + method + " State:" + dialog.state.name, success, e);
-
- switch (method) {
-
- case "verto.answer":
- case "verto.attach":
- if (success) {
- dialog.setState($.verto.enum.state.active);
- } else {
- dialog.hangup();
- }
- break;
- case "verto.invite":
- if (success) {
- dialog.setState($.verto.enum.state.trying);
- } else {
- dialog.setState($.verto.enum.state.destroy);
- }
- break;
-
- case "verto.bye":
- dialog.hangup();
- break;
-
- case "verto.modify":
- if (e.holdState) {
- if (e.holdState == "held") {
- if (dialog.state != $.verto.enum.state.held) {
- dialog.setState($.verto.enum.state.held);
- }
- } else if (e.holdState == "active") {
- if (dialog.state != $.verto.enum.state.active) {
- dialog.setState($.verto.enum.state.active);
- }
- }
- }
-
- if (success) {}
-
- break;
-
- default:
- break;
- }
-
- };
-
- $.verto.dialog.prototype.hangup = function(params) {
- var dialog = this;
-
- if (params) {
- if (params.causeCode) {
- dialog.causeCode = params.causeCode;
- }
-
- if (params.cause) {
- dialog.cause = params.cause;
- }
- }
-
- if (!dialog.cause && !dialog.causeCode) {
- dialog.cause = "NORMAL_CLEARING";
- }
-
- if (dialog.state.val >= $.verto.enum.state.new.val && dialog.state.val < $.verto.enum.state.hangup.val) {
- dialog.setState($.verto.enum.state.hangup);
- } else if (dialog.state.val < $.verto.enum.state.destroy) {
- dialog.setState($.verto.enum.state.destroy);
- }
- };
-
- $.verto.dialog.prototype.stopRinging = function() {
- var dialog = this;
- if (dialog.verto.ringer) {
- dialog.verto.ringer.stop();
- }
- };
-
- $.verto.dialog.prototype.indicateRing = function() {
- var dialog = this;
-
- if (dialog.verto.ringer) {
- dialog.verto.ringer.attr("src", dialog.verto.options.ringFile)[0].play();
-
- setTimeout(function() {
- dialog.stopRinging();
- if (dialog.state == $.verto.enum.state.ringing) {
- dialog.indicateRing();
- }
- },
- dialog.verto.options.ringSleep);
- }
- };
-
- $.verto.dialog.prototype.ring = function() {
- var dialog = this;
-
- dialog.setState($.verto.enum.state.ringing);
- dialog.indicateRing();
- };
-
- $.verto.dialog.prototype.useVideo = function(on) {
- var dialog = this;
-
- dialog.params.useVideo = on;
-
- if (on) {
- dialog.videoStream = dialog.audioStream;
- } else {
- dialog.videoStream = null;
- }
-
- dialog.rtc.useVideo(dialog.videoStream, dialog.localVideo);
-
- };
-
- $.verto.dialog.prototype.setMute = function(what) {
- var dialog = this;
- return dialog.rtc.setMute(what);
- };
-
- $.verto.dialog.prototype.getMute = function() {
- var dialog = this;
- return dialog.rtc.getMute();
- };
-
- $.verto.dialog.prototype.setVideoMute = function(what) {
- var dialog = this;
- return dialog.rtc.setVideoMute(what);
- };
-
- $.verto.dialog.prototype.getVideoMute = function() {
- var dialog = this;
- return dialog.rtc.getVideoMute();
- };
-
- $.verto.dialog.prototype.useStereo = function(on) {
- var dialog = this;
-
- dialog.params.useStereo = on;
- dialog.rtc.useStereo(on);
- };
-
- $.verto.dialog.prototype.dtmf = function(digits) {
- var dialog = this;
- if (digits) {
- dialog.sendMethod("verto.info", {
- dtmf: digits
- });
- }
- };
-
- $.verto.dialog.prototype.rtt = function(obj) {
- var dialog = this;
- var pobj = {};
-
- if (!obj) {
- return false;
- }
-
- pobj.code = obj.code;
- pobj.chars = obj.chars;
-
-
- if (pobj.chars || pobj.code) {
- dialog.sendMethod("verto.info", {
- txt: obj,
- noDialogParams: true
- });
- }
- };
-
- $.verto.dialog.prototype.transfer = function(dest, params) {
- var dialog = this;
- if (dest) {
- dialog.sendMethod("verto.modify", {
- action: "transfer",
- destination: dest,
- params: params
- });
- }
- };
-
- $.verto.dialog.prototype.replace = function(replaceCallID, params) {
- var dialog = this;
- if (replaceCallID) {
- dialog.sendMethod("verto.modify", {
- action: "replace",
- replaceCallID: replaceCallID,
- params: params
- });
- }
- };
-
- $.verto.dialog.prototype.hold = function(params) {
- var dialog = this;
-
- dialog.sendMethod("verto.modify", {
- action: "hold",
- params: params
- });
- };
-
- $.verto.dialog.prototype.unhold = function(params) {
- var dialog = this;
-
- dialog.sendMethod("verto.modify", {
- action: "unhold",
- params: params
- });
- };
-
- $.verto.dialog.prototype.toggleHold = function(params) {
- var dialog = this;
-
- dialog.sendMethod("verto.modify", {
- action: "toggleHold",
- params: params
- });
- };
-
- $.verto.dialog.prototype.message = function(msg) {
- var dialog = this;
- var err = 0;
-
- msg.from = dialog.params.login;
-
- if (!msg.to) {
- console.error("Missing To");
- err++;
- }
-
- if (!msg.body) {
- console.error("Missing Body");
- err++;
- }
-
- if (err) {
- return false;
- }
-
- dialog.sendMethod("verto.info", {
- msg: msg
- });
-
- return true;
- };
-
- $.verto.dialog.prototype.answer = function(params) {
- var dialog = this;
-
- if (!dialog.answered) {
- if (!params) {
- params = {};
- }
-
- params.sdp = dialog.params.sdp;
-
- if (params) {
- if (params.useVideo) {
- dialog.useVideo(true);
- }
- dialog.params.callee_id_name = params.callee_id_name;
- dialog.params.callee_id_number = params.callee_id_number;
-
- if (params.useCamera) {
- dialog.useCamera = params.useCamera;
- }
-
- if (params.useMic) {
- dialog.useMic = params.useMic;
- }
-
- if (params.useSpeak) {
- dialog.useSpeak = params.useSpeak;
- }
- }
-
- dialog.rtc.createAnswer(params);
- dialog.answered = true;
- }
- };
-
- $.verto.dialog.prototype.handleAnswer = function(params) {
- var dialog = this;
-
- dialog.gotAnswer = true;
-
- if (dialog.state.val >= $.verto.enum.state.active.val) {
- return;
- }
-
- if (dialog.state.val >= $.verto.enum.state.early.val) {
- dialog.setState($.verto.enum.state.active);
- } else {
- if (dialog.gotEarly) {
- console.log("Dialog " + dialog.callID + " Got answer while still establishing early media, delaying...");
- } else {
- console.log("Dialog " + dialog.callID + " Answering Channel");
- dialog.rtc.answer(params.sdp, function() {
- dialog.setState($.verto.enum.state.active);
- }, function(e) {
- console.error(e);
- dialog.hangup();
- });
- console.log("Dialog " + dialog.callID + "ANSWER SDP", params.sdp);
- }
- }
-
-
- };
-
- $.verto.dialog.prototype.cidString = function(enc) {
- var dialog = this;
- var party = dialog.params.remote_caller_id_name + (enc ? " <" : " <") + dialog.params.remote_caller_id_number + (enc ? ">" : ">");
- return party;
- };
-
- $.verto.dialog.prototype.sendMessage = function(msg, params) {
- var dialog = this;
-
- if (dialog.callbacks.onMessage) {
- dialog.callbacks.onMessage(dialog.verto, dialog, msg, params);
- }
- };
-
- $.verto.dialog.prototype.handleInfo = function(params) {
- var dialog = this;
-
- dialog.sendMessage($.verto.enum.message.info, params);
-
- };
-
- $.verto.dialog.prototype.handleDisplay = function(params) {
- var dialog = this;
-
- if (params.display_name) {
- dialog.params.remote_caller_id_name = params.display_name;
- }
- if (params.display_number) {
- dialog.params.remote_caller_id_number = params.display_number;
- }
-
- dialog.sendMessage($.verto.enum.message.display, {});
- };
-
- $.verto.dialog.prototype.handleMedia = function(params) {
- var dialog = this;
-
- if (dialog.state.val >= $.verto.enum.state.early.val) {
- return;
- }
-
- dialog.gotEarly = true;
-
- dialog.rtc.answer(params.sdp, function() {
- console.log("Dialog " + dialog.callID + "Establishing early media");
- dialog.setState($.verto.enum.state.early);
-
- if (dialog.gotAnswer) {
- console.log("Dialog " + dialog.callID + "Answering Channel");
- dialog.setState($.verto.enum.state.active);
- }
- }, function(e) {
- console.error(e);
- dialog.hangup();
- });
- console.log("Dialog " + dialog.callID + "EARLY SDP", params.sdp);
- };
-
- $.verto.ENUM = function(s) {
- var i = 0,
- o = {};
- s.split(" ").map(function(x) {
- o[x] = {
- name: x,
- val: i++
- };
- });
- return Object.freeze(o);
- };
-
- $.verto.enum = {};
-
- $.verto.enum.states = Object.freeze({
- new: {
- requesting: 1,
- recovering: 1,
- ringing: 1,
- destroy: 1,
- answering: 1,
- hangup: 1
- },
- requesting: {
- trying: 1,
- hangup: 1,
- active: 1
- },
- recovering: {
- answering: 1,
- hangup: 1
- },
- trying: {
- active: 1,
- early: 1,
- hangup: 1
- },
- ringing: {
- answering: 1,
- hangup: 1
- },
- answering: {
- active: 1,
- hangup: 1
- },
- active: {
- answering: 1,
- requesting: 1,
- hangup: 1,
- held: 1
- },
- held: {
- hangup: 1,
- active: 1
- },
- early: {
- hangup: 1,
- active: 1
- },
- hangup: {
- destroy: 1
- },
- destroy: {},
- purge: {
- destroy: 1
- }
- });
-
- $.verto.enum.state = $.verto.ENUM("new requesting trying recovering ringing answering early active held hangup destroy purge");
- $.verto.enum.direction = $.verto.ENUM("inbound outbound");
- $.verto.enum.message = $.verto.ENUM("display info pvtEvent clientReady");
-
- $.verto.enum = Object.freeze($.verto.enum);
-
- $.verto.saved = [];
-
- $.verto.unloadJobs = [];
-
- var unloadEventName = 'beforeunload';
- // Hacks for Mobile Safari
- var iOS = ['iPad', 'iPhone', 'iPod'].indexOf(navigator.platform) >= 0;
- if (iOS) {
- unloadEventName = 'pagehide';
- }
-
- $(window).bind(unloadEventName, function() {
- for (var f in $.verto.unloadJobs) {
- $.verto.unloadJobs[f]();
- }
-
- if ($.verto.haltClosure)
- return $.verto.haltClosure();
-
- for (var i in $.verto.saved) {
- var verto = $.verto.saved[i];
- if (verto) {
- verto.purge();
- verto.logout();
- }
- }
-
- return $.verto.warnOnUnload;
- });
-
- $.verto.videoDevices = [];
- $.verto.audioInDevices = [];
- $.verto.audioOutDevices = [];
-
- var checkDevices = function(runtime) {
- console.info("enumerating devices");
- var aud_in = [], aud_out = [], vid = [];
- var has_video = 0, has_audio = 0;
- var Xstream;
-
- function gotDevices(deviceInfos) {
- // Handles being called several times to update labels. Preserve values.
- for (var i = 0; i !== deviceInfos.length; ++i) {
- var deviceInfo = deviceInfos[i];
- var text = "";
-
- console.log(deviceInfo);
- console.log(deviceInfo.kind + ": " + deviceInfo.label + " id = " + deviceInfo.deviceId);
-
- if (deviceInfo.kind === 'audioinput') {
- text = deviceInfo.label || 'microphone ' + (aud_in.length + 1);
- aud_in.push({id: deviceInfo.deviceId, kind: "audio_in", label: text});
- } else if (deviceInfo.kind === 'audiooutput') {
- text = deviceInfo.label || 'speaker ' + (aud_out.length + 1);
- aud_out.push({id: deviceInfo.deviceId, kind: "audio_out", label: text});
- } else if (deviceInfo.kind === 'videoinput') {
- text = deviceInfo.label || 'camera ' + (vid.length + 1);
- vid.push({id: deviceInfo.deviceId, kind: "video", label: text});
- } else {
- console.log('Some other kind of source/device: ', deviceInfo);
- }
- }
-
-
- $.verto.videoDevices = vid;
- $.verto.audioInDevices = aud_in;
- $.verto.audioOutDevices = aud_out;
-
- console.info("Audio IN Devices", $.verto.audioInDevices);
- console.info("Audio Out Devices", $.verto.audioOutDevices);
- console.info("Video Devices", $.verto.videoDevices);
-
- if (Xstream) {
- Xstream.getTracks().forEach(function(track) {track.stop();});
- }
-
- if (runtime) {
- runtime(true);
- }
- }
-
-
-
-
- function handleError(error) {
- console.log('device enumeration error: ', error);
- if (runtime) runtime(false);
- }
-
-
- function checkTypes(devs) {
- for (var i = 0; i !== devs.length; ++i) {
-
- if (devs[i].kind === 'audioinput') {
- has_audio++;
- } else if (devs[i].kind === 'videoinput') {
- has_video++;
- }
- }
-
- navigator.getUserMedia({ audio: (has_audio > 0 ? true : false), video: (has_video > 0 ? true : false)},
- function(stream) {
- Xstream = stream;
- navigator.mediaDevices.enumerateDevices().then(gotDevices).catch(handleError);
- },
- function(err) {
- console.log("The following error occurred: " + err.name);
- }
- );
- }
-
- navigator.mediaDevices.enumerateDevices().then(checkTypes).catch(handleError);
-
- };
-
- $.verto.refreshDevices = function(runtime) {
- checkDevices(runtime);
- }
-
- $.verto.init = function(obj, runtime) {
- if (!obj) {
- obj = {};
- }
-
- if (!obj.skipPermCheck && !obj.skipDeviceCheck) {
- $.FSRTC.checkPerms(function(status) {
- checkDevices(runtime);
- }, true, true);
- } else if (obj.skipPermCheck && !obj.skipDeviceCheck) {
- checkDevices(runtime);
- } else if (!obj.skipPermCheck && obj.skipDeviceCheck) {
- $.FSRTC.checkPerms(function(status) {
- runtime(status);
- }, true, true);
- } else {
- runtime(null);
- }
-
- }
-
- $.verto.genUUID = function () {
- return generateGUID();
- }
-
-
-})(jQuery);
-(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.adapter = 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= 14393 &&
- url.indexOf('?transport=udp') === -1;
- });
-
- delete server.url;
- server.urls = isString ? urls[0] : urls;
- return !!urls.length;
- }
- });
-}
-
-// Determines the intersection of local and remote capabilities.
-function getCommonCapabilities(localCapabilities, remoteCapabilities) {
- var commonCapabilities = {
- codecs: [],
- headerExtensions: [],
- fecMechanisms: []
- };
-
- var findCodecByPayloadType = function(pt, codecs) {
- pt = parseInt(pt, 10);
- for (var i = 0; i < codecs.length; i++) {
- if (codecs[i].payloadType === pt ||
- codecs[i].preferredPayloadType === pt) {
- return codecs[i];
- }
- }
- };
-
- var rtxCapabilityMatches = function(lRtx, rRtx, lCodecs, rCodecs) {
- var lCodec = findCodecByPayloadType(lRtx.parameters.apt, lCodecs);
- var rCodec = findCodecByPayloadType(rRtx.parameters.apt, rCodecs);
- return lCodec && rCodec &&
- lCodec.name.toLowerCase() === rCodec.name.toLowerCase();
- };
-
- localCapabilities.codecs.forEach(function(lCodec) {
- for (var i = 0; i < remoteCapabilities.codecs.length; i++) {
- var rCodec = remoteCapabilities.codecs[i];
- if (lCodec.name.toLowerCase() === rCodec.name.toLowerCase() &&
- lCodec.clockRate === rCodec.clockRate) {
- if (lCodec.name.toLowerCase() === 'rtx' &&
- lCodec.parameters && rCodec.parameters.apt) {
- // for RTX we need to find the local rtx that has a apt
- // which points to the same local codec as the remote one.
- if (!rtxCapabilityMatches(lCodec, rCodec,
- localCapabilities.codecs, remoteCapabilities.codecs)) {
- continue;
- }
- }
- rCodec = JSON.parse(JSON.stringify(rCodec)); // deepcopy
- // number of channels is the highest common number of channels
- rCodec.numChannels = Math.min(lCodec.numChannels,
- rCodec.numChannels);
- // push rCodec so we reply with offerer payload type
- commonCapabilities.codecs.push(rCodec);
-
- // determine common feedback mechanisms
- rCodec.rtcpFeedback = rCodec.rtcpFeedback.filter(function(fb) {
- for (var j = 0; j < lCodec.rtcpFeedback.length; j++) {
- if (lCodec.rtcpFeedback[j].type === fb.type &&
- lCodec.rtcpFeedback[j].parameter === fb.parameter) {
- return true;
- }
- }
- return false;
- });
- // FIXME: also need to determine .parameters
- // see https://github.com/openpeer/ortc/issues/569
- break;
- }
- }
- });
-
- localCapabilities.headerExtensions.forEach(function(lHeaderExtension) {
- for (var i = 0; i < remoteCapabilities.headerExtensions.length;
- i++) {
- var rHeaderExtension = remoteCapabilities.headerExtensions[i];
- if (lHeaderExtension.uri === rHeaderExtension.uri) {
- commonCapabilities.headerExtensions.push(rHeaderExtension);
- break;
- }
- }
- });
-
- // FIXME: fecMechanisms
- return commonCapabilities;
-}
-
-// is action=setLocalDescription with type allowed in signalingState
-function isActionAllowedInSignalingState(action, type, signalingState) {
- return {
- offer: {
- setLocalDescription: ['stable', 'have-local-offer'],
- setRemoteDescription: ['stable', 'have-remote-offer']
- },
- answer: {
- setLocalDescription: ['have-remote-offer', 'have-local-pranswer'],
- setRemoteDescription: ['have-local-offer', 'have-remote-pranswer']
- }
- }[type][action].indexOf(signalingState) !== -1;
-}
-
-function maybeAddCandidate(iceTransport, candidate) {
- // Edge's internal representation adds some fields therefore
- // not all fieldѕ are taken into account.
- var alreadyAdded = iceTransport.getRemoteCandidates()
- .find(function(remoteCandidate) {
- return candidate.foundation === remoteCandidate.foundation &&
- candidate.ip === remoteCandidate.ip &&
- candidate.port === remoteCandidate.port &&
- candidate.priority === remoteCandidate.priority &&
- candidate.protocol === remoteCandidate.protocol &&
- candidate.type === remoteCandidate.type;
- });
- if (!alreadyAdded) {
- iceTransport.addRemoteCandidate(candidate);
- }
- return !alreadyAdded;
-}
-
-
-// https://w3c.github.io/mediacapture-main/#mediastream
-// Helper function to add the track to the stream and
-// dispatch the event ourselves.
-function addTrackToStreamAndFireEvent(track, stream) {
- stream.addTrack(track);
- var e = new Event('addtrack'); // TODO: MediaStreamTrackEvent
- e.track = track;
- stream.dispatchEvent(e);
-}
-
-function removeTrackFromStreamAndFireEvent(track, stream) {
- stream.removeTrack(track);
- var e = new Event('removetrack'); // TODO: MediaStreamTrackEvent
- e.track = track;
- stream.dispatchEvent(e);
-}
-
-function fireAddTrack(pc, track, receiver, streams) {
- var trackEvent = new Event('track');
- trackEvent.track = track;
- trackEvent.receiver = receiver;
- trackEvent.transceiver = {receiver: receiver};
- trackEvent.streams = streams;
- window.setTimeout(function() {
- pc._dispatchEvent('track', trackEvent);
- });
-}
-
-function makeError(name, description) {
- var e = new Error(description);
- e.name = name;
- return e;
-}
-
-module.exports = function(window, edgeVersion) {
- var RTCPeerConnection = function(config) {
- var pc = this;
-
- var _eventTarget = document.createDocumentFragment();
- ['addEventListener', 'removeEventListener', 'dispatchEvent']
- .forEach(function(method) {
- pc[method] = _eventTarget[method].bind(_eventTarget);
- });
-
- this.canTrickleIceCandidates = null;
-
- this.needNegotiation = false;
-
- this.localStreams = [];
- this.remoteStreams = [];
-
- this.localDescription = null;
- this.remoteDescription = null;
-
- this.signalingState = 'stable';
- this.iceConnectionState = 'new';
- this.iceGatheringState = 'new';
-
- config = JSON.parse(JSON.stringify(config || {}));
-
- this.usingBundle = config.bundlePolicy === 'max-bundle';
- if (config.rtcpMuxPolicy === 'negotiate') {
- throw(makeError('NotSupportedError',
- 'rtcpMuxPolicy \'negotiate\' is not supported'));
- } else if (!config.rtcpMuxPolicy) {
- config.rtcpMuxPolicy = 'require';
- }
-
- switch (config.iceTransportPolicy) {
- case 'all':
- case 'relay':
- break;
- default:
- config.iceTransportPolicy = 'all';
- break;
- }
-
- switch (config.bundlePolicy) {
- case 'balanced':
- case 'max-compat':
- case 'max-bundle':
- break;
- default:
- config.bundlePolicy = 'balanced';
- break;
- }
-
- config.iceServers = filterIceServers(config.iceServers || [], edgeVersion);
-
- this._iceGatherers = [];
- if (config.iceCandidatePoolSize) {
- for (var i = config.iceCandidatePoolSize; i > 0; i--) {
- this._iceGatherers = new window.RTCIceGatherer({
- iceServers: config.iceServers,
- gatherPolicy: config.iceTransportPolicy
- });
- }
- } else {
- config.iceCandidatePoolSize = 0;
- }
-
- this._config = config;
-
- // per-track iceGathers, iceTransports, dtlsTransports, rtpSenders, ...
- // everything that is needed to describe a SDP m-line.
- this.transceivers = [];
-
- this._sdpSessionId = SDPUtils.generateSessionId();
- this._sdpSessionVersion = 0;
-
- this._dtlsRole = undefined; // role for a=setup to use in answers.
-
- this._isClosed = false;
- };
-
- // set up event handlers on prototype
- RTCPeerConnection.prototype.onicecandidate = null;
- RTCPeerConnection.prototype.onaddstream = null;
- RTCPeerConnection.prototype.ontrack = null;
- RTCPeerConnection.prototype.onremovestream = null;
- RTCPeerConnection.prototype.onsignalingstatechange = null;
- RTCPeerConnection.prototype.oniceconnectionstatechange = null;
- RTCPeerConnection.prototype.onicegatheringstatechange = null;
- RTCPeerConnection.prototype.onnegotiationneeded = null;
- RTCPeerConnection.prototype.ondatachannel = null;
-
- RTCPeerConnection.prototype._dispatchEvent = function(name, event) {
- if (this._isClosed) {
- return;
- }
- this.dispatchEvent(event);
- if (typeof this['on' + name] === 'function') {
- this['on' + name](event);
- }
- };
-
- RTCPeerConnection.prototype._emitGatheringStateChange = function() {
- var event = new Event('icegatheringstatechange');
- this._dispatchEvent('icegatheringstatechange', event);
- };
-
- RTCPeerConnection.prototype.getConfiguration = function() {
- return this._config;
- };
-
- RTCPeerConnection.prototype.getLocalStreams = function() {
- return this.localStreams;
- };
-
- RTCPeerConnection.prototype.getRemoteStreams = function() {
- return this.remoteStreams;
- };
-
- // internal helper to create a transceiver object.
- // (whih is not yet the same as the WebRTC 1.0 transceiver)
- RTCPeerConnection.prototype._createTransceiver = function(kind) {
- var hasBundleTransport = this.transceivers.length > 0;
- var transceiver = {
- track: null,
- iceGatherer: null,
- iceTransport: null,
- dtlsTransport: null,
- localCapabilities: null,
- remoteCapabilities: null,
- rtpSender: null,
- rtpReceiver: null,
- kind: kind,
- mid: null,
- sendEncodingParameters: null,
- recvEncodingParameters: null,
- stream: null,
- associatedRemoteMediaStreams: [],
- wantReceive: true
- };
- if (this.usingBundle && hasBundleTransport) {
- transceiver.iceTransport = this.transceivers[0].iceTransport;
- transceiver.dtlsTransport = this.transceivers[0].dtlsTransport;
- } else {
- var transports = this._createIceAndDtlsTransports();
- transceiver.iceTransport = transports.iceTransport;
- transceiver.dtlsTransport = transports.dtlsTransport;
- }
- this.transceivers.push(transceiver);
- return transceiver;
- };
-
- RTCPeerConnection.prototype.addTrack = function(track, stream) {
- var alreadyExists = this.transceivers.find(function(s) {
- return s.track === track;
- });
-
- if (alreadyExists) {
- throw makeError('InvalidAccessError', 'Track already exists.');
- }
-
- if (this.signalingState === 'closed') {
- throw makeError('InvalidStateError',
- 'Attempted to call addTrack on a closed peerconnection.');
- }
-
- var transceiver;
- for (var i = 0; i < this.transceivers.length; i++) {
- if (!this.transceivers[i].track &&
- this.transceivers[i].kind === track.kind) {
- transceiver = this.transceivers[i];
- }
- }
- if (!transceiver) {
- transceiver = this._createTransceiver(track.kind);
- }
-
- this._maybeFireNegotiationNeeded();
-
- if (this.localStreams.indexOf(stream) === -1) {
- this.localStreams.push(stream);
- }
-
- transceiver.track = track;
- transceiver.stream = stream;
- transceiver.rtpSender = new window.RTCRtpSender(track,
- transceiver.dtlsTransport);
- return transceiver.rtpSender;
- };
-
- RTCPeerConnection.prototype.addStream = function(stream) {
- var pc = this;
- if (edgeVersion >= 15025) {
- stream.getTracks().forEach(function(track) {
- pc.addTrack(track, stream);
- });
- } else {
- // Clone is necessary for local demos mostly, attaching directly
- // to two different senders does not work (build 10547).
- // Fixed in 15025 (or earlier)
- var clonedStream = stream.clone();
- stream.getTracks().forEach(function(track, idx) {
- var clonedTrack = clonedStream.getTracks()[idx];
- track.addEventListener('enabled', function(event) {
- clonedTrack.enabled = event.enabled;
- });
- });
- clonedStream.getTracks().forEach(function(track) {
- pc.addTrack(track, clonedStream);
- });
- }
- };
-
- RTCPeerConnection.prototype.removeTrack = function(sender) {
- if (!(sender instanceof window.RTCRtpSender)) {
- throw new TypeError('Argument 1 of RTCPeerConnection.removeTrack ' +
- 'does not implement interface RTCRtpSender.');
- }
-
- var transceiver = this.transceivers.find(function(t) {
- return t.rtpSender === sender;
- });
-
- if (!transceiver) {
- throw makeError('InvalidAccessError',
- 'Sender was not created by this connection.');
- }
- var stream = transceiver.stream;
-
- transceiver.rtpSender.stop();
- transceiver.rtpSender = null;
- transceiver.track = null;
- transceiver.stream = null;
-
- // remove the stream from the set of local streams
- var localStreams = this.transceivers.map(function(t) {
- return t.stream;
- });
- if (localStreams.indexOf(stream) === -1 &&
- this.localStreams.indexOf(stream) > -1) {
- this.localStreams.splice(this.localStreams.indexOf(stream), 1);
- }
-
- this._maybeFireNegotiationNeeded();
- };
-
- RTCPeerConnection.prototype.removeStream = function(stream) {
- var pc = this;
- stream.getTracks().forEach(function(track) {
- var sender = pc.getSenders().find(function(s) {
- return s.track === track;
- });
- if (sender) {
- pc.removeTrack(sender);
- }
- });
- };
-
- RTCPeerConnection.prototype.getSenders = function() {
- return this.transceivers.filter(function(transceiver) {
- return !!transceiver.rtpSender;
- })
- .map(function(transceiver) {
- return transceiver.rtpSender;
- });
- };
-
- RTCPeerConnection.prototype.getReceivers = function() {
- return this.transceivers.filter(function(transceiver) {
- return !!transceiver.rtpReceiver;
- })
- .map(function(transceiver) {
- return transceiver.rtpReceiver;
- });
- };
-
-
- RTCPeerConnection.prototype._createIceGatherer = function(sdpMLineIndex,
- usingBundle) {
- var pc = this;
- if (usingBundle && sdpMLineIndex > 0) {
- return this.transceivers[0].iceGatherer;
- } else if (this._iceGatherers.length) {
- return this._iceGatherers.shift();
- }
- var iceGatherer = new window.RTCIceGatherer({
- iceServers: this._config.iceServers,
- gatherPolicy: this._config.iceTransportPolicy
- });
- Object.defineProperty(iceGatherer, 'state',
- {value: 'new', writable: true}
- );
-
- this.transceivers[sdpMLineIndex].candidates = [];
- this.transceivers[sdpMLineIndex].bufferCandidates = function(event) {
- var end = !event.candidate || Object.keys(event.candidate).length === 0;
- // polyfill since RTCIceGatherer.state is not implemented in
- // Edge 10547 yet.
- iceGatherer.state = end ? 'completed' : 'gathering';
- if (pc.transceivers[sdpMLineIndex].candidates !== null) {
- pc.transceivers[sdpMLineIndex].candidates.push(event.candidate);
- }
- };
- iceGatherer.addEventListener('localcandidate',
- this.transceivers[sdpMLineIndex].bufferCandidates);
- return iceGatherer;
- };
-
- // start gathering from an RTCIceGatherer.
- RTCPeerConnection.prototype._gather = function(mid, sdpMLineIndex) {
- var pc = this;
- var iceGatherer = this.transceivers[sdpMLineIndex].iceGatherer;
- if (iceGatherer.onlocalcandidate) {
- return;
- }
- var candidates = this.transceivers[sdpMLineIndex].candidates;
- this.transceivers[sdpMLineIndex].candidates = null;
- iceGatherer.removeEventListener('localcandidate',
- this.transceivers[sdpMLineIndex].bufferCandidates);
- iceGatherer.onlocalcandidate = function(evt) {
- if (pc.usingBundle && sdpMLineIndex > 0) {
- // if we know that we use bundle we can drop candidates with
- // Ń•dpMLineIndex > 0. If we don't do this then our state gets
- // confused since we dispose the extra ice gatherer.
- return;
- }
- var event = new Event('icecandidate');
- event.candidate = {sdpMid: mid, sdpMLineIndex: sdpMLineIndex};
-
- var cand = evt.candidate;
- // Edge emits an empty object for RTCIceCandidateComplete‥
- var end = !cand || Object.keys(cand).length === 0;
- if (end) {
- // polyfill since RTCIceGatherer.state is not implemented in
- // Edge 10547 yet.
- if (iceGatherer.state === 'new' || iceGatherer.state === 'gathering') {
- iceGatherer.state = 'completed';
- }
- } else {
- if (iceGatherer.state === 'new') {
- iceGatherer.state = 'gathering';
- }
- // RTCIceCandidate doesn't have a component, needs to be added
- cand.component = 1;
- event.candidate.candidate = SDPUtils.writeCandidate(cand);
- }
-
- // update local description.
- var sections = SDPUtils.splitSections(pc.localDescription.sdp);
- if (!end) {
- sections[event.candidate.sdpMLineIndex + 1] +=
- 'a=' + event.candidate.candidate + '\r\n';
- } else {
- sections[event.candidate.sdpMLineIndex + 1] +=
- 'a=end-of-candidates\r\n';
- }
- pc.localDescription.sdp = sections.join('');
- var complete = pc.transceivers.every(function(transceiver) {
- return transceiver.iceGatherer &&
- transceiver.iceGatherer.state === 'completed';
- });
-
- if (pc.iceGatheringState !== 'gathering') {
- pc.iceGatheringState = 'gathering';
- pc._emitGatheringStateChange();
- }
-
- // Emit candidate. Also emit null candidate when all gatherers are
- // complete.
- if (!end) {
- pc._dispatchEvent('icecandidate', event);
- }
- if (complete) {
- pc._dispatchEvent('icecandidate', new Event('icecandidate'));
- pc.iceGatheringState = 'complete';
- pc._emitGatheringStateChange();
- }
- };
-
- // emit already gathered candidates.
- window.setTimeout(function() {
- candidates.forEach(function(candidate) {
- var e = new Event('RTCIceGatherEvent');
- e.candidate = candidate;
- iceGatherer.onlocalcandidate(e);
- });
- }, 0);
- };
-
- // Create ICE transport and DTLS transport.
- RTCPeerConnection.prototype._createIceAndDtlsTransports = function() {
- var pc = this;
- var iceTransport = new window.RTCIceTransport(null);
- iceTransport.onicestatechange = function() {
- pc._updateConnectionState();
- };
-
- var dtlsTransport = new window.RTCDtlsTransport(iceTransport);
- dtlsTransport.ondtlsstatechange = function() {
- pc._updateConnectionState();
- };
- dtlsTransport.onerror = function() {
- // onerror does not set state to failed by itpc.
- Object.defineProperty(dtlsTransport, 'state',
- {value: 'failed', writable: true});
- pc._updateConnectionState();
- };
-
- return {
- iceTransport: iceTransport,
- dtlsTransport: dtlsTransport
- };
- };
-
- // Destroy ICE gatherer, ICE transport and DTLS transport.
- // Without triggering the callbacks.
- RTCPeerConnection.prototype._disposeIceAndDtlsTransports = function(
- sdpMLineIndex) {
- var iceGatherer = this.transceivers[sdpMLineIndex].iceGatherer;
- if (iceGatherer) {
- delete iceGatherer.onlocalcandidate;
- delete this.transceivers[sdpMLineIndex].iceGatherer;
- }
- var iceTransport = this.transceivers[sdpMLineIndex].iceTransport;
- if (iceTransport) {
- delete iceTransport.onicestatechange;
- delete this.transceivers[sdpMLineIndex].iceTransport;
- }
- var dtlsTransport = this.transceivers[sdpMLineIndex].dtlsTransport;
- if (dtlsTransport) {
- delete dtlsTransport.ondtlsstatechange;
- delete dtlsTransport.onerror;
- delete this.transceivers[sdpMLineIndex].dtlsTransport;
- }
- };
-
- // Start the RTP Sender and Receiver for a transceiver.
- RTCPeerConnection.prototype._transceive = function(transceiver,
- send, recv) {
- var params = getCommonCapabilities(transceiver.localCapabilities,
- transceiver.remoteCapabilities);
- if (send && transceiver.rtpSender) {
- params.encodings = transceiver.sendEncodingParameters;
- params.rtcp = {
- cname: SDPUtils.localCName,
- compound: transceiver.rtcpParameters.compound
- };
- if (transceiver.recvEncodingParameters.length) {
- params.rtcp.ssrc = transceiver.recvEncodingParameters[0].ssrc;
- }
- transceiver.rtpSender.send(params);
- }
- if (recv && transceiver.rtpReceiver && params.codecs.length > 0) {
- // remove RTX field in Edge 14942
- if (transceiver.kind === 'video'
- && transceiver.recvEncodingParameters
- && edgeVersion < 15019) {
- transceiver.recvEncodingParameters.forEach(function(p) {
- delete p.rtx;
- });
- }
- if (transceiver.recvEncodingParameters.length) {
- params.encodings = transceiver.recvEncodingParameters;
- }
- params.rtcp = {
- compound: transceiver.rtcpParameters.compound
- };
- if (transceiver.rtcpParameters.cname) {
- params.rtcp.cname = transceiver.rtcpParameters.cname;
- }
- if (transceiver.sendEncodingParameters.length) {
- params.rtcp.ssrc = transceiver.sendEncodingParameters[0].ssrc;
- }
- transceiver.rtpReceiver.receive(params);
- }
- };
-
- RTCPeerConnection.prototype.setLocalDescription = function(description) {
- var pc = this;
-
- if (!isActionAllowedInSignalingState('setLocalDescription',
- description.type, this.signalingState) || this._isClosed) {
- return Promise.reject(makeError('InvalidStateError',
- 'Can not set local ' + description.type +
- ' in state ' + pc.signalingState));
- }
-
- var sections;
- var sessionpart;
- if (description.type === 'offer') {
- // VERY limited support for SDP munging. Limited to:
- // * changing the order of codecs
- sections = SDPUtils.splitSections(description.sdp);
- sessionpart = sections.shift();
- sections.forEach(function(mediaSection, sdpMLineIndex) {
- var caps = SDPUtils.parseRtpParameters(mediaSection);
- pc.transceivers[sdpMLineIndex].localCapabilities = caps;
- });
-
- this.transceivers.forEach(function(transceiver, sdpMLineIndex) {
- pc._gather(transceiver.mid, sdpMLineIndex);
- });
- } else if (description.type === 'answer') {
- sections = SDPUtils.splitSections(pc.remoteDescription.sdp);
- sessionpart = sections.shift();
- var isIceLite = SDPUtils.matchPrefix(sessionpart,
- 'a=ice-lite').length > 0;
- sections.forEach(function(mediaSection, sdpMLineIndex) {
- var transceiver = pc.transceivers[sdpMLineIndex];
- var iceGatherer = transceiver.iceGatherer;
- var iceTransport = transceiver.iceTransport;
- var dtlsTransport = transceiver.dtlsTransport;
- var localCapabilities = transceiver.localCapabilities;
- var remoteCapabilities = transceiver.remoteCapabilities;
-
- // treat bundle-only as not-rejected.
- var rejected = SDPUtils.isRejected(mediaSection) &&
- SDPUtils.matchPrefix(mediaSection, 'a=bundle-only').length === 0;
-
- if (!rejected && !transceiver.isDatachannel) {
- var remoteIceParameters = SDPUtils.getIceParameters(
- mediaSection, sessionpart);
- var remoteDtlsParameters = SDPUtils.getDtlsParameters(
- mediaSection, sessionpart);
- if (isIceLite) {
- remoteDtlsParameters.role = 'server';
- }
-
- if (!pc.usingBundle || sdpMLineIndex === 0) {
- pc._gather(transceiver.mid, sdpMLineIndex);
- if (iceTransport.state === 'new') {
- iceTransport.start(iceGatherer, remoteIceParameters,
- isIceLite ? 'controlling' : 'controlled');
- }
- if (dtlsTransport.state === 'new') {
- dtlsTransport.start(remoteDtlsParameters);
- }
- }
-
- // Calculate intersection of capabilities.
- var params = getCommonCapabilities(localCapabilities,
- remoteCapabilities);
-
- // Start the RTCRtpSender. The RTCRtpReceiver for this
- // transceiver has already been started in setRemoteDescription.
- pc._transceive(transceiver,
- params.codecs.length > 0,
- false);
- }
- });
- }
-
- this.localDescription = {
- type: description.type,
- sdp: description.sdp
- };
- switch (description.type) {
- case 'offer':
- this._updateSignalingState('have-local-offer');
- break;
- case 'answer':
- this._updateSignalingState('stable');
- break;
- default:
- throw new TypeError('unsupported type "' + description.type +
- '"');
- }
-
- return Promise.resolve();
- };
-
- RTCPeerConnection.prototype.setRemoteDescription = function(description) {
- var pc = this;
-
- if (!isActionAllowedInSignalingState('setRemoteDescription',
- description.type, this.signalingState) || this._isClosed) {
- return Promise.reject(makeError('InvalidStateError',
- 'Can not set remote ' + description.type +
- ' in state ' + pc.signalingState));
- }
-
- var streams = {};
- this.remoteStreams.forEach(function(stream) {
- streams[stream.id] = stream;
- });
- var receiverList = [];
- var sections = SDPUtils.splitSections(description.sdp);
- var sessionpart = sections.shift();
- var isIceLite = SDPUtils.matchPrefix(sessionpart,
- 'a=ice-lite').length > 0;
- var usingBundle = SDPUtils.matchPrefix(sessionpart,
- 'a=group:BUNDLE ').length > 0;
- this.usingBundle = usingBundle;
- var iceOptions = SDPUtils.matchPrefix(sessionpart,
- 'a=ice-options:')[0];
- if (iceOptions) {
- this.canTrickleIceCandidates = iceOptions.substr(14).split(' ')
- .indexOf('trickle') >= 0;
- } else {
- this.canTrickleIceCandidates = false;
- }
-
- sections.forEach(function(mediaSection, sdpMLineIndex) {
- var lines = SDPUtils.splitLines(mediaSection);
- var kind = SDPUtils.getKind(mediaSection);
- // treat bundle-only as not-rejected.
- var rejected = SDPUtils.isRejected(mediaSection) &&
- SDPUtils.matchPrefix(mediaSection, 'a=bundle-only').length === 0;
- var protocol = lines[0].substr(2).split(' ')[2];
-
- var direction = SDPUtils.getDirection(mediaSection, sessionpart);
- var remoteMsid = SDPUtils.parseMsid(mediaSection);
-
- var mid = SDPUtils.getMid(mediaSection) || SDPUtils.generateIdentifier();
-
- // Reject datachannels which are not implemented yet.
- if (kind === 'application' && protocol === 'DTLS/SCTP') {
- pc.transceivers[sdpMLineIndex] = {
- mid: mid,
- isDatachannel: true
- };
- return;
- }
-
- var transceiver;
- var iceGatherer;
- var iceTransport;
- var dtlsTransport;
- var rtpReceiver;
- var sendEncodingParameters;
- var recvEncodingParameters;
- var localCapabilities;
-
- var track;
- // FIXME: ensure the mediaSection has rtcp-mux set.
- var remoteCapabilities = SDPUtils.parseRtpParameters(mediaSection);
- var remoteIceParameters;
- var remoteDtlsParameters;
- if (!rejected) {
- remoteIceParameters = SDPUtils.getIceParameters(mediaSection,
- sessionpart);
- remoteDtlsParameters = SDPUtils.getDtlsParameters(mediaSection,
- sessionpart);
- remoteDtlsParameters.role = 'client';
- }
- recvEncodingParameters =
- SDPUtils.parseRtpEncodingParameters(mediaSection);
-
- var rtcpParameters = SDPUtils.parseRtcpParameters(mediaSection);
-
- var isComplete = SDPUtils.matchPrefix(mediaSection,
- 'a=end-of-candidates', sessionpart).length > 0;
- var cands = SDPUtils.matchPrefix(mediaSection, 'a=candidate:')
- .map(function(cand) {
- return SDPUtils.parseCandidate(cand);
- })
- .filter(function(cand) {
- return cand.component === 1;
- });
-
- // Check if we can use BUNDLE and dispose transports.
- if ((description.type === 'offer' || description.type === 'answer') &&
- !rejected && usingBundle && sdpMLineIndex > 0 &&
- pc.transceivers[sdpMLineIndex]) {
- pc._disposeIceAndDtlsTransports(sdpMLineIndex);
- pc.transceivers[sdpMLineIndex].iceGatherer =
- pc.transceivers[0].iceGatherer;
- pc.transceivers[sdpMLineIndex].iceTransport =
- pc.transceivers[0].iceTransport;
- pc.transceivers[sdpMLineIndex].dtlsTransport =
- pc.transceivers[0].dtlsTransport;
- if (pc.transceivers[sdpMLineIndex].rtpSender) {
- pc.transceivers[sdpMLineIndex].rtpSender.setTransport(
- pc.transceivers[0].dtlsTransport);
- }
- if (pc.transceivers[sdpMLineIndex].rtpReceiver) {
- pc.transceivers[sdpMLineIndex].rtpReceiver.setTransport(
- pc.transceivers[0].dtlsTransport);
- }
- }
- if (description.type === 'offer' && !rejected) {
- transceiver = pc.transceivers[sdpMLineIndex] ||
- pc._createTransceiver(kind);
- transceiver.mid = mid;
-
- if (!transceiver.iceGatherer) {
- transceiver.iceGatherer = pc._createIceGatherer(sdpMLineIndex,
- usingBundle);
- }
-
- if (cands.length && transceiver.iceTransport.state === 'new') {
- if (isComplete && (!usingBundle || sdpMLineIndex === 0)) {
- transceiver.iceTransport.setRemoteCandidates(cands);
- } else {
- cands.forEach(function(candidate) {
- maybeAddCandidate(transceiver.iceTransport, candidate);
- });
- }
- }
-
- localCapabilities = window.RTCRtpReceiver.getCapabilities(kind);
-
- // filter RTX until additional stuff needed for RTX is implemented
- // in adapter.js
- if (edgeVersion < 15019) {
- localCapabilities.codecs = localCapabilities.codecs.filter(
- function(codec) {
- return codec.name !== 'rtx';
- });
- }
-
- sendEncodingParameters = transceiver.sendEncodingParameters || [{
- ssrc: (2 * sdpMLineIndex + 2) * 1001
- }];
-
- // TODO: rewrite to use http://w3c.github.io/webrtc-pc/#set-associated-remote-streams
- var isNewTrack = false;
- if (direction === 'sendrecv' || direction === 'sendonly') {
- isNewTrack = !transceiver.rtpReceiver;
- rtpReceiver = transceiver.rtpReceiver ||
- new window.RTCRtpReceiver(transceiver.dtlsTransport, kind);
-
- if (isNewTrack) {
- var stream;
- track = rtpReceiver.track;
- // FIXME: does not work with Plan B.
- if (remoteMsid && remoteMsid.stream === '-') {
- // no-op. a stream id of '-' means: no associated stream.
- } else if (remoteMsid) {
- if (!streams[remoteMsid.stream]) {
- streams[remoteMsid.stream] = new window.MediaStream();
- Object.defineProperty(streams[remoteMsid.stream], 'id', {
- get: function() {
- return remoteMsid.stream;
- }
- });
- }
- Object.defineProperty(track, 'id', {
- get: function() {
- return remoteMsid.track;
- }
- });
- stream = streams[remoteMsid.stream];
- } else {
- if (!streams.default) {
- streams.default = new window.MediaStream();
- }
- stream = streams.default;
- }
- if (stream) {
- addTrackToStreamAndFireEvent(track, stream);
- transceiver.associatedRemoteMediaStreams.push(stream);
- }
- receiverList.push([track, rtpReceiver, stream]);
- }
- } else if (transceiver.rtpReceiver && transceiver.rtpReceiver.track) {
- transceiver.associatedRemoteMediaStreams.forEach(function(s) {
- var nativeTrack = s.getTracks().find(function(t) {
- return t.id === transceiver.rtpReceiver.track.id;
- });
- if (nativeTrack) {
- removeTrackFromStreamAndFireEvent(nativeTrack, s);
- }
- });
- transceiver.associatedRemoteMediaStreams = [];
- }
-
- transceiver.localCapabilities = localCapabilities;
- transceiver.remoteCapabilities = remoteCapabilities;
- transceiver.rtpReceiver = rtpReceiver;
- transceiver.rtcpParameters = rtcpParameters;
- transceiver.sendEncodingParameters = sendEncodingParameters;
- transceiver.recvEncodingParameters = recvEncodingParameters;
-
- // Start the RTCRtpReceiver now. The RTPSender is started in
- // setLocalDescription.
- pc._transceive(pc.transceivers[sdpMLineIndex],
- false,
- isNewTrack);
- } else if (description.type === 'answer' && !rejected) {
- transceiver = pc.transceivers[sdpMLineIndex];
- iceGatherer = transceiver.iceGatherer;
- iceTransport = transceiver.iceTransport;
- dtlsTransport = transceiver.dtlsTransport;
- rtpReceiver = transceiver.rtpReceiver;
- sendEncodingParameters = transceiver.sendEncodingParameters;
- localCapabilities = transceiver.localCapabilities;
-
- pc.transceivers[sdpMLineIndex].recvEncodingParameters =
- recvEncodingParameters;
- pc.transceivers[sdpMLineIndex].remoteCapabilities =
- remoteCapabilities;
- pc.transceivers[sdpMLineIndex].rtcpParameters = rtcpParameters;
-
- if (cands.length && iceTransport.state === 'new') {
- if ((isIceLite || isComplete) &&
- (!usingBundle || sdpMLineIndex === 0)) {
- iceTransport.setRemoteCandidates(cands);
- } else {
- cands.forEach(function(candidate) {
- maybeAddCandidate(transceiver.iceTransport, candidate);
- });
- }
- }
-
- if (!usingBundle || sdpMLineIndex === 0) {
- if (iceTransport.state === 'new') {
- iceTransport.start(iceGatherer, remoteIceParameters,
- 'controlling');
- }
- if (dtlsTransport.state === 'new') {
- dtlsTransport.start(remoteDtlsParameters);
- }
- }
-
- pc._transceive(transceiver,
- direction === 'sendrecv' || direction === 'recvonly',
- direction === 'sendrecv' || direction === 'sendonly');
-
- // TODO: rewrite to use http://w3c.github.io/webrtc-pc/#set-associated-remote-streams
- if (rtpReceiver &&
- (direction === 'sendrecv' || direction === 'sendonly')) {
- track = rtpReceiver.track;
- if (remoteMsid) {
- if (!streams[remoteMsid.stream]) {
- streams[remoteMsid.stream] = new window.MediaStream();
- }
- addTrackToStreamAndFireEvent(track, streams[remoteMsid.stream]);
- receiverList.push([track, rtpReceiver, streams[remoteMsid.stream]]);
- } else {
- if (!streams.default) {
- streams.default = new window.MediaStream();
- }
- addTrackToStreamAndFireEvent(track, streams.default);
- receiverList.push([track, rtpReceiver, streams.default]);
- }
- } else {
- // FIXME: actually the receiver should be created later.
- delete transceiver.rtpReceiver;
- }
- }
- });
-
- if (this._dtlsRole === undefined) {
- this._dtlsRole = description.type === 'offer' ? 'active' : 'passive';
- }
-
- this.remoteDescription = {
- type: description.type,
- sdp: description.sdp
- };
- switch (description.type) {
- case 'offer':
- this._updateSignalingState('have-remote-offer');
- break;
- case 'answer':
- this._updateSignalingState('stable');
- break;
- default:
- throw new TypeError('unsupported type "' + description.type +
- '"');
- }
- Object.keys(streams).forEach(function(sid) {
- var stream = streams[sid];
- if (stream.getTracks().length) {
- if (pc.remoteStreams.indexOf(stream) === -1) {
- pc.remoteStreams.push(stream);
- var event = new Event('addstream');
- event.stream = stream;
- window.setTimeout(function() {
- pc._dispatchEvent('addstream', event);
- });
- }
-
- receiverList.forEach(function(item) {
- var track = item[0];
- var receiver = item[1];
- if (stream.id !== item[2].id) {
- return;
- }
- fireAddTrack(pc, track, receiver, [stream]);
- });
- }
- });
- receiverList.forEach(function(item) {
- if (item[2]) {
- return;
- }
- fireAddTrack(pc, item[0], item[1], []);
- });
-
- // check whether addIceCandidate({}) was called within four seconds after
- // setRemoteDescription.
- window.setTimeout(function() {
- if (!(pc && pc.transceivers)) {
- return;
- }
- pc.transceivers.forEach(function(transceiver) {
- if (transceiver.iceTransport &&
- transceiver.iceTransport.state === 'new' &&
- transceiver.iceTransport.getRemoteCandidates().length > 0) {
- console.warn('Timeout for addRemoteCandidate. Consider sending ' +
- 'an end-of-candidates notification');
- transceiver.iceTransport.addRemoteCandidate({});
- }
- });
- }, 4000);
-
- return Promise.resolve();
- };
-
- RTCPeerConnection.prototype.close = function() {
- this.transceivers.forEach(function(transceiver) {
- /* not yet
- if (transceiver.iceGatherer) {
- transceiver.iceGatherer.close();
- }
- */
- if (transceiver.iceTransport) {
- transceiver.iceTransport.stop();
- }
- if (transceiver.dtlsTransport) {
- transceiver.dtlsTransport.stop();
- }
- if (transceiver.rtpSender) {
- transceiver.rtpSender.stop();
- }
- if (transceiver.rtpReceiver) {
- transceiver.rtpReceiver.stop();
- }
- });
- // FIXME: clean up tracks, local streams, remote streams, etc
- this._isClosed = true;
- this._updateSignalingState('closed');
- };
-
- // Update the signaling state.
- RTCPeerConnection.prototype._updateSignalingState = function(newState) {
- this.signalingState = newState;
- var event = new Event('signalingstatechange');
- this._dispatchEvent('signalingstatechange', event);
- };
-
- // Determine whether to fire the negotiationneeded event.
- RTCPeerConnection.prototype._maybeFireNegotiationNeeded = function() {
- var pc = this;
- if (this.signalingState !== 'stable' || this.needNegotiation === true) {
- return;
- }
- this.needNegotiation = true;
- window.setTimeout(function() {
- if (pc.needNegotiation === false) {
- return;
- }
- pc.needNegotiation = false;
- var event = new Event('negotiationneeded');
- pc._dispatchEvent('negotiationneeded', event);
- }, 0);
- };
-
- // Update the connection state.
- RTCPeerConnection.prototype._updateConnectionState = function() {
- var newState;
- var states = {
- 'new': 0,
- closed: 0,
- connecting: 0,
- checking: 0,
- connected: 0,
- completed: 0,
- disconnected: 0,
- failed: 0
- };
- this.transceivers.forEach(function(transceiver) {
- states[transceiver.iceTransport.state]++;
- states[transceiver.dtlsTransport.state]++;
- });
- // ICETransport.completed and connected are the same for this purpose.
- states.connected += states.completed;
-
- newState = 'new';
- if (states.failed > 0) {
- newState = 'failed';
- } else if (states.connecting > 0 || states.checking > 0) {
- newState = 'connecting';
- } else if (states.disconnected > 0) {
- newState = 'disconnected';
- } else if (states.new > 0) {
- newState = 'new';
- } else if (states.connected > 0 || states.completed > 0) {
- newState = 'connected';
- }
-
- if (newState !== this.iceConnectionState) {
- this.iceConnectionState = newState;
- var event = new Event('iceconnectionstatechange');
- this._dispatchEvent('iceconnectionstatechange', event);
- }
- };
-
- RTCPeerConnection.prototype.createOffer = function() {
- var pc = this;
-
- if (this._isClosed) {
- return Promise.reject(makeError('InvalidStateError',
- 'Can not call createOffer after close'));
- }
-
- var numAudioTracks = this.transceivers.filter(function(t) {
- return t.kind === 'audio';
- }).length;
- var numVideoTracks = this.transceivers.filter(function(t) {
- return t.kind === 'video';
- }).length;
-
- // Determine number of audio and video tracks we need to send/recv.
- var offerOptions = arguments[0];
- if (offerOptions) {
- // Reject Chrome legacy constraints.
- if (offerOptions.mandatory || offerOptions.optional) {
- throw new TypeError(
- 'Legacy mandatory/optional constraints not supported.');
- }
- if (offerOptions.offerToReceiveAudio !== undefined) {
- if (offerOptions.offerToReceiveAudio === true) {
- numAudioTracks = 1;
- } else if (offerOptions.offerToReceiveAudio === false) {
- numAudioTracks = 0;
- } else {
- numAudioTracks = offerOptions.offerToReceiveAudio;
- }
- }
- if (offerOptions.offerToReceiveVideo !== undefined) {
- if (offerOptions.offerToReceiveVideo === true) {
- numVideoTracks = 1;
- } else if (offerOptions.offerToReceiveVideo === false) {
- numVideoTracks = 0;
- } else {
- numVideoTracks = offerOptions.offerToReceiveVideo;
- }
- }
- }
-
- this.transceivers.forEach(function(transceiver) {
- if (transceiver.kind === 'audio') {
- numAudioTracks--;
- if (numAudioTracks < 0) {
- transceiver.wantReceive = false;
- }
- } else if (transceiver.kind === 'video') {
- numVideoTracks--;
- if (numVideoTracks < 0) {
- transceiver.wantReceive = false;
- }
- }
- });
-
- // Create M-lines for recvonly streams.
- while (numAudioTracks > 0 || numVideoTracks > 0) {
- if (numAudioTracks > 0) {
- this._createTransceiver('audio');
- numAudioTracks--;
- }
- if (numVideoTracks > 0) {
- this._createTransceiver('video');
- numVideoTracks--;
- }
- }
-
- var sdp = SDPUtils.writeSessionBoilerplate(this._sdpSessionId,
- this._sdpSessionVersion++);
- this.transceivers.forEach(function(transceiver, sdpMLineIndex) {
- // For each track, create an ice gatherer, ice transport,
- // dtls transport, potentially rtpsender and rtpreceiver.
- var track = transceiver.track;
- var kind = transceiver.kind;
- var mid = SDPUtils.generateIdentifier();
- transceiver.mid = mid;
-
- if (!transceiver.iceGatherer) {
- transceiver.iceGatherer = pc._createIceGatherer(sdpMLineIndex,
- pc.usingBundle);
- }
-
- var localCapabilities = window.RTCRtpSender.getCapabilities(kind);
- // filter RTX until additional stuff needed for RTX is implemented
- // in adapter.js
- if (edgeVersion < 15019) {
- localCapabilities.codecs = localCapabilities.codecs.filter(
- function(codec) {
- return codec.name !== 'rtx';
- });
- }
- localCapabilities.codecs.forEach(function(codec) {
- // work around https://bugs.chromium.org/p/webrtc/issues/detail?id=6552
- // by adding level-asymmetry-allowed=1
- if (codec.name === 'H264' &&
- codec.parameters['level-asymmetry-allowed'] === undefined) {
- codec.parameters['level-asymmetry-allowed'] = '1';
- }
- });
-
- // generate an ssrc now, to be used later in rtpSender.send
- var sendEncodingParameters = transceiver.sendEncodingParameters || [{
- ssrc: (2 * sdpMLineIndex + 1) * 1001
- }];
- if (track) {
- // add RTX
- if (edgeVersion >= 15019 && kind === 'video' &&
- !sendEncodingParameters[0].rtx) {
- sendEncodingParameters[0].rtx = {
- ssrc: sendEncodingParameters[0].ssrc + 1
- };
- }
- }
-
- if (transceiver.wantReceive) {
- transceiver.rtpReceiver = new window.RTCRtpReceiver(
- transceiver.dtlsTransport, kind);
- }
-
- transceiver.localCapabilities = localCapabilities;
- transceiver.sendEncodingParameters = sendEncodingParameters;
- });
-
- // always offer BUNDLE and dispose on return if not supported.
- if (this._config.bundlePolicy !== 'max-compat') {
- sdp += 'a=group:BUNDLE ' + this.transceivers.map(function(t) {
- return t.mid;
- }).join(' ') + '\r\n';
- }
- sdp += 'a=ice-options:trickle\r\n';
-
- this.transceivers.forEach(function(transceiver, sdpMLineIndex) {
- sdp += writeMediaSection(transceiver, transceiver.localCapabilities,
- 'offer', transceiver.stream, pc._dtlsRole);
- sdp += 'a=rtcp-rsize\r\n';
-
- if (transceiver.iceGatherer && pc.iceGatheringState !== 'new' &&
- (sdpMLineIndex === 0 || !pc.usingBundle)) {
- transceiver.iceGatherer.getLocalCandidates().forEach(function(cand) {
- cand.component = 1;
- sdp += 'a=' + SDPUtils.writeCandidate(cand) + '\r\n';
- });
-
- if (transceiver.iceGatherer.state === 'completed') {
- sdp += 'a=end-of-candidates\r\n';
- }
- }
- });
-
- var desc = new window.RTCSessionDescription({
- type: 'offer',
- sdp: sdp
- });
- return Promise.resolve(desc);
- };
-
- RTCPeerConnection.prototype.createAnswer = function() {
- var pc = this;
-
- if (this._isClosed) {
- return Promise.reject(makeError('InvalidStateError',
- 'Can not call createAnswer after close'));
- }
-
- var sdp = SDPUtils.writeSessionBoilerplate(this._sdpSessionId,
- this._sdpSessionVersion++);
- if (this.usingBundle) {
- sdp += 'a=group:BUNDLE ' + this.transceivers.map(function(t) {
- return t.mid;
- }).join(' ') + '\r\n';
- }
- var mediaSectionsInOffer = SDPUtils.splitSections(
- this.remoteDescription.sdp).length - 1;
- this.transceivers.forEach(function(transceiver, sdpMLineIndex) {
- if (sdpMLineIndex + 1 > mediaSectionsInOffer) {
- return;
- }
- if (transceiver.isDatachannel) {
- sdp += 'm=application 0 DTLS/SCTP 5000\r\n' +
- 'c=IN IP4 0.0.0.0\r\n' +
- 'a=mid:' + transceiver.mid + '\r\n';
- return;
- }
-
- // FIXME: look at direction.
- if (transceiver.stream) {
- var localTrack;
- if (transceiver.kind === 'audio') {
- localTrack = transceiver.stream.getAudioTracks()[0];
- } else if (transceiver.kind === 'video') {
- localTrack = transceiver.stream.getVideoTracks()[0];
- }
- if (localTrack) {
- // add RTX
- if (edgeVersion >= 15019 && transceiver.kind === 'video' &&
- !transceiver.sendEncodingParameters[0].rtx) {
- transceiver.sendEncodingParameters[0].rtx = {
- ssrc: transceiver.sendEncodingParameters[0].ssrc + 1
- };
- }
- }
- }
-
- // Calculate intersection of capabilities.
- var commonCapabilities = getCommonCapabilities(
- transceiver.localCapabilities,
- transceiver.remoteCapabilities);
-
- var hasRtx = commonCapabilities.codecs.filter(function(c) {
- return c.name.toLowerCase() === 'rtx';
- }).length;
- if (!hasRtx && transceiver.sendEncodingParameters[0].rtx) {
- delete transceiver.sendEncodingParameters[0].rtx;
- }
-
- sdp += writeMediaSection(transceiver, commonCapabilities,
- 'answer', transceiver.stream, pc._dtlsRole);
- if (transceiver.rtcpParameters &&
- transceiver.rtcpParameters.reducedSize) {
- sdp += 'a=rtcp-rsize\r\n';
- }
- });
-
- var desc = new window.RTCSessionDescription({
- type: 'answer',
- sdp: sdp
- });
- return Promise.resolve(desc);
- };
-
- RTCPeerConnection.prototype.addIceCandidate = function(candidate) {
- var sections;
- if (!candidate || candidate.candidate === '') {
- for (var j = 0; j < this.transceivers.length; j++) {
- if (this.transceivers[j].isDatachannel) {
- continue;
- }
- this.transceivers[j].iceTransport.addRemoteCandidate({});
- sections = SDPUtils.splitSections(this.remoteDescription.sdp);
- sections[j + 1] += 'a=end-of-candidates\r\n';
- this.remoteDescription.sdp = sections.join('');
- if (this.usingBundle) {
- break;
- }
- }
- } else if (!(candidate.sdpMLineIndex !== undefined || candidate.sdpMid)) {
- throw new TypeError('sdpMLineIndex or sdpMid required');
- } else if (!this.remoteDescription) {
- return Promise.reject(makeError('InvalidStateError',
- 'Can not add ICE candidate without a remote description'));
- } else {
- var sdpMLineIndex = candidate.sdpMLineIndex;
- if (candidate.sdpMid) {
- for (var i = 0; i < this.transceivers.length; i++) {
- if (this.transceivers[i].mid === candidate.sdpMid) {
- sdpMLineIndex = i;
- break;
- }
- }
- }
- var transceiver = this.transceivers[sdpMLineIndex];
- if (transceiver) {
- if (transceiver.isDatachannel) {
- return Promise.resolve();
- }
- var cand = Object.keys(candidate.candidate).length > 0 ?
- SDPUtils.parseCandidate(candidate.candidate) : {};
- // Ignore Chrome's invalid candidates since Edge does not like them.
- if (cand.protocol === 'tcp' && (cand.port === 0 || cand.port === 9)) {
- return Promise.resolve();
- }
- // Ignore RTCP candidates, we assume RTCP-MUX.
- if (cand.component && cand.component !== 1) {
- return Promise.resolve();
- }
- // when using bundle, avoid adding candidates to the wrong
- // ice transport. And avoid adding candidates added in the SDP.
- if (sdpMLineIndex === 0 || (sdpMLineIndex > 0 &&
- transceiver.iceTransport !== this.transceivers[0].iceTransport)) {
- if (!maybeAddCandidate(transceiver.iceTransport, cand)) {
- return Promise.reject(makeError('OperationError',
- 'Can not add ICE candidate'));
- }
- }
-
- // update the remoteDescription.
- var candidateString = candidate.candidate.trim();
- if (candidateString.indexOf('a=') === 0) {
- candidateString = candidateString.substr(2);
- }
- sections = SDPUtils.splitSections(this.remoteDescription.sdp);
- sections[sdpMLineIndex + 1] += 'a=' +
- (cand.type ? candidateString : 'end-of-candidates')
- + '\r\n';
- this.remoteDescription.sdp = sections.join('');
- } else {
- return Promise.reject(makeError('OperationError',
- 'Can not add ICE candidate'));
- }
- }
- return Promise.resolve();
- };
-
- RTCPeerConnection.prototype.getStats = function() {
- var promises = [];
- this.transceivers.forEach(function(transceiver) {
- ['rtpSender', 'rtpReceiver', 'iceGatherer', 'iceTransport',
- 'dtlsTransport'].forEach(function(method) {
- if (transceiver[method]) {
- promises.push(transceiver[method].getStats());
- }
- });
- });
- var fixStatsType = function(stat) {
- return {
- inboundrtp: 'inbound-rtp',
- outboundrtp: 'outbound-rtp',
- candidatepair: 'candidate-pair',
- localcandidate: 'local-candidate',
- remotecandidate: 'remote-candidate'
- }[stat.type] || stat.type;
- };
- return new Promise(function(resolve) {
- // shim getStats with maplike support
- var results = new Map();
- Promise.all(promises).then(function(res) {
- res.forEach(function(result) {
- Object.keys(result).forEach(function(id) {
- result[id].type = fixStatsType(result[id]);
- results.set(id, result[id]);
- });
- });
- resolve(results);
- });
- });
- };
-
- // legacy callback shims. Should be moved to adapter.js some days.
- var methods = ['createOffer', 'createAnswer'];
- methods.forEach(function(method) {
- var nativeMethod = RTCPeerConnection.prototype[method];
- RTCPeerConnection.prototype[method] = function() {
- var args = arguments;
- if (typeof args[0] === 'function' ||
- typeof args[1] === 'function') { // legacy
- return nativeMethod.apply(this, [arguments[2]])
- .then(function(description) {
- if (typeof args[0] === 'function') {
- args[0].apply(null, [description]);
- }
- }, function(error) {
- if (typeof args[1] === 'function') {
- args[1].apply(null, [error]);
- }
- });
- }
- return nativeMethod.apply(this, arguments);
- };
- });
-
- methods = ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate'];
- methods.forEach(function(method) {
- var nativeMethod = RTCPeerConnection.prototype[method];
- RTCPeerConnection.prototype[method] = function() {
- var args = arguments;
- if (typeof args[1] === 'function' ||
- typeof args[2] === 'function') { // legacy
- return nativeMethod.apply(this, arguments)
- .then(function() {
- if (typeof args[1] === 'function') {
- args[1].apply(null);
- }
- }, function(error) {
- if (typeof args[2] === 'function') {
- args[2].apply(null, [error]);
- }
- });
- }
- return nativeMethod.apply(this, arguments);
- };
- });
-
- // getStats is special. It doesn't have a spec legacy method yet we support
- // getStats(something, cb) without error callbacks.
- ['getStats'].forEach(function(method) {
- var nativeMethod = RTCPeerConnection.prototype[method];
- RTCPeerConnection.prototype[method] = function() {
- var args = arguments;
- if (typeof args[1] === 'function') {
- return nativeMethod.apply(this, arguments)
- .then(function() {
- if (typeof args[1] === 'function') {
- args[1].apply(null);
- }
- });
- }
- return nativeMethod.apply(this, arguments);
- };
- });
-
- return RTCPeerConnection;
-};
-
-},{"sdp":2}],2:[function(require,module,exports){
- /* eslint-env node */
-'use strict';
-
-// SDP helpers.
-var SDPUtils = {};
-
-// Generate an alphanumeric identifier for cname or mids.
-// TODO: use UUIDs instead? https://gist.github.com/jed/982883
-SDPUtils.generateIdentifier = function() {
- return Math.random().toString(36).substr(2, 10);
-};
-
-// The RTCP CNAME used by all peerconnections from the same JS.
-SDPUtils.localCName = SDPUtils.generateIdentifier();
-
-// Splits SDP into lines, dealing with both CRLF and LF.
-SDPUtils.splitLines = function(blob) {
- return blob.trim().split('\n').map(function(line) {
- return line.trim();
- });
-};
-// Splits SDP into sessionpart and mediasections. Ensures CRLF.
-SDPUtils.splitSections = function(blob) {
- var parts = blob.split('\nm=');
- return parts.map(function(part, index) {
- return (index > 0 ? 'm=' + part : part).trim() + '\r\n';
- });
-};
-
-// Returns lines that start with a certain prefix.
-SDPUtils.matchPrefix = function(blob, prefix) {
- return SDPUtils.splitLines(blob).filter(function(line) {
- return line.indexOf(prefix) === 0;
- });
-};
-
-// Parses an ICE candidate line. Sample input:
-// candidate:702786350 2 udp 41819902 8.8.8.8 60769 typ relay raddr 8.8.8.8
-// rport 55996"
-SDPUtils.parseCandidate = function(line) {
- var parts;
- // Parse both variants.
- if (line.indexOf('a=candidate:') === 0) {
- parts = line.substring(12).split(' ');
- } else {
- parts = line.substring(10).split(' ');
- }
-
- var candidate = {
- foundation: parts[0],
- component: parseInt(parts[1], 10),
- protocol: parts[2].toLowerCase(),
- priority: parseInt(parts[3], 10),
- ip: parts[4],
- port: parseInt(parts[5], 10),
- // skip parts[6] == 'typ'
- type: parts[7]
- };
-
- for (var i = 8; i < parts.length; i += 2) {
- switch (parts[i]) {
- case 'raddr':
- candidate.relatedAddress = parts[i + 1];
- break;
- case 'rport':
- candidate.relatedPort = parseInt(parts[i + 1], 10);
- break;
- case 'tcptype':
- candidate.tcpType = parts[i + 1];
- break;
- case 'ufrag':
- candidate.ufrag = parts[i + 1]; // for backward compability.
- candidate.usernameFragment = parts[i + 1];
- break;
- default: // extension handling, in particular ufrag
- candidate[parts[i]] = parts[i + 1];
- break;
- }
- }
- return candidate;
-};
-
-// Translates a candidate object into SDP candidate attribute.
-SDPUtils.writeCandidate = function(candidate) {
- var sdp = [];
- sdp.push(candidate.foundation);
- sdp.push(candidate.component);
- sdp.push(candidate.protocol.toUpperCase());
- sdp.push(candidate.priority);
- sdp.push(candidate.ip);
- sdp.push(candidate.port);
-
- var type = candidate.type;
- sdp.push('typ');
- sdp.push(type);
- if (type !== 'host' && candidate.relatedAddress &&
- candidate.relatedPort) {
- sdp.push('raddr');
- sdp.push(candidate.relatedAddress); // was: relAddr
- sdp.push('rport');
- sdp.push(candidate.relatedPort); // was: relPort
- }
- if (candidate.tcpType && candidate.protocol.toLowerCase() === 'tcp') {
- sdp.push('tcptype');
- sdp.push(candidate.tcpType);
- }
- if (candidate.ufrag) {
- sdp.push('ufrag');
- sdp.push(candidate.ufrag);
- }
- return 'candidate:' + sdp.join(' ');
-};
-
-// Parses an ice-options line, returns an array of option tags.
-// a=ice-options:foo bar
-SDPUtils.parseIceOptions = function(line) {
- return line.substr(14).split(' ');
-}
-
-// Parses an rtpmap line, returns RTCRtpCoddecParameters. Sample input:
-// a=rtpmap:111 opus/48000/2
-SDPUtils.parseRtpMap = function(line) {
- var parts = line.substr(9).split(' ');
- var parsed = {
- payloadType: parseInt(parts.shift(), 10) // was: id
- };
-
- parts = parts[0].split('/');
-
- parsed.name = parts[0];
- parsed.clockRate = parseInt(parts[1], 10); // was: clockrate
- // was: channels
- parsed.numChannels = parts.length === 3 ? parseInt(parts[2], 10) : 1;
- return parsed;
-};
-
-// Generate an a=rtpmap line from RTCRtpCodecCapability or
-// RTCRtpCodecParameters.
-SDPUtils.writeRtpMap = function(codec) {
- var pt = codec.payloadType;
- if (codec.preferredPayloadType !== undefined) {
- pt = codec.preferredPayloadType;
- }
- return 'a=rtpmap:' + pt + ' ' + codec.name + '/' + codec.clockRate +
- (codec.numChannels !== 1 ? '/' + codec.numChannels : '') + '\r\n';
-};
-
-// Parses an a=extmap line (headerextension from RFC 5285). Sample input:
-// a=extmap:2 urn:ietf:params:rtp-hdrext:toffset
-// a=extmap:2/sendonly urn:ietf:params:rtp-hdrext:toffset
-SDPUtils.parseExtmap = function(line) {
- var parts = line.substr(9).split(' ');
- return {
- id: parseInt(parts[0], 10),
- direction: parts[0].indexOf('/') > 0 ? parts[0].split('/')[1] : 'sendrecv',
- uri: parts[1]
- };
-};
-
-// Generates a=extmap line from RTCRtpHeaderExtensionParameters or
-// RTCRtpHeaderExtension.
-SDPUtils.writeExtmap = function(headerExtension) {
- return 'a=extmap:' + (headerExtension.id || headerExtension.preferredId) +
- (headerExtension.direction && headerExtension.direction !== 'sendrecv'
- ? '/' + headerExtension.direction
- : '') +
- ' ' + headerExtension.uri + '\r\n';
-};
-
-// Parses an ftmp line, returns dictionary. Sample input:
-// a=fmtp:96 vbr=on;cng=on
-// Also deals with vbr=on; cng=on
-SDPUtils.parseFmtp = function(line) {
- var parsed = {};
- var kv;
- var parts = line.substr(line.indexOf(' ') + 1).split(';');
- for (var j = 0; j < parts.length; j++) {
- kv = parts[j].trim().split('=');
- parsed[kv[0].trim()] = kv[1];
- }
- return parsed;
-};
-
-// Generates an a=ftmp line from RTCRtpCodecCapability or RTCRtpCodecParameters.
-SDPUtils.writeFmtp = function(codec) {
- var line = '';
- var pt = codec.payloadType;
- if (codec.preferredPayloadType !== undefined) {
- pt = codec.preferredPayloadType;
- }
- if (codec.parameters && Object.keys(codec.parameters).length) {
- var params = [];
- Object.keys(codec.parameters).forEach(function(param) {
- params.push(param + '=' + codec.parameters[param]);
- });
- line += 'a=fmtp:' + pt + ' ' + params.join(';') + '\r\n';
- }
- return line;
-};
-
-// Parses an rtcp-fb line, returns RTCPRtcpFeedback object. Sample input:
-// a=rtcp-fb:98 nack rpsi
-SDPUtils.parseRtcpFb = function(line) {
- var parts = line.substr(line.indexOf(' ') + 1).split(' ');
- return {
- type: parts.shift(),
- parameter: parts.join(' ')
- };
-};
-// Generate a=rtcp-fb lines from RTCRtpCodecCapability or RTCRtpCodecParameters.
-SDPUtils.writeRtcpFb = function(codec) {
- var lines = '';
- var pt = codec.payloadType;
- if (codec.preferredPayloadType !== undefined) {
- pt = codec.preferredPayloadType;
- }
- if (codec.rtcpFeedback && codec.rtcpFeedback.length) {
- // FIXME: special handling for trr-int?
- codec.rtcpFeedback.forEach(function(fb) {
- lines += 'a=rtcp-fb:' + pt + ' ' + fb.type +
- (fb.parameter && fb.parameter.length ? ' ' + fb.parameter : '') +
- '\r\n';
- });
- }
- return lines;
-};
-
-// Parses an RFC 5576 ssrc media attribute. Sample input:
-// a=ssrc:3735928559 cname:something
-SDPUtils.parseSsrcMedia = function(line) {
- var sp = line.indexOf(' ');
- var parts = {
- ssrc: parseInt(line.substr(7, sp - 7), 10)
- };
- var colon = line.indexOf(':', sp);
- if (colon > -1) {
- parts.attribute = line.substr(sp + 1, colon - sp - 1);
- parts.value = line.substr(colon + 1);
- } else {
- parts.attribute = line.substr(sp + 1);
- }
- return parts;
-};
-
-// Extracts the MID (RFC 5888) from a media section.
-// returns the MID or undefined if no mid line was found.
-SDPUtils.getMid = function(mediaSection) {
- var mid = SDPUtils.matchPrefix(mediaSection, 'a=mid:')[0];
- if (mid) {
- return mid.substr(6);
- }
-}
-
-SDPUtils.parseFingerprint = function(line) {
- var parts = line.substr(14).split(' ');
- return {
- algorithm: parts[0].toLowerCase(), // algorithm is case-sensitive in Edge.
- value: parts[1]
- };
-};
-
-// Extracts DTLS parameters from SDP media section or sessionpart.
-// FIXME: for consistency with other functions this should only
-// get the fingerprint line as input. See also getIceParameters.
-SDPUtils.getDtlsParameters = function(mediaSection, sessionpart) {
- var lines = SDPUtils.matchPrefix(mediaSection + sessionpart,
- 'a=fingerprint:');
- // Note: a=setup line is ignored since we use the 'auto' role.
- // Note2: 'algorithm' is not case sensitive except in Edge.
- return {
- role: 'auto',
- fingerprints: lines.map(SDPUtils.parseFingerprint)
- };
-};
-
-// Serializes DTLS parameters to SDP.
-SDPUtils.writeDtlsParameters = function(params, setupType) {
- var sdp = 'a=setup:' + setupType + '\r\n';
- params.fingerprints.forEach(function(fp) {
- sdp += 'a=fingerprint:' + fp.algorithm + ' ' + fp.value + '\r\n';
- });
- return sdp;
-};
-// Parses ICE information from SDP media section or sessionpart.
-// FIXME: for consistency with other functions this should only
-// get the ice-ufrag and ice-pwd lines as input.
-SDPUtils.getIceParameters = function(mediaSection, sessionpart) {
- var lines = SDPUtils.splitLines(mediaSection);
- // Search in session part, too.
- lines = lines.concat(SDPUtils.splitLines(sessionpart));
- var iceParameters = {
- usernameFragment: lines.filter(function(line) {
- return line.indexOf('a=ice-ufrag:') === 0;
- })[0].substr(12),
- password: lines.filter(function(line) {
- return line.indexOf('a=ice-pwd:') === 0;
- })[0].substr(10)
- };
- return iceParameters;
-};
-
-// Serializes ICE parameters to SDP.
-SDPUtils.writeIceParameters = function(params) {
- return 'a=ice-ufrag:' + params.usernameFragment + '\r\n' +
- 'a=ice-pwd:' + params.password + '\r\n';
-};
-
-// Parses the SDP media section and returns RTCRtpParameters.
-SDPUtils.parseRtpParameters = function(mediaSection) {
- var description = {
- codecs: [],
- headerExtensions: [],
- fecMechanisms: [],
- rtcp: []
- };
- var lines = SDPUtils.splitLines(mediaSection);
- var mline = lines[0].split(' ');
- for (var i = 3; i < mline.length; i++) { // find all codecs from mline[3..]
- var pt = mline[i];
- var rtpmapline = SDPUtils.matchPrefix(
- mediaSection, 'a=rtpmap:' + pt + ' ')[0];
- if (rtpmapline) {
- var codec = SDPUtils.parseRtpMap(rtpmapline);
- var fmtps = SDPUtils.matchPrefix(
- mediaSection, 'a=fmtp:' + pt + ' ');
- // Only the first a=fmtp: is considered.
- codec.parameters = fmtps.length ? SDPUtils.parseFmtp(fmtps[0]) : {};
- codec.rtcpFeedback = SDPUtils.matchPrefix(
- mediaSection, 'a=rtcp-fb:' + pt + ' ')
- .map(SDPUtils.parseRtcpFb);
- description.codecs.push(codec);
- // parse FEC mechanisms from rtpmap lines.
- switch (codec.name.toUpperCase()) {
- case 'RED':
- case 'ULPFEC':
- description.fecMechanisms.push(codec.name.toUpperCase());
- break;
- default: // only RED and ULPFEC are recognized as FEC mechanisms.
- break;
- }
- }
- }
- SDPUtils.matchPrefix(mediaSection, 'a=extmap:').forEach(function(line) {
- description.headerExtensions.push(SDPUtils.parseExtmap(line));
- });
- // FIXME: parse rtcp.
- return description;
-};
-
-// Generates parts of the SDP media section describing the capabilities /
-// parameters.
-SDPUtils.writeRtpDescription = function(kind, caps) {
- var sdp = '';
-
- // Build the mline.
- sdp += 'm=' + kind + ' ';
- sdp += caps.codecs.length > 0 ? '9' : '0'; // reject if no codecs.
- sdp += ' UDP/TLS/RTP/SAVPF ';
- sdp += caps.codecs.map(function(codec) {
- if (codec.preferredPayloadType !== undefined) {
- return codec.preferredPayloadType;
- }
- return codec.payloadType;
- }).join(' ') + '\r\n';
-
- sdp += 'c=IN IP4 0.0.0.0\r\n';
- sdp += 'a=rtcp:9 IN IP4 0.0.0.0\r\n';
-
- // Add a=rtpmap lines for each codec. Also fmtp and rtcp-fb.
- caps.codecs.forEach(function(codec) {
- sdp += SDPUtils.writeRtpMap(codec);
- sdp += SDPUtils.writeFmtp(codec);
- sdp += SDPUtils.writeRtcpFb(codec);
- });
- var maxptime = 0;
- caps.codecs.forEach(function(codec) {
- if (codec.maxptime > maxptime) {
- maxptime = codec.maxptime;
- }
- });
- if (maxptime > 0) {
- sdp += 'a=maxptime:' + maxptime + '\r\n';
- }
- sdp += 'a=rtcp-mux\r\n';
-
- caps.headerExtensions.forEach(function(extension) {
- sdp += SDPUtils.writeExtmap(extension);
- });
- // FIXME: write fecMechanisms.
- return sdp;
-};
-
-// Parses the SDP media section and returns an array of
-// RTCRtpEncodingParameters.
-SDPUtils.parseRtpEncodingParameters = function(mediaSection) {
- var encodingParameters = [];
- var description = SDPUtils.parseRtpParameters(mediaSection);
- var hasRed = description.fecMechanisms.indexOf('RED') !== -1;
- var hasUlpfec = description.fecMechanisms.indexOf('ULPFEC') !== -1;
-
- // filter a=ssrc:... cname:, ignore PlanB-msid
- var ssrcs = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:')
- .map(function(line) {
- return SDPUtils.parseSsrcMedia(line);
- })
- .filter(function(parts) {
- return parts.attribute === 'cname';
- });
- var primarySsrc = ssrcs.length > 0 && ssrcs[0].ssrc;
- var secondarySsrc;
-
- var flows = SDPUtils.matchPrefix(mediaSection, 'a=ssrc-group:FID')
- .map(function(line) {
- var parts = line.split(' ');
- parts.shift();
- return parts.map(function(part) {
- return parseInt(part, 10);
- });
- });
- if (flows.length > 0 && flows[0].length > 1 && flows[0][0] === primarySsrc) {
- secondarySsrc = flows[0][1];
- }
-
- description.codecs.forEach(function(codec) {
- if (codec.name.toUpperCase() === 'RTX' && codec.parameters.apt) {
- var encParam = {
- ssrc: primarySsrc,
- codecPayloadType: parseInt(codec.parameters.apt, 10),
- rtx: {
- ssrc: secondarySsrc
- }
- };
- encodingParameters.push(encParam);
- if (hasRed) {
- encParam = JSON.parse(JSON.stringify(encParam));
- encParam.fec = {
- ssrc: secondarySsrc,
- mechanism: hasUlpfec ? 'red+ulpfec' : 'red'
- };
- encodingParameters.push(encParam);
- }
- }
- });
- if (encodingParameters.length === 0 && primarySsrc) {
- encodingParameters.push({
- ssrc: primarySsrc
- });
- }
-
- // we support both b=AS and b=TIAS but interpret AS as TIAS.
- var bandwidth = SDPUtils.matchPrefix(mediaSection, 'b=');
- if (bandwidth.length) {
- if (bandwidth[0].indexOf('b=TIAS:') === 0) {
- bandwidth = parseInt(bandwidth[0].substr(7), 10);
- } else if (bandwidth[0].indexOf('b=AS:') === 0) {
- // use formula from JSEP to convert b=AS to TIAS value.
- bandwidth = parseInt(bandwidth[0].substr(5), 10) * 1000 * 0.95
- - (50 * 40 * 8);
- } else {
- bandwidth = undefined;
- }
- encodingParameters.forEach(function(params) {
- params.maxBitrate = bandwidth;
- });
- }
- return encodingParameters;
-};
-
-// parses http://draft.ortc.org/#rtcrtcpparameters*
-SDPUtils.parseRtcpParameters = function(mediaSection) {
- var rtcpParameters = {};
-
- var cname;
- // Gets the first SSRC. Note that with RTX there might be multiple
- // SSRCs.
- var remoteSsrc = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:')
- .map(function(line) {
- return SDPUtils.parseSsrcMedia(line);
- })
- .filter(function(obj) {
- return obj.attribute === 'cname';
- })[0];
- if (remoteSsrc) {
- rtcpParameters.cname = remoteSsrc.value;
- rtcpParameters.ssrc = remoteSsrc.ssrc;
- }
-
- // Edge uses the compound attribute instead of reducedSize
- // compound is !reducedSize
- var rsize = SDPUtils.matchPrefix(mediaSection, 'a=rtcp-rsize');
- rtcpParameters.reducedSize = rsize.length > 0;
- rtcpParameters.compound = rsize.length === 0;
-
- // parses the rtcp-mux attrŃ–bute.
- // Note that Edge does not support unmuxed RTCP.
- var mux = SDPUtils.matchPrefix(mediaSection, 'a=rtcp-mux');
- rtcpParameters.mux = mux.length > 0;
-
- return rtcpParameters;
-};
-
-// parses either a=msid: or a=ssrc:... msid lines and returns
-// the id of the MediaStream and MediaStreamTrack.
-SDPUtils.parseMsid = function(mediaSection) {
- var parts;
- var spec = SDPUtils.matchPrefix(mediaSection, 'a=msid:');
- if (spec.length === 1) {
- parts = spec[0].substr(7).split(' ');
- return {stream: parts[0], track: parts[1]};
- }
- var planB = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:')
- .map(function(line) {
- return SDPUtils.parseSsrcMedia(line);
- })
- .filter(function(parts) {
- return parts.attribute === 'msid';
- });
- if (planB.length > 0) {
- parts = planB[0].value.split(' ');
- return {stream: parts[0], track: parts[1]};
- }
-};
-
-// Generate a session ID for SDP.
-// https://tools.ietf.org/html/draft-ietf-rtcweb-jsep-20#section-5.2.1
-// recommends using a cryptographically random +ve 64-bit value
-// but right now this should be acceptable and within the right range
-SDPUtils.generateSessionId = function() {
- return Math.random().toString().substr(2, 21);
-};
-
-// Write boilder plate for start of SDP
-// sessId argument is optional - if not supplied it will
-// be generated randomly
-// sessVersion is optional and defaults to 2
-SDPUtils.writeSessionBoilerplate = function(sessId, sessVer) {
- var sessionId;
- var version = sessVer !== undefined ? sessVer : 2;
- if (sessId) {
- sessionId = sessId;
- } else {
- sessionId = SDPUtils.generateSessionId();
- }
- // FIXME: sess-id should be an NTP timestamp.
- return 'v=0\r\n' +
- 'o=thisisadapterortc ' + sessionId + ' ' + version + ' IN IP4 127.0.0.1\r\n' +
- 's=-\r\n' +
- 't=0 0\r\n';
-};
-
-SDPUtils.writeMediaSection = function(transceiver, caps, type, stream) {
- var sdp = SDPUtils.writeRtpDescription(transceiver.kind, caps);
-
- // Map ICE parameters (ufrag, pwd) to SDP.
- sdp += SDPUtils.writeIceParameters(
- transceiver.iceGatherer.getLocalParameters());
-
- // Map DTLS parameters to SDP.
- sdp += SDPUtils.writeDtlsParameters(
- transceiver.dtlsTransport.getLocalParameters(),
- type === 'offer' ? 'actpass' : 'active');
-
- sdp += 'a=mid:' + transceiver.mid + '\r\n';
-
- if (transceiver.direction) {
- sdp += 'a=' + transceiver.direction + '\r\n';
- } else if (transceiver.rtpSender && transceiver.rtpReceiver) {
- sdp += 'a=sendrecv\r\n';
- } else if (transceiver.rtpSender) {
- sdp += 'a=sendonly\r\n';
- } else if (transceiver.rtpReceiver) {
- sdp += 'a=recvonly\r\n';
- } else {
- sdp += 'a=inactive\r\n';
- }
-
- if (transceiver.rtpSender) {
- // spec.
- var msid = 'msid:' + stream.id + ' ' +
- transceiver.rtpSender.track.id + '\r\n';
- sdp += 'a=' + msid;
-
- // for Chrome.
- sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].ssrc +
- ' ' + msid;
- if (transceiver.sendEncodingParameters[0].rtx) {
- sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].rtx.ssrc +
- ' ' + msid;
- sdp += 'a=ssrc-group:FID ' +
- transceiver.sendEncodingParameters[0].ssrc + ' ' +
- transceiver.sendEncodingParameters[0].rtx.ssrc +
- '\r\n';
- }
- }
- // FIXME: this should be written by writeRtpDescription.
- sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].ssrc +
- ' cname:' + SDPUtils.localCName + '\r\n';
- if (transceiver.rtpSender && transceiver.sendEncodingParameters[0].rtx) {
- sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].rtx.ssrc +
- ' cname:' + SDPUtils.localCName + '\r\n';
- }
- return sdp;
-};
-
-// Gets the direction from the mediaSection or the sessionpart.
-SDPUtils.getDirection = function(mediaSection, sessionpart) {
- // Look for sendrecv, sendonly, recvonly, inactive, default to sendrecv.
- var lines = SDPUtils.splitLines(mediaSection);
- for (var i = 0; i < lines.length; i++) {
- switch (lines[i]) {
- case 'a=sendrecv':
- case 'a=sendonly':
- case 'a=recvonly':
- case 'a=inactive':
- return lines[i].substr(2);
- default:
- // FIXME: What should happen here?
- }
- }
- if (sessionpart) {
- return SDPUtils.getDirection(sessionpart);
- }
- return 'sendrecv';
-};
-
-SDPUtils.getKind = function(mediaSection) {
- var lines = SDPUtils.splitLines(mediaSection);
- var mline = lines[0].split(' ');
- return mline[0].substr(2);
-};
-
-SDPUtils.isRejected = function(mediaSection) {
- return mediaSection.split(' ', 2)[1] === '0';
-};
-
-SDPUtils.parseMLine = function(mediaSection) {
- var lines = SDPUtils.splitLines(mediaSection);
- var mline = lines[0].split(' ');
- return {
- kind: mline[0].substr(2),
- port: parseInt(mline[1], 10),
- protocol: mline[2],
- fmt: mline.slice(3).join(' ')
- };
-};
-
-// Expose public methods.
-if (typeof module === 'object') {
- module.exports = SDPUtils;
-}
-
-},{}],3:[function(require,module,exports){
-(function (global){
-/*
- * Copyright (c) 2016 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.
- */
- /* eslint-env node */
-
-'use strict';
-
-var adapterFactory = require('./adapter_factory.js');
-module.exports = adapterFactory({window: global.window});
-
-}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-},{"./adapter_factory.js":4}],4:[function(require,module,exports){
-/*
- * Copyright (c) 2016 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.
- */
- /* eslint-env node */
-
-'use strict';
-
-var utils = require('./utils');
-// Shimming starts here.
-module.exports = function(dependencies, opts) {
- var window = dependencies && dependencies.window;
-
- var options = {
- shimChrome: true,
- shimFirefox: true,
- shimEdge: true,
- shimSafari: true,
- };
-
- for (var key in opts) {
- if (hasOwnProperty.call(opts, key)) {
- options[key] = opts[key];
- }
- }
-
- // Utils.
- var logging = utils.log;
- var browserDetails = utils.detectBrowser(window);
-
- // Uncomment the line below if you want logging to occur, including logging
- // for the switch statement below. Can also be turned on in the browser via
- // adapter.disableLog(false), but then logging from the switch statement below
- // will not appear.
- // require('./utils').disableLog(false);
-
- // Browser shims.
- var chromeShim = require('./chrome/chrome_shim') || null;
- var edgeShim = require('./edge/edge_shim') || null;
- var firefoxShim = require('./firefox/firefox_shim') || null;
- var safariShim = require('./safari/safari_shim') || null;
- var commonShim = require('./common_shim') || null;
-
- // Export to the adapter global object visible in the browser.
- var adapter = {
- browserDetails: browserDetails,
- commonShim: commonShim,
- extractVersion: utils.extractVersion,
- disableLog: utils.disableLog,
- disableWarnings: utils.disableWarnings
- };
-
- // Shim browser if found.
- switch (browserDetails.browser) {
- case 'chrome':
- if (!chromeShim || !chromeShim.shimPeerConnection ||
- !options.shimChrome) {
- logging('Chrome shim is not included in this adapter release.');
- return adapter;
- }
- logging('adapter.js shimming chrome.');
- // Export to the adapter global object visible in the browser.
- adapter.browserShim = chromeShim;
- commonShim.shimCreateObjectURL(window);
-
- chromeShim.shimGetUserMedia(window);
- chromeShim.shimMediaStream(window);
- chromeShim.shimSourceObject(window);
- chromeShim.shimPeerConnection(window);
- chromeShim.shimOnTrack(window);
- chromeShim.shimAddTrackRemoveTrack(window);
- chromeShim.shimGetSendersWithDtmf(window);
-
- commonShim.shimRTCIceCandidate(window);
- commonShim.shimMaxMessageSize(window);
- commonShim.shimSendThrowTypeError(window);
- break;
- case 'firefox':
- if (!firefoxShim || !firefoxShim.shimPeerConnection ||
- !options.shimFirefox) {
- logging('Firefox shim is not included in this adapter release.');
- return adapter;
- }
- logging('adapter.js shimming firefox.');
- // Export to the adapter global object visible in the browser.
- adapter.browserShim = firefoxShim;
- commonShim.shimCreateObjectURL(window);
-
- firefoxShim.shimGetUserMedia(window);
- firefoxShim.shimSourceObject(window);
- firefoxShim.shimPeerConnection(window);
- firefoxShim.shimOnTrack(window);
- firefoxShim.shimRemoveStream(window);
-
- commonShim.shimRTCIceCandidate(window);
- commonShim.shimMaxMessageSize(window);
- commonShim.shimSendThrowTypeError(window);
- break;
- case 'edge':
- if (!edgeShim || !edgeShim.shimPeerConnection || !options.shimEdge) {
- logging('MS edge shim is not included in this adapter release.');
- return adapter;
- }
- logging('adapter.js shimming edge.');
- // Export to the adapter global object visible in the browser.
- adapter.browserShim = edgeShim;
- commonShim.shimCreateObjectURL(window);
-
- edgeShim.shimGetUserMedia(window);
- edgeShim.shimPeerConnection(window);
- edgeShim.shimReplaceTrack(window);
-
- // the edge shim implements the full RTCIceCandidate object.
-
- commonShim.shimMaxMessageSize(window);
- commonShim.shimSendThrowTypeError(window);
- break;
- case 'safari':
- if (!safariShim || !options.shimSafari) {
- logging('Safari shim is not included in this adapter release.');
- return adapter;
- }
- logging('adapter.js shimming safari.');
- // Export to the adapter global object visible in the browser.
- adapter.browserShim = safariShim;
- commonShim.shimCreateObjectURL(window);
-
- safariShim.shimRTCIceServerUrls(window);
- safariShim.shimCallbacksAPI(window);
- safariShim.shimLocalStreamsAPI(window);
- safariShim.shimRemoteStreamsAPI(window);
- safariShim.shimTrackEventTransceiver(window);
- safariShim.shimGetUserMedia(window);
- safariShim.shimCreateOfferLegacy(window);
-
- commonShim.shimRTCIceCandidate(window);
- commonShim.shimMaxMessageSize(window);
- commonShim.shimSendThrowTypeError(window);
- break;
- default:
- logging('Unsupported browser!');
- break;
- }
-
- return adapter;
-};
-
-},{"./chrome/chrome_shim":5,"./common_shim":7,"./edge/edge_shim":8,"./firefox/firefox_shim":10,"./safari/safari_shim":12,"./utils":13}],5:[function(require,module,exports){
-
-/*
- * Copyright (c) 2016 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.
- */
- /* eslint-env node */
-'use strict';
-var utils = require('../utils.js');
-var logging = utils.log;
-
-module.exports = {
- shimGetUserMedia: require('./getusermedia'),
- shimMediaStream: function(window) {
- window.MediaStream = window.MediaStream || window.webkitMediaStream;
- },
-
- shimOnTrack: function(window) {
- if (typeof window === 'object' && window.RTCPeerConnection && !('ontrack' in
- window.RTCPeerConnection.prototype)) {
- Object.defineProperty(window.RTCPeerConnection.prototype, 'ontrack', {
- get: function() {
- return this._ontrack;
- },
- set: function(f) {
- if (this._ontrack) {
- this.removeEventListener('track', this._ontrack);
- }
- this.addEventListener('track', this._ontrack = f);
- }
- });
- var origSetRemoteDescription =
- window.RTCPeerConnection.prototype.setRemoteDescription;
- window.RTCPeerConnection.prototype.setRemoteDescription = function() {
- var pc = this;
- if (!pc._ontrackpoly) {
- pc._ontrackpoly = function(e) {
- // onaddstream does not fire when a track is added to an existing
- // stream. But stream.onaddtrack is implemented so we use that.
- e.stream.addEventListener('addtrack', function(te) {
- var receiver;
- if (window.RTCPeerConnection.prototype.getReceivers) {
- receiver = pc.getReceivers().find(function(r) {
- return r.track && r.track.id === te.track.id;
- });
- } else {
- receiver = {track: te.track};
- }
-
- var event = new Event('track');
- event.track = te.track;
- event.receiver = receiver;
- event.transceiver = {receiver: receiver};
- event.streams = [e.stream];
- pc.dispatchEvent(event);
- });
- e.stream.getTracks().forEach(function(track) {
- var receiver;
- if (window.RTCPeerConnection.prototype.getReceivers) {
- receiver = pc.getReceivers().find(function(r) {
- return r.track && r.track.id === track.id;
- });
- } else {
- receiver = {track: track};
- }
- var event = new Event('track');
- event.track = track;
- event.receiver = receiver;
- event.transceiver = {receiver: receiver};
- event.streams = [e.stream];
- pc.dispatchEvent(event);
- });
- };
- pc.addEventListener('addstream', pc._ontrackpoly);
- }
- return origSetRemoteDescription.apply(pc, arguments);
- };
- } else if (!('RTCRtpTransceiver' in window)) {
- utils.wrapPeerConnectionEvent(window, 'track', function(e) {
- if (!e.transceiver) {
- e.transceiver = {receiver: e.receiver};
- }
- return e;
- });
- }
- },
-
- shimGetSendersWithDtmf: function(window) {
- // Overrides addTrack/removeTrack, depends on shimAddTrackRemoveTrack.
- if (typeof window === 'object' && window.RTCPeerConnection &&
- !('getSenders' in window.RTCPeerConnection.prototype) &&
- 'createDTMFSender' in window.RTCPeerConnection.prototype) {
- var shimSenderWithDtmf = function(pc, track) {
- return {
- track: track,
- get dtmf() {
- if (this._dtmf === undefined) {
- if (track.kind === 'audio') {
- this._dtmf = pc.createDTMFSender(track);
- } else {
- this._dtmf = null;
- }
- }
- return this._dtmf;
- },
- _pc: pc
- };
- };
-
- // augment addTrack when getSenders is not available.
- if (!window.RTCPeerConnection.prototype.getSenders) {
- window.RTCPeerConnection.prototype.getSenders = function() {
- this._senders = this._senders || [];
- return this._senders.slice(); // return a copy of the internal state.
- };
- var origAddTrack = window.RTCPeerConnection.prototype.addTrack;
- window.RTCPeerConnection.prototype.addTrack = function(track, stream) {
- var pc = this;
- var sender = origAddTrack.apply(pc, arguments);
- if (!sender) {
- sender = shimSenderWithDtmf(pc, track);
- pc._senders.push(sender);
- }
- return sender;
- };
-
- var origRemoveTrack = window.RTCPeerConnection.prototype.removeTrack;
- window.RTCPeerConnection.prototype.removeTrack = function(sender) {
- var pc = this;
- origRemoveTrack.apply(pc, arguments);
- var idx = pc._senders.indexOf(sender);
- if (idx !== -1) {
- pc._senders.splice(idx, 1);
- }
- };
- }
- var origAddStream = window.RTCPeerConnection.prototype.addStream;
- window.RTCPeerConnection.prototype.addStream = function(stream) {
- var pc = this;
- pc._senders = pc._senders || [];
- origAddStream.apply(pc, [stream]);
- stream.getTracks().forEach(function(track) {
- pc._senders.push(shimSenderWithDtmf(pc, track));
- });
- };
-
- var origRemoveStream = window.RTCPeerConnection.prototype.removeStream;
- window.RTCPeerConnection.prototype.removeStream = function(stream) {
- var pc = this;
- pc._senders = pc._senders || [];
- origRemoveStream.apply(pc, [stream]);
-
- stream.getTracks().forEach(function(track) {
- var sender = pc._senders.find(function(s) {
- return s.track === track;
- });
- if (sender) {
- pc._senders.splice(pc._senders.indexOf(sender), 1); // remove sender
- }
- });
- };
- } else if (typeof window === 'object' && window.RTCPeerConnection &&
- 'getSenders' in window.RTCPeerConnection.prototype &&
- 'createDTMFSender' in window.RTCPeerConnection.prototype &&
- window.RTCRtpSender &&
- !('dtmf' in window.RTCRtpSender.prototype)) {
- var origGetSenders = window.RTCPeerConnection.prototype.getSenders;
- window.RTCPeerConnection.prototype.getSenders = function() {
- var pc = this;
- var senders = origGetSenders.apply(pc, []);
- senders.forEach(function(sender) {
- sender._pc = pc;
- });
- return senders;
- };
-
- Object.defineProperty(window.RTCRtpSender.prototype, 'dtmf', {
- get: function() {
- if (this._dtmf === undefined) {
- if (this.track.kind === 'audio') {
- this._dtmf = this._pc.createDTMFSender(this.track);
- } else {
- this._dtmf = null;
- }
- }
- return this._dtmf;
- }
- });
- }
- },
-
- shimSourceObject: function(window) {
- var URL = window && window.URL;
-
- 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() {
- return this._srcObject;
- },
- set: function(stream) {
- var self = this;
- // Use _srcObject as a private property for this shim
- this._srcObject = stream;
- if (this.src) {
- URL.revokeObjectURL(this.src);
- }
-
- if (!stream) {
- this.src = '';
- return undefined;
- }
- this.src = URL.createObjectURL(stream);
- // We need to recreate the blob url when a track is added or
- // removed. Doing it manually since we want to avoid a recursion.
- stream.addEventListener('addtrack', function() {
- if (self.src) {
- URL.revokeObjectURL(self.src);
- }
- self.src = URL.createObjectURL(stream);
- });
- stream.addEventListener('removetrack', function() {
- if (self.src) {
- URL.revokeObjectURL(self.src);
- }
- self.src = URL.createObjectURL(stream);
- });
- }
- });
- }
- }
- },
-
- shimAddTrackRemoveTrackWithNative: function(window) {
- // shim addTrack/removeTrack with native variants in order to make
- // the interactions with legacy getLocalStreams behave as in other browsers.
- // Keeps a mapping stream.id => [stream, rtpsenders...]
- window.RTCPeerConnection.prototype.getLocalStreams = function() {
- var pc = this;
- this._shimmedLocalStreams = this._shimmedLocalStreams || {};
- return Object.keys(this._shimmedLocalStreams).map(function(streamId) {
- return pc._shimmedLocalStreams[streamId][0];
- });
- };
-
- var origAddTrack = window.RTCPeerConnection.prototype.addTrack;
- window.RTCPeerConnection.prototype.addTrack = function(track, stream) {
- if (!stream) {
- return origAddTrack.apply(this, arguments);
- }
- this._shimmedLocalStreams = this._shimmedLocalStreams || {};
-
- var sender = origAddTrack.apply(this, arguments);
- if (!this._shimmedLocalStreams[stream.id]) {
- this._shimmedLocalStreams[stream.id] = [stream, sender];
- } else if (this._shimmedLocalStreams[stream.id].indexOf(sender) === -1) {
- this._shimmedLocalStreams[stream.id].push(sender);
- }
- return sender;
- };
-
- var origAddStream = window.RTCPeerConnection.prototype.addStream;
- window.RTCPeerConnection.prototype.addStream = function(stream) {
- var pc = this;
- this._shimmedLocalStreams = this._shimmedLocalStreams || {};
-
- stream.getTracks().forEach(function(track) {
- var alreadyExists = pc.getSenders().find(function(s) {
- return s.track === track;
- });
- if (alreadyExists) {
- throw new DOMException('Track already exists.',
- 'InvalidAccessError');
- }
- });
- var existingSenders = pc.getSenders();
- origAddStream.apply(this, arguments);
- var newSenders = pc.getSenders().filter(function(newSender) {
- return existingSenders.indexOf(newSender) === -1;
- });
- this._shimmedLocalStreams[stream.id] = [stream].concat(newSenders);
- };
-
- var origRemoveStream = window.RTCPeerConnection.prototype.removeStream;
- window.RTCPeerConnection.prototype.removeStream = function(stream) {
- this._shimmedLocalStreams = this._shimmedLocalStreams || {};
- delete this._shimmedLocalStreams[stream.id];
- return origRemoveStream.apply(this, arguments);
- };
-
- var origRemoveTrack = window.RTCPeerConnection.prototype.removeTrack;
- window.RTCPeerConnection.prototype.removeTrack = function(sender) {
- var pc = this;
- this._shimmedLocalStreams = this._shimmedLocalStreams || {};
- if (sender) {
- Object.keys(this._shimmedLocalStreams).forEach(function(streamId) {
- var idx = pc._shimmedLocalStreams[streamId].indexOf(sender);
- if (idx !== -1) {
- pc._shimmedLocalStreams[streamId].splice(idx, 1);
- }
- if (pc._shimmedLocalStreams[streamId].length === 1) {
- delete pc._shimmedLocalStreams[streamId];
- }
- });
- }
- return origRemoveTrack.apply(this, arguments);
- };
- },
-
- shimAddTrackRemoveTrack: function(window) {
- var browserDetails = utils.detectBrowser(window);
- // shim addTrack and removeTrack.
- if (window.RTCPeerConnection.prototype.addTrack &&
- browserDetails.version >= 65) {
- return this.shimAddTrackRemoveTrackWithNative(window);
- }
-
- // also shim pc.getLocalStreams when addTrack is shimmed
- // to return the original streams.
- var origGetLocalStreams = window.RTCPeerConnection.prototype
- .getLocalStreams;
- window.RTCPeerConnection.prototype.getLocalStreams = function() {
- var pc = this;
- var nativeStreams = origGetLocalStreams.apply(this);
- pc._reverseStreams = pc._reverseStreams || {};
- return nativeStreams.map(function(stream) {
- return pc._reverseStreams[stream.id];
- });
- };
-
- var origAddStream = window.RTCPeerConnection.prototype.addStream;
- window.RTCPeerConnection.prototype.addStream = function(stream) {
- var pc = this;
- pc._streams = pc._streams || {};
- pc._reverseStreams = pc._reverseStreams || {};
-
- stream.getTracks().forEach(function(track) {
- var alreadyExists = pc.getSenders().find(function(s) {
- return s.track === track;
- });
- if (alreadyExists) {
- throw new DOMException('Track already exists.',
- 'InvalidAccessError');
- }
- });
- // Add identity mapping for consistency with addTrack.
- // Unless this is being used with a stream from addTrack.
- if (!pc._reverseStreams[stream.id]) {
- var newStream = new window.MediaStream(stream.getTracks());
- pc._streams[stream.id] = newStream;
- pc._reverseStreams[newStream.id] = stream;
- stream = newStream;
- }
- origAddStream.apply(pc, [stream]);
- };
-
- var origRemoveStream = window.RTCPeerConnection.prototype.removeStream;
- window.RTCPeerConnection.prototype.removeStream = function(stream) {
- var pc = this;
- pc._streams = pc._streams || {};
- pc._reverseStreams = pc._reverseStreams || {};
-
- origRemoveStream.apply(pc, [(pc._streams[stream.id] || stream)]);
- delete pc._reverseStreams[(pc._streams[stream.id] ?
- pc._streams[stream.id].id : stream.id)];
- delete pc._streams[stream.id];
- };
-
- window.RTCPeerConnection.prototype.addTrack = function(track, stream) {
- var pc = this;
- if (pc.signalingState === 'closed') {
- throw new DOMException(
- 'The RTCPeerConnection\'s signalingState is \'closed\'.',
- 'InvalidStateError');
- }
- var streams = [].slice.call(arguments, 1);
- if (streams.length !== 1 ||
- !streams[0].getTracks().find(function(t) {
- return t === track;
- })) {
- // this is not fully correct but all we can manage without
- // [[associated MediaStreams]] internal slot.
- throw new DOMException(
- 'The adapter.js addTrack polyfill only supports a single ' +
- ' stream which is associated with the specified track.',
- 'NotSupportedError');
- }
-
- var alreadyExists = pc.getSenders().find(function(s) {
- return s.track === track;
- });
- if (alreadyExists) {
- throw new DOMException('Track already exists.',
- 'InvalidAccessError');
- }
-
- pc._streams = pc._streams || {};
- pc._reverseStreams = pc._reverseStreams || {};
- var oldStream = pc._streams[stream.id];
- if (oldStream) {
- // this is using odd Chrome behaviour, use with caution:
- // https://bugs.chromium.org/p/webrtc/issues/detail?id=7815
- // Note: we rely on the high-level addTrack/dtmf shim to
- // create the sender with a dtmf sender.
- oldStream.addTrack(track);
-
- // Trigger ONN async.
- Promise.resolve().then(function() {
- pc.dispatchEvent(new Event('negotiationneeded'));
- });
- } else {
- var newStream = new window.MediaStream([track]);
- pc._streams[stream.id] = newStream;
- pc._reverseStreams[newStream.id] = stream;
- pc.addStream(newStream);
- }
- return pc.getSenders().find(function(s) {
- return s.track === track;
- });
- };
-
- // replace the internal stream id with the external one and
- // vice versa.
- function replaceInternalStreamId(pc, description) {
- var sdp = description.sdp;
- Object.keys(pc._reverseStreams || []).forEach(function(internalId) {
- var externalStream = pc._reverseStreams[internalId];
- var internalStream = pc._streams[externalStream.id];
- sdp = sdp.replace(new RegExp(internalStream.id, 'g'),
- externalStream.id);
- });
- return new RTCSessionDescription({
- type: description.type,
- sdp: sdp
- });
- }
- function replaceExternalStreamId(pc, description) {
- var sdp = description.sdp;
- Object.keys(pc._reverseStreams || []).forEach(function(internalId) {
- var externalStream = pc._reverseStreams[internalId];
- var internalStream = pc._streams[externalStream.id];
- sdp = sdp.replace(new RegExp(externalStream.id, 'g'),
- internalStream.id);
- });
- return new RTCSessionDescription({
- type: description.type,
- sdp: sdp
- });
- }
- ['createOffer', 'createAnswer'].forEach(function(method) {
- var nativeMethod = window.RTCPeerConnection.prototype[method];
- window.RTCPeerConnection.prototype[method] = function() {
- var pc = this;
- var args = arguments;
- var isLegacyCall = arguments.length &&
- typeof arguments[0] === 'function';
- if (isLegacyCall) {
- return nativeMethod.apply(pc, [
- function(description) {
- var desc = replaceInternalStreamId(pc, description);
- args[0].apply(null, [desc]);
- },
- function(err) {
- if (args[1]) {
- args[1].apply(null, err);
- }
- }, arguments[2]
- ]);
- }
- return nativeMethod.apply(pc, arguments)
- .then(function(description) {
- return replaceInternalStreamId(pc, description);
- });
- };
- });
-
- var origSetLocalDescription =
- window.RTCPeerConnection.prototype.setLocalDescription;
- window.RTCPeerConnection.prototype.setLocalDescription = function() {
- var pc = this;
- if (!arguments.length || !arguments[0].type) {
- return origSetLocalDescription.apply(pc, arguments);
- }
- arguments[0] = replaceExternalStreamId(pc, arguments[0]);
- return origSetLocalDescription.apply(pc, arguments);
- };
-
- // TODO: mangle getStats: https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamstats-streamidentifier
-
- var origLocalDescription = Object.getOwnPropertyDescriptor(
- window.RTCPeerConnection.prototype, 'localDescription');
- Object.defineProperty(window.RTCPeerConnection.prototype,
- 'localDescription', {
- get: function() {
- var pc = this;
- var description = origLocalDescription.get.apply(this);
- if (description.type === '') {
- return description;
- }
- return replaceInternalStreamId(pc, description);
- }
- });
-
- window.RTCPeerConnection.prototype.removeTrack = function(sender) {
- var pc = this;
- if (pc.signalingState === 'closed') {
- throw new DOMException(
- 'The RTCPeerConnection\'s signalingState is \'closed\'.',
- 'InvalidStateError');
- }
- // We can not yet check for sender instanceof RTCRtpSender
- // since we shim RTPSender. So we check if sender._pc is set.
- if (!sender._pc) {
- throw new DOMException('Argument 1 of RTCPeerConnection.removeTrack ' +
- 'does not implement interface RTCRtpSender.', 'TypeError');
- }
- var isLocal = sender._pc === pc;
- if (!isLocal) {
- throw new DOMException('Sender was not created by this connection.',
- 'InvalidAccessError');
- }
-
- // Search for the native stream the senders track belongs to.
- pc._streams = pc._streams || {};
- var stream;
- Object.keys(pc._streams).forEach(function(streamid) {
- var hasTrack = pc._streams[streamid].getTracks().find(function(track) {
- return sender.track === track;
- });
- if (hasTrack) {
- stream = pc._streams[streamid];
- }
- });
-
- if (stream) {
- if (stream.getTracks().length === 1) {
- // if this is the last track of the stream, remove the stream. This
- // takes care of any shimmed _senders.
- pc.removeStream(pc._reverseStreams[stream.id]);
- } else {
- // relying on the same odd chrome behaviour as above.
- stream.removeTrack(sender.track);
- }
- pc.dispatchEvent(new Event('negotiationneeded'));
- }
- };
- },
-
- shimPeerConnection: function(window) {
- var browserDetails = utils.detectBrowser(window);
-
- // The RTCPeerConnection object.
- if (!window.RTCPeerConnection && window.webkitRTCPeerConnection) {
- window.RTCPeerConnection = function(pcConfig, pcConstraints) {
- // Translate iceTransportPolicy to iceTransports,
- // see https://code.google.com/p/webrtc/issues/detail?id=4869
- // this was fixed in M56 along with unprefixing RTCPeerConnection.
- logging('PeerConnection');
- if (pcConfig && pcConfig.iceTransportPolicy) {
- pcConfig.iceTransports = pcConfig.iceTransportPolicy;
- }
-
- return new window.webkitRTCPeerConnection(pcConfig, pcConstraints);
- };
- window.RTCPeerConnection.prototype =
- window.webkitRTCPeerConnection.prototype;
- // wrap static methods. Currently just generateCertificate.
- if (window.webkitRTCPeerConnection.generateCertificate) {
- Object.defineProperty(window.RTCPeerConnection, 'generateCertificate', {
- get: function() {
- return window.webkitRTCPeerConnection.generateCertificate;
- }
- });
- }
- } else {
- // migrate from non-spec RTCIceServer.url to RTCIceServer.urls
- var OrigPeerConnection = window.RTCPeerConnection;
- window.RTCPeerConnection = function(pcConfig, pcConstraints) {
- if (pcConfig && pcConfig.iceServers) {
- var newIceServers = [];
- for (var i = 0; i < pcConfig.iceServers.length; i++) {
- var server = pcConfig.iceServers[i];
- if (!server.hasOwnProperty('urls') &&
- server.hasOwnProperty('url')) {
- utils.deprecated('RTCIceServer.url', 'RTCIceServer.urls');
- server = JSON.parse(JSON.stringify(server));
- server.urls = server.url;
- newIceServers.push(server);
- } else {
- newIceServers.push(pcConfig.iceServers[i]);
- }
- }
- pcConfig.iceServers = newIceServers;
- }
- return new OrigPeerConnection(pcConfig, pcConstraints);
- };
- window.RTCPeerConnection.prototype = OrigPeerConnection.prototype;
- // wrap static methods. Currently just generateCertificate.
- Object.defineProperty(window.RTCPeerConnection, 'generateCertificate', {
- get: function() {
- return OrigPeerConnection.generateCertificate;
- }
- });
- }
-
- var origGetStats = window.RTCPeerConnection.prototype.getStats;
- window.RTCPeerConnection.prototype.getStats = function(selector,
- successCallback, errorCallback) {
- var pc = 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.apply(this, arguments);
- }
-
- // When spec-style getStats is supported, return those when called with
- // either no arguments or the selector argument is null.
- if (origGetStats.length === 0 && (arguments.length === 0 ||
- typeof arguments[0] !== 'function')) {
- return origGetStats.apply(this, []);
- }
-
- var fixChromeStats_ = function(response) {
- var standardReport = {};
- var reports = response.result();
- reports.forEach(function(report) {
- var standardStats = {
- id: report.id,
- timestamp: report.timestamp,
- type: {
- localcandidate: 'local-candidate',
- remotecandidate: 'remote-candidate'
- }[report.type] || report.type
- };
- report.names().forEach(function(name) {
- standardStats[name] = report.stat(name);
- });
- standardReport[standardStats.id] = standardStats;
- });
-
- return standardReport;
- };
-
- // shim getStats with maplike support
- var makeMapStats = function(stats) {
- return new Map(Object.keys(stats).map(function(key) {
- return [key, stats[key]];
- }));
- };
-
- if (arguments.length >= 2) {
- var successCallbackWrapper_ = function(response) {
- args[1](makeMapStats(fixChromeStats_(response)));
- };
-
- return origGetStats.apply(this, [successCallbackWrapper_,
- arguments[0]]);
- }
-
- // promise-support
- return new Promise(function(resolve, reject) {
- origGetStats.apply(pc, [
- function(response) {
- resolve(makeMapStats(fixChromeStats_(response)));
- }, reject]);
- }).then(successCallback, errorCallback);
- };
-
- // add promise support -- natively available in Chrome 51
- if (browserDetails.version < 51) {
- ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate']
- .forEach(function(method) {
- var nativeMethod = window.RTCPeerConnection.prototype[method];
- window.RTCPeerConnection.prototype[method] = function() {
- var args = arguments;
- var pc = this;
- var promise = new Promise(function(resolve, reject) {
- nativeMethod.apply(pc, [args[0], resolve, reject]);
- });
- if (args.length < 2) {
- return promise;
- }
- return promise.then(function() {
- args[1].apply(null, []);
- },
- function(err) {
- if (args.length >= 3) {
- args[2].apply(null, [err]);
- }
- });
- };
- });
- }
-
- // promise support for createOffer and createAnswer. Available (without
- // bugs) since M52: crbug/619289
- if (browserDetails.version < 52) {
- ['createOffer', 'createAnswer'].forEach(function(method) {
- var nativeMethod = window.RTCPeerConnection.prototype[method];
- window.RTCPeerConnection.prototype[method] = function() {
- var pc = 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(pc, [resolve, reject, opts]);
- });
- }
- return nativeMethod.apply(this, arguments);
- };
- });
- }
-
- // shim implicit creation of RTCSessionDescription/RTCIceCandidate
- ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate']
- .forEach(function(method) {
- var nativeMethod = window.RTCPeerConnection.prototype[method];
- window.RTCPeerConnection.prototype[method] = function() {
- arguments[0] = new ((method === 'addIceCandidate') ?
- window.RTCIceCandidate :
- window.RTCSessionDescription)(arguments[0]);
- return nativeMethod.apply(this, arguments);
- };
- });
-
- // support for addIceCandidate(null or undefined)
- var nativeAddIceCandidate =
- window.RTCPeerConnection.prototype.addIceCandidate;
- window.RTCPeerConnection.prototype.addIceCandidate = function() {
- if (!arguments[0]) {
- if (arguments[1]) {
- arguments[1].apply(null);
- }
- return Promise.resolve();
- }
- return nativeAddIceCandidate.apply(this, arguments);
- };
- }
-};
-
-},{"../utils.js":13,"./getusermedia":6}],6:[function(require,module,exports){
-/*
- * Copyright (c) 2016 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.
- */
- /* eslint-env node */
-'use strict';
-var utils = require('../utils.js');
-var logging = utils.log;
-
-// Expose public methods.
-module.exports = function(window) {
- var browserDetails = utils.detectBrowser(window);
- var navigator = window && window.navigator;
-
- 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;
- };
-
- var shimConstraints_ = function(constraints, func) {
- if (browserDetails.version >= 61) {
- return func(constraints);
- }
- constraints = JSON.parse(JSON.stringify(constraints));
- if (constraints && typeof constraints.audio === 'object') {
- var remap = function(obj, a, b) {
- if (a in obj && !(b in obj)) {
- obj[b] = obj[a];
- delete obj[a];
- }
- };
- constraints = JSON.parse(JSON.stringify(constraints));
- remap(constraints.audio, 'autoGainControl', 'googAutoGainControl');
- remap(constraints.audio, 'noiseSuppression', 'googNoiseSuppression');
- constraints.audio = constraintsToChrome_(constraints.audio);
- }
- if (constraints && typeof constraints.video === 'object') {
- // Shim facingMode for mobile & surface pro.
- var face = constraints.video.facingMode;
- face = face && ((typeof face === 'object') ? face : {ideal: face});
- var getSupportedFacingModeLies = browserDetails.version < 66;
-
- if ((face && (face.exact === 'user' || face.exact === 'environment' ||
- face.ideal === 'user' || face.ideal === 'environment')) &&
- !(navigator.mediaDevices.getSupportedConstraints &&
- navigator.mediaDevices.getSupportedConstraints().facingMode &&
- !getSupportedFacingModeLies)) {
- delete constraints.video.facingMode;
- var matches;
- if (face.exact === 'environment' || face.ideal === 'environment') {
- matches = ['back', 'rear'];
- } else if (face.exact === 'user' || face.ideal === 'user') {
- matches = ['front'];
- }
- if (matches) {
- // Look for matches in label, or use last cam for back (typical).
- return navigator.mediaDevices.enumerateDevices()
- .then(function(devices) {
- devices = devices.filter(function(d) {
- return d.kind === 'videoinput';
- });
- var dev = devices.find(function(d) {
- return matches.some(function(match) {
- return d.label.toLowerCase().indexOf(match) !== -1;
- });
- });
- if (!dev && devices.length && matches.indexOf('back') !== -1) {
- dev = devices[devices.length - 1]; // more likely the back cam
- }
- if (dev) {
- constraints.video.deviceId = face.exact ? {exact: dev.deviceId} :
- {ideal: dev.deviceId};
- }
- constraints.video = constraintsToChrome_(constraints.video);
- logging('chrome: ' + JSON.stringify(constraints));
- return func(constraints);
- });
- }
- }
- constraints.video = constraintsToChrome_(constraints.video);
- }
- logging('chrome: ' + JSON.stringify(constraints));
- return func(constraints);
- };
-
- var shimError_ = function(e) {
- return {
- name: {
- PermissionDeniedError: 'NotAllowedError',
- InvalidStateError: 'NotReadableError',
- DevicesNotFoundError: 'NotFoundError',
- ConstraintNotSatisfiedError: 'OverconstrainedError',
- TrackStartError: 'NotReadableError',
- MediaDeviceFailedDueToShutdown: 'NotReadableError',
- MediaDeviceKillSwitchOn: 'NotReadableError'
- }[e.name] || e.name,
- message: e.message,
- constraint: e.constraintName,
- toString: function() {
- return this.name + (this.message && ': ') + this.message;
- }
- };
- };
-
- var getUserMedia_ = function(constraints, onSuccess, onError) {
- shimConstraints_(constraints, function(c) {
- navigator.webkitGetUserMedia(c, onSuccess, function(e) {
- if (onError) {
- onError(shimError_(e));
- }
- });
- });
- };
-
- navigator.getUserMedia = getUserMedia_;
-
- // Returns the result of getUserMedia as a Promise.
- var getUserMediaPromise_ = function(constraints) {
- return new Promise(function(resolve, reject) {
- navigator.getUserMedia(constraints, resolve, reject);
- });
- };
-
- if (!navigator.mediaDevices) {
- navigator.mediaDevices = {
- getUserMedia: getUserMediaPromise_,
- enumerateDevices: function() {
- return new Promise(function(resolve) {
- var kinds = {audio: 'audioinput', video: 'videoinput'};
- return window.MediaStreamTrack.getSources(function(devices) {
- resolve(devices.map(function(device) {
- return {label: device.label,
- kind: kinds[device.kind],
- deviceId: device.id,
- groupId: ''};
- }));
- });
- });
- },
- getSupportedConstraints: function() {
- return {
- deviceId: true, echoCancellation: true, facingMode: true,
- frameRate: true, height: true, width: true
- };
- }
- };
- }
-
- // 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 getUserMediaPromise_(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(cs) {
- return shimConstraints_(cs, function(c) {
- return origGetUserMedia(c).then(function(stream) {
- if (c.audio && !stream.getAudioTracks().length ||
- c.video && !stream.getVideoTracks().length) {
- stream.getTracks().forEach(function(track) {
- track.stop();
- });
- throw new DOMException('', 'NotFoundError');
- }
- return stream;
- }, function(e) {
- return Promise.reject(shimError_(e));
- });
- });
- };
- }
-
- // Dummy devicechange event methods.
- // TODO(KaptenJansson) remove once implemented in Chrome stable.
- if (typeof navigator.mediaDevices.addEventListener === 'undefined') {
- navigator.mediaDevices.addEventListener = function() {
- logging('Dummy mediaDevices.addEventListener called.');
- };
- }
- if (typeof navigator.mediaDevices.removeEventListener === 'undefined') {
- navigator.mediaDevices.removeEventListener = function() {
- logging('Dummy mediaDevices.removeEventListener called.');
- };
- }
-};
-
-},{"../utils.js":13}],7:[function(require,module,exports){
-/*
- * Copyright (c) 2017 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.
- */
- /* eslint-env node */
-'use strict';
-
-var SDPUtils = require('sdp');
-var utils = require('./utils');
-
-module.exports = {
- shimRTCIceCandidate: function(window) {
- // foundation is arbitrarily chosen as an indicator for full support for
- // https://w3c.github.io/webrtc-pc/#rtcicecandidate-interface
- if (window.RTCIceCandidate && 'foundation' in
- window.RTCIceCandidate.prototype) {
- return;
- }
-
- var NativeRTCIceCandidate = window.RTCIceCandidate;
- window.RTCIceCandidate = function(args) {
- // Remove the a= which shouldn't be part of the candidate string.
- if (typeof args === 'object' && args.candidate &&
- args.candidate.indexOf('a=') === 0) {
- args = JSON.parse(JSON.stringify(args));
- args.candidate = args.candidate.substr(2);
- }
-
- // Augment the native candidate with the parsed fields.
- var nativeCandidate = new NativeRTCIceCandidate(args);
- var parsedCandidate = SDPUtils.parseCandidate(args.candidate);
- var augmentedCandidate = Object.assign(nativeCandidate,
- parsedCandidate);
-
- // Add a serializer that does not serialize the extra attributes.
- augmentedCandidate.toJSON = function() {
- return {
- candidate: augmentedCandidate.candidate,
- sdpMid: augmentedCandidate.sdpMid,
- sdpMLineIndex: augmentedCandidate.sdpMLineIndex,
- usernameFragment: augmentedCandidate.usernameFragment,
- };
- };
- return augmentedCandidate;
- };
-
- // Hook up the augmented candidate in onicecandidate and
- // addEventListener('icecandidate', ...)
- utils.wrapPeerConnectionEvent(window, 'icecandidate', function(e) {
- if (e.candidate) {
- Object.defineProperty(e, 'candidate', {
- value: new window.RTCIceCandidate(e.candidate),
- writable: 'false'
- });
- }
- return e;
- });
- },
-
- // shimCreateObjectURL must be called before shimSourceObject to avoid loop.
-
- shimCreateObjectURL: function(window) {
- var URL = window && window.URL;
-
- if (!(typeof window === 'object' && window.HTMLMediaElement &&
- 'srcObject' in window.HTMLMediaElement.prototype &&
- URL.createObjectURL && URL.revokeObjectURL)) {
- // Only shim CreateObjectURL using srcObject if srcObject exists.
- return undefined;
- }
-
- var nativeCreateObjectURL = URL.createObjectURL.bind(URL);
- var nativeRevokeObjectURL = URL.revokeObjectURL.bind(URL);
- var streams = new Map(), newId = 0;
-
- URL.createObjectURL = function(stream) {
- if ('getTracks' in stream) {
- var url = 'polyblob:' + (++newId);
- streams.set(url, stream);
- utils.deprecated('URL.createObjectURL(stream)',
- 'elem.srcObject = stream');
- return url;
- }
- return nativeCreateObjectURL(stream);
- };
- URL.revokeObjectURL = function(url) {
- nativeRevokeObjectURL(url);
- streams.delete(url);
- };
-
- var dsc = Object.getOwnPropertyDescriptor(window.HTMLMediaElement.prototype,
- 'src');
- Object.defineProperty(window.HTMLMediaElement.prototype, 'src', {
- get: function() {
- return dsc.get.apply(this);
- },
- set: function(url) {
- this.srcObject = streams.get(url) || null;
- return dsc.set.apply(this, [url]);
- }
- });
-
- var nativeSetAttribute = window.HTMLMediaElement.prototype.setAttribute;
- window.HTMLMediaElement.prototype.setAttribute = function() {
- if (arguments.length === 2 &&
- ('' + arguments[0]).toLowerCase() === 'src') {
- this.srcObject = streams.get(arguments[1]) || null;
- }
- return nativeSetAttribute.apply(this, arguments);
- };
- },
-
- shimMaxMessageSize: function(window) {
- if (window.RTCSctpTransport || !window.RTCPeerConnection) {
- return;
- }
- var browserDetails = utils.detectBrowser(window);
-
- if (!('sctp' in window.RTCPeerConnection.prototype)) {
- Object.defineProperty(window.RTCPeerConnection.prototype, 'sctp', {
- get: function() {
- return typeof this._sctp === 'undefined' ? null : this._sctp;
- }
- });
- }
-
- var sctpInDescription = function(description) {
- var sections = SDPUtils.splitSections(description.sdp);
- sections.shift();
- return sections.some(function(mediaSection) {
- var mLine = SDPUtils.parseMLine(mediaSection);
- return mLine && mLine.kind === 'application'
- && mLine.protocol.indexOf('SCTP') !== -1;
- });
- };
-
- var getRemoteFirefoxVersion = function(description) {
- // TODO: Is there a better solution for detecting Firefox?
- var match = description.sdp.match(/mozilla...THIS_IS_SDPARTA-(\d+)/);
- if (match === null || match.length < 2) {
- return -1;
- }
- var version = parseInt(match[1], 10);
- // Test for NaN (yes, this is ugly)
- return version !== version ? -1 : version;
- };
-
- var getCanSendMaxMessageSize = function(remoteIsFirefox) {
- // Every implementation we know can send at least 64 KiB.
- // Note: Although Chrome is technically able to send up to 256 KiB, the
- // data does not reach the other peer reliably.
- // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=8419
- var canSendMaxMessageSize = 65536;
- if (browserDetails.browser === 'firefox') {
- if (browserDetails.version < 57) {
- if (remoteIsFirefox === -1) {
- // FF < 57 will send in 16 KiB chunks using the deprecated PPID
- // fragmentation.
- canSendMaxMessageSize = 16384;
- } else {
- // However, other FF (and RAWRTC) can reassemble PPID-fragmented
- // messages. Thus, supporting ~2 GiB when sending.
- canSendMaxMessageSize = 2147483637;
- }
- } else {
- // Currently, all FF >= 57 will reset the remote maximum message size
- // to the default value when a data channel is created at a later
- // stage. :(
- // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1426831
- canSendMaxMessageSize =
- browserDetails.version === 57 ? 65535 : 65536;
- }
- }
- return canSendMaxMessageSize;
- };
-
- var getMaxMessageSize = function(description, remoteIsFirefox) {
- // Note: 65536 bytes is the default value from the SDP spec. Also,
- // every implementation we know supports receiving 65536 bytes.
- var maxMessageSize = 65536;
-
- // FF 57 has a slightly incorrect default remote max message size, so
- // we need to adjust it here to avoid a failure when sending.
- // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1425697
- if (browserDetails.browser === 'firefox'
- && browserDetails.version === 57) {
- maxMessageSize = 65535;
- }
-
- var match = SDPUtils.matchPrefix(description.sdp, 'a=max-message-size:');
- if (match.length > 0) {
- maxMessageSize = parseInt(match[0].substr(19), 10);
- } else if (browserDetails.browser === 'firefox' &&
- remoteIsFirefox !== -1) {
- // If the maximum message size is not present in the remote SDP and
- // both local and remote are Firefox, the remote peer can receive
- // ~2 GiB.
- maxMessageSize = 2147483637;
- }
- return maxMessageSize;
- };
-
- var origSetRemoteDescription =
- window.RTCPeerConnection.prototype.setRemoteDescription;
- window.RTCPeerConnection.prototype.setRemoteDescription = function() {
- var pc = this;
- pc._sctp = null;
-
- if (sctpInDescription(arguments[0])) {
- // Check if the remote is FF.
- var isFirefox = getRemoteFirefoxVersion(arguments[0]);
-
- // Get the maximum message size the local peer is capable of sending
- var canSendMMS = getCanSendMaxMessageSize(isFirefox);
-
- // Get the maximum message size of the remote peer.
- var remoteMMS = getMaxMessageSize(arguments[0], isFirefox);
-
- // Determine final maximum message size
- var maxMessageSize;
- if (canSendMMS === 0 && remoteMMS === 0) {
- maxMessageSize = Number.POSITIVE_INFINITY;
- } else if (canSendMMS === 0 || remoteMMS === 0) {
- maxMessageSize = Math.max(canSendMMS, remoteMMS);
- } else {
- maxMessageSize = Math.min(canSendMMS, remoteMMS);
- }
-
- // Create a dummy RTCSctpTransport object and the 'maxMessageSize'
- // attribute.
- var sctp = {};
- Object.defineProperty(sctp, 'maxMessageSize', {
- get: function() {
- return maxMessageSize;
- }
- });
- pc._sctp = sctp;
- }
-
- return origSetRemoteDescription.apply(pc, arguments);
- };
- },
-
- shimSendThrowTypeError: function(window) {
- // Note: Although Firefox >= 57 has a native implementation, the maximum
- // message size can be reset for all data channels at a later stage.
- // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1426831
-
- var origCreateDataChannel =
- window.RTCPeerConnection.prototype.createDataChannel;
- window.RTCPeerConnection.prototype.createDataChannel = function() {
- var pc = this;
- var dataChannel = origCreateDataChannel.apply(pc, arguments);
- var origDataChannelSend = dataChannel.send;
-
- // Patch 'send' method
- dataChannel.send = function() {
- var dc = this;
- var data = arguments[0];
- var length = data.length || data.size || data.byteLength;
- if (length > pc.sctp.maxMessageSize) {
- throw new DOMException('Message too large (can send a maximum of ' +
- pc.sctp.maxMessageSize + ' bytes)', 'TypeError');
- }
- return origDataChannelSend.apply(dc, arguments);
- };
-
- return dataChannel;
- };
- }
-};
-
-},{"./utils":13,"sdp":2}],8:[function(require,module,exports){
-/*
- * Copyright (c) 2016 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.
- */
- /* eslint-env node */
-'use strict';
-
-var utils = require('../utils');
-var shimRTCPeerConnection = require('rtcpeerconnection-shim');
-
-module.exports = {
- shimGetUserMedia: require('./getusermedia'),
- shimPeerConnection: function(window) {
- var browserDetails = utils.detectBrowser(window);
-
- if (window.RTCIceGatherer) {
- // ORTC defines an RTCIceCandidate object but no constructor.
- // Not implemented in Edge.
- if (!window.RTCIceCandidate) {
- window.RTCIceCandidate = function(args) {
- return args;
- };
- }
- // ORTC does not have a session description object but
- // other browsers (i.e. Chrome) that will support both PC and ORTC
- // in the future might have this defined already.
- if (!window.RTCSessionDescription) {
- window.RTCSessionDescription = function(args) {
- return args;
- };
- }
- // this adds an additional event listener to MediaStrackTrack that signals
- // when a tracks enabled property was changed. Workaround for a bug in
- // addStream, see below. No longer required in 15025+
- if (browserDetails.version < 15025) {
- var origMSTEnabled = Object.getOwnPropertyDescriptor(
- window.MediaStreamTrack.prototype, 'enabled');
- Object.defineProperty(window.MediaStreamTrack.prototype, 'enabled', {
- set: function(value) {
- origMSTEnabled.set.call(this, value);
- var ev = new Event('enabled');
- ev.enabled = value;
- this.dispatchEvent(ev);
- }
- });
- }
- }
-
- // ORTC defines the DTMF sender a bit different.
- // https://github.com/w3c/ortc/issues/714
- if (window.RTCRtpSender && !('dtmf' in window.RTCRtpSender.prototype)) {
- Object.defineProperty(window.RTCRtpSender.prototype, 'dtmf', {
- get: function() {
- if (this._dtmf === undefined) {
- if (this.track.kind === 'audio') {
- this._dtmf = new window.RTCDtmfSender(this);
- } else if (this.track.kind === 'video') {
- this._dtmf = null;
- }
- }
- return this._dtmf;
- }
- });
- }
-
- window.RTCPeerConnection =
- shimRTCPeerConnection(window, browserDetails.version);
- },
- shimReplaceTrack: function(window) {
- // ORTC has replaceTrack -- https://github.com/w3c/ortc/issues/614
- if (window.RTCRtpSender &&
- !('replaceTrack' in window.RTCRtpSender.prototype)) {
- window.RTCRtpSender.prototype.replaceTrack =
- window.RTCRtpSender.prototype.setTrack;
- }
- }
-};
-
-},{"../utils":13,"./getusermedia":9,"rtcpeerconnection-shim":1}],9:[function(require,module,exports){
-/*
- * Copyright (c) 2016 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.
- */
- /* eslint-env node */
-'use strict';
-
-// Expose public methods.
-module.exports = function(window) {
- var navigator = window && window.navigator;
-
- var shimError_ = function(e) {
- return {
- name: {PermissionDeniedError: 'NotAllowedError'}[e.name] || e.name,
- message: e.message,
- constraint: e.constraint,
- toString: function() {
- return this.name;
- }
- };
- };
-
- // getUserMedia error shim.
- var origGetUserMedia = navigator.mediaDevices.getUserMedia.
- bind(navigator.mediaDevices);
- navigator.mediaDevices.getUserMedia = function(c) {
- return origGetUserMedia(c).catch(function(e) {
- return Promise.reject(shimError_(e));
- });
- };
-};
-
-},{}],10:[function(require,module,exports){
-/*
- * Copyright (c) 2016 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.
- */
- /* eslint-env node */
-'use strict';
-
-var utils = require('../utils');
-
-module.exports = {
- shimGetUserMedia: require('./getusermedia'),
- shimOnTrack: function(window) {
- if (typeof window === 'object' && window.RTCPeerConnection && !('ontrack' in
- window.RTCPeerConnection.prototype)) {
- Object.defineProperty(window.RTCPeerConnection.prototype, 'ontrack', {
- get: function() {
- return this._ontrack;
- },
- set: function(f) {
- if (this._ontrack) {
- this.removeEventListener('track', this._ontrack);
- this.removeEventListener('addstream', this._ontrackpoly);
- }
- this.addEventListener('track', this._ontrack = f);
- this.addEventListener('addstream', this._ontrackpoly = function(e) {
- e.stream.getTracks().forEach(function(track) {
- var event = new Event('track');
- event.track = track;
- event.receiver = {track: track};
- event.transceiver = {receiver: event.receiver};
- event.streams = [e.stream];
- this.dispatchEvent(event);
- }.bind(this));
- }.bind(this));
- }
- });
- }
- if (typeof window === 'object' && window.RTCTrackEvent &&
- ('receiver' in window.RTCTrackEvent.prototype) &&
- !('transceiver' in window.RTCTrackEvent.prototype)) {
- Object.defineProperty(window.RTCTrackEvent.prototype, 'transceiver', {
- get: function() {
- return {receiver: this.receiver};
- }
- });
- }
- },
-
- shimSourceObject: function(window) {
- // Firefox has supported mozSrcObject since FF22, unprefixed in 42.
- 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() {
- return this.mozSrcObject;
- },
- set: function(stream) {
- this.mozSrcObject = stream;
- }
- });
- }
- }
- },
-
- shimPeerConnection: function(window) {
- var browserDetails = utils.detectBrowser(window);
-
- if (typeof window !== 'object' || !(window.RTCPeerConnection ||
- window.mozRTCPeerConnection)) {
- return; // probably media.peerconnection.enabled=false in about:config
- }
- // The RTCPeerConnection object.
- if (!window.RTCPeerConnection) {
- window.RTCPeerConnection = function(pcConfig, pcConstraints) {
- if (browserDetails.version < 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 window.mozRTCPeerConnection(pcConfig, pcConstraints);
- };
- window.RTCPeerConnection.prototype =
- window.mozRTCPeerConnection.prototype;
-
- // wrap static methods. Currently just generateCertificate.
- if (window.mozRTCPeerConnection.generateCertificate) {
- Object.defineProperty(window.RTCPeerConnection, 'generateCertificate', {
- get: function() {
- return window.mozRTCPeerConnection.generateCertificate;
- }
- });
- }
-
- window.RTCSessionDescription = window.mozRTCSessionDescription;
- window.RTCIceCandidate = window.mozRTCIceCandidate;
- }
-
- // shim away need for obsolete RTCIceCandidate/RTCSessionDescription.
- ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate']
- .forEach(function(method) {
- var nativeMethod = window.RTCPeerConnection.prototype[method];
- window.RTCPeerConnection.prototype[method] = function() {
- arguments[0] = new ((method === 'addIceCandidate') ?
- window.RTCIceCandidate :
- window.RTCSessionDescription)(arguments[0]);
- return nativeMethod.apply(this, arguments);
- };
- });
-
- // support for addIceCandidate(null or undefined)
- var nativeAddIceCandidate =
- window.RTCPeerConnection.prototype.addIceCandidate;
- window.RTCPeerConnection.prototype.addIceCandidate = function() {
- if (!arguments[0]) {
- if (arguments[1]) {
- arguments[1].apply(null);
- }
- return Promise.resolve();
- }
- return nativeAddIceCandidate.apply(this, arguments);
- };
-
- // shim getStats with maplike support
- var makeMapStats = function(stats) {
- var map = new Map();
- Object.keys(stats).forEach(function(key) {
- map.set(key, stats[key]);
- map[key] = stats[key];
- });
- return map;
- };
-
- var modernStatsTypes = {
- inboundrtp: 'inbound-rtp',
- outboundrtp: 'outbound-rtp',
- candidatepair: 'candidate-pair',
- localcandidate: 'local-candidate',
- remotecandidate: 'remote-candidate'
- };
-
- var nativeGetStats = window.RTCPeerConnection.prototype.getStats;
- window.RTCPeerConnection.prototype.getStats = function(
- selector,
- onSucc,
- onErr
- ) {
- return nativeGetStats.apply(this, [selector || null])
- .then(function(stats) {
- if (browserDetails.version < 48) {
- stats = makeMapStats(stats);
- }
- if (browserDetails.version < 53 && !onSucc) {
- // Shim only promise getStats with spec-hyphens in type names
- // Leave callback version alone; misc old uses of forEach before Map
- try {
- stats.forEach(function(stat) {
- stat.type = modernStatsTypes[stat.type] || stat.type;
- });
- } catch (e) {
- if (e.name !== 'TypeError') {
- throw e;
- }
- // Avoid TypeError: "type" is read-only, in old versions. 34-43ish
- stats.forEach(function(stat, i) {
- stats.set(i, Object.assign({}, stat, {
- type: modernStatsTypes[stat.type] || stat.type
- }));
- });
- }
- }
- return stats;
- })
- .then(onSucc, onErr);
- };
- },
-
- shimRemoveStream: function(window) {
- if (!window.RTCPeerConnection ||
- 'removeStream' in window.RTCPeerConnection.prototype) {
- return;
- }
- window.RTCPeerConnection.prototype.removeStream = function(stream) {
- var pc = this;
- utils.deprecated('removeStream', 'removeTrack');
- this.getSenders().forEach(function(sender) {
- if (sender.track && stream.getTracks().indexOf(sender.track) !== -1) {
- pc.removeTrack(sender);
- }
- });
- };
- }
-};
-
-},{"../utils":13,"./getusermedia":11}],11:[function(require,module,exports){
-/*
- * Copyright (c) 2016 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.
- */
- /* eslint-env node */
-'use strict';
-
-var utils = require('../utils');
-var logging = utils.log;
-
-// Expose public methods.
-module.exports = function(window) {
- var browserDetails = utils.detectBrowser(window);
- var navigator = window && window.navigator;
- var MediaStreamTrack = window && window.MediaStreamTrack;
-
- var shimError_ = function(e) {
- return {
- name: {
- InternalError: 'NotReadableError',
- NotSupportedError: 'TypeError',
- PermissionDeniedError: 'NotAllowedError',
- SecurityError: 'NotAllowedError'
- }[e.name] || e.name,
- message: {
- 'The operation is insecure.': 'The request is not allowed by the ' +
- 'user agent or the platform in the current context.'
- }[e.message] || e.message,
- constraint: e.constraint,
- toString: function() {
- return this.name + (this.message && ': ') + this.message;
- }
- };
- };
-
- // getUserMedia constraints shim.
- var 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;
- };
- constraints = JSON.parse(JSON.stringify(constraints));
- if (browserDetails.version < 38) {
- logging('spec: ' + JSON.stringify(constraints));
- if (constraints.audio) {
- constraints.audio = constraintsToFF37_(constraints.audio);
- }
- if (constraints.video) {
- constraints.video = constraintsToFF37_(constraints.video);
- }
- logging('ff37: ' + JSON.stringify(constraints));
- }
- return navigator.mozGetUserMedia(constraints, onSuccess, function(e) {
- onError(shimError_(e));
- });
- };
-
- // Returns the result of getUserMedia as a Promise.
- var getUserMediaPromise_ = function(constraints) {
- return new Promise(function(resolve, reject) {
- getUserMedia_(constraints, resolve, reject);
- });
- };
-
- // Shim for mediaDevices on older versions.
- if (!navigator.mediaDevices) {
- navigator.mediaDevices = {getUserMedia: getUserMediaPromise_,
- 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 (browserDetails.version < 41) {
- // Work around http://bugzil.la/1169665
- var orgEnumerateDevices =
- navigator.mediaDevices.enumerateDevices.bind(navigator.mediaDevices);
- navigator.mediaDevices.enumerateDevices = function() {
- return orgEnumerateDevices().then(undefined, function(e) {
- if (e.name === 'NotFoundError') {
- return [];
- }
- throw e;
- });
- };
- }
- if (browserDetails.version < 49) {
- var origGetUserMedia = navigator.mediaDevices.getUserMedia.
- bind(navigator.mediaDevices);
- navigator.mediaDevices.getUserMedia = function(c) {
- return origGetUserMedia(c).then(function(stream) {
- // Work around https://bugzil.la/802326
- if (c.audio && !stream.getAudioTracks().length ||
- c.video && !stream.getVideoTracks().length) {
- stream.getTracks().forEach(function(track) {
- track.stop();
- });
- throw new DOMException('The object can not be found here.',
- 'NotFoundError');
- }
- return stream;
- }, function(e) {
- return Promise.reject(shimError_(e));
- });
- };
- }
- if (!(browserDetails.version > 55 &&
- 'autoGainControl' in navigator.mediaDevices.getSupportedConstraints())) {
- var remap = function(obj, a, b) {
- if (a in obj && !(b in obj)) {
- obj[b] = obj[a];
- delete obj[a];
- }
- };
-
- var nativeGetUserMedia = navigator.mediaDevices.getUserMedia.
- bind(navigator.mediaDevices);
- navigator.mediaDevices.getUserMedia = function(c) {
- if (typeof c === 'object' && typeof c.audio === 'object') {
- c = JSON.parse(JSON.stringify(c));
- remap(c.audio, 'autoGainControl', 'mozAutoGainControl');
- remap(c.audio, 'noiseSuppression', 'mozNoiseSuppression');
- }
- return nativeGetUserMedia(c);
- };
-
- if (MediaStreamTrack && MediaStreamTrack.prototype.getSettings) {
- var nativeGetSettings = MediaStreamTrack.prototype.getSettings;
- MediaStreamTrack.prototype.getSettings = function() {
- var obj = nativeGetSettings.apply(this, arguments);
- remap(obj, 'mozAutoGainControl', 'autoGainControl');
- remap(obj, 'mozNoiseSuppression', 'noiseSuppression');
- return obj;
- };
- }
-
- if (MediaStreamTrack && MediaStreamTrack.prototype.applyConstraints) {
- var nativeApplyConstraints = MediaStreamTrack.prototype.applyConstraints;
- MediaStreamTrack.prototype.applyConstraints = function(c) {
- if (this.kind === 'audio' && typeof c === 'object') {
- c = JSON.parse(JSON.stringify(c));
- remap(c, 'autoGainControl', 'mozAutoGainControl');
- remap(c, 'noiseSuppression', 'mozNoiseSuppression');
- }
- return nativeApplyConstraints.apply(this, [c]);
- };
- }
- }
- navigator.getUserMedia = function(constraints, onSuccess, onError) {
- if (browserDetails.version < 44) {
- return getUserMedia_(constraints, onSuccess, onError);
- }
- // Replace Firefox 44+'s deprecation warning with unprefixed version.
- utils.deprecated('navigator.getUserMedia',
- 'navigator.mediaDevices.getUserMedia');
- navigator.mediaDevices.getUserMedia(constraints).then(onSuccess, onError);
- };
-};
-
-},{"../utils":13}],12:[function(require,module,exports){
-/*
- * Copyright (c) 2016 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.
- */
-'use strict';
-var utils = require('../utils');
-
-module.exports = {
- shimLocalStreamsAPI: function(window) {
- if (typeof window !== 'object' || !window.RTCPeerConnection) {
- return;
- }
- if (!('getLocalStreams' in window.RTCPeerConnection.prototype)) {
- window.RTCPeerConnection.prototype.getLocalStreams = function() {
- if (!this._localStreams) {
- this._localStreams = [];
- }
- return this._localStreams;
- };
- }
- if (!('getStreamById' in window.RTCPeerConnection.prototype)) {
- window.RTCPeerConnection.prototype.getStreamById = function(id) {
- var result = null;
- if (this._localStreams) {
- this._localStreams.forEach(function(stream) {
- if (stream.id === id) {
- result = stream;
- }
- });
- }
- if (this._remoteStreams) {
- this._remoteStreams.forEach(function(stream) {
- if (stream.id === id) {
- result = stream;
- }
- });
- }
- return result;
- };
- }
- if (!('addStream' in window.RTCPeerConnection.prototype)) {
- var _addTrack = window.RTCPeerConnection.prototype.addTrack;
- window.RTCPeerConnection.prototype.addStream = function(stream) {
- if (!this._localStreams) {
- this._localStreams = [];
- }
- if (this._localStreams.indexOf(stream) === -1) {
- this._localStreams.push(stream);
- }
- var pc = this;
- stream.getTracks().forEach(function(track) {
- _addTrack.call(pc, track, stream);
- });
- };
-
- window.RTCPeerConnection.prototype.addTrack = function(track, stream) {
- if (stream) {
- if (!this._localStreams) {
- this._localStreams = [stream];
- } else if (this._localStreams.indexOf(stream) === -1) {
- this._localStreams.push(stream);
- }
- }
- return _addTrack.call(this, track, stream);
- };
- }
- if (!('removeStream' in window.RTCPeerConnection.prototype)) {
- window.RTCPeerConnection.prototype.removeStream = function(stream) {
- if (!this._localStreams) {
- this._localStreams = [];
- }
- var index = this._localStreams.indexOf(stream);
- if (index === -1) {
- return;
- }
- this._localStreams.splice(index, 1);
- var pc = this;
- var tracks = stream.getTracks();
- this.getSenders().forEach(function(sender) {
- if (tracks.indexOf(sender.track) !== -1) {
- pc.removeTrack(sender);
- }
- });
- };
- }
- },
- shimRemoteStreamsAPI: function(window) {
- if (typeof window !== 'object' || !window.RTCPeerConnection) {
- return;
- }
- if (!('getRemoteStreams' in window.RTCPeerConnection.prototype)) {
- window.RTCPeerConnection.prototype.getRemoteStreams = function() {
- return this._remoteStreams ? this._remoteStreams : [];
- };
- }
- if (!('onaddstream' in window.RTCPeerConnection.prototype)) {
- Object.defineProperty(window.RTCPeerConnection.prototype, 'onaddstream', {
- get: function() {
- return this._onaddstream;
- },
- set: function(f) {
- var pc = this;
- if (this._onaddstream) {
- this.removeEventListener('addstream', this._onaddstream);
- this.removeEventListener('track', this._onaddstreampoly);
- }
- this.addEventListener('addstream', this._onaddstream = f);
- this.addEventListener('track', this._onaddstreampoly = function(e) {
- e.streams.forEach(function(stream) {
- if (!pc._remoteStreams) {
- pc._remoteStreams = [];
- }
- if (pc._remoteStreams.indexOf(stream) >= 0) {
- return;
- }
- pc._remoteStreams.push(stream);
- var event = new Event('addstream');
- event.stream = stream;
- pc.dispatchEvent(event);
- });
- });
- }
- });
- }
- },
- shimCallbacksAPI: function(window) {
- if (typeof window !== 'object' || !window.RTCPeerConnection) {
- return;
- }
- var prototype = window.RTCPeerConnection.prototype;
- var createOffer = prototype.createOffer;
- var createAnswer = prototype.createAnswer;
- var setLocalDescription = prototype.setLocalDescription;
- var setRemoteDescription = prototype.setRemoteDescription;
- var addIceCandidate = prototype.addIceCandidate;
-
- prototype.createOffer = function(successCallback, failureCallback) {
- var options = (arguments.length >= 2) ? arguments[2] : arguments[0];
- var promise = createOffer.apply(this, [options]);
- if (!failureCallback) {
- return promise;
- }
- promise.then(successCallback, failureCallback);
- return Promise.resolve();
- };
-
- prototype.createAnswer = function(successCallback, failureCallback) {
- var options = (arguments.length >= 2) ? arguments[2] : arguments[0];
- var promise = createAnswer.apply(this, [options]);
- if (!failureCallback) {
- return promise;
- }
- promise.then(successCallback, failureCallback);
- return Promise.resolve();
- };
-
- var withCallback = function(description, successCallback, failureCallback) {
- var promise = setLocalDescription.apply(this, [description]);
- if (!failureCallback) {
- return promise;
- }
- promise.then(successCallback, failureCallback);
- return Promise.resolve();
- };
- prototype.setLocalDescription = withCallback;
-
- withCallback = function(description, successCallback, failureCallback) {
- var promise = setRemoteDescription.apply(this, [description]);
- if (!failureCallback) {
- return promise;
- }
- promise.then(successCallback, failureCallback);
- return Promise.resolve();
- };
- prototype.setRemoteDescription = withCallback;
-
- withCallback = function(candidate, successCallback, failureCallback) {
- var promise = addIceCandidate.apply(this, [candidate]);
- if (!failureCallback) {
- return promise;
- }
- promise.then(successCallback, failureCallback);
- return Promise.resolve();
- };
- prototype.addIceCandidate = withCallback;
- },
- shimGetUserMedia: function(window) {
- var navigator = window && window.navigator;
-
- if (!navigator.getUserMedia) {
- if (navigator.webkitGetUserMedia) {
- navigator.getUserMedia = navigator.webkitGetUserMedia.bind(navigator);
- } else if (navigator.mediaDevices &&
- navigator.mediaDevices.getUserMedia) {
- navigator.getUserMedia = function(constraints, cb, errcb) {
- navigator.mediaDevices.getUserMedia(constraints)
- .then(cb, errcb);
- }.bind(navigator);
- }
- }
- },
- shimRTCIceServerUrls: function(window) {
- // migrate from non-spec RTCIceServer.url to RTCIceServer.urls
- var OrigPeerConnection = window.RTCPeerConnection;
- window.RTCPeerConnection = function(pcConfig, pcConstraints) {
- if (pcConfig && pcConfig.iceServers) {
- var newIceServers = [];
- for (var i = 0; i < pcConfig.iceServers.length; i++) {
- var server = pcConfig.iceServers[i];
- if (!server.hasOwnProperty('urls') &&
- server.hasOwnProperty('url')) {
- utils.deprecated('RTCIceServer.url', 'RTCIceServer.urls');
- server = JSON.parse(JSON.stringify(server));
- server.urls = server.url;
- delete server.url;
- newIceServers.push(server);
- } else {
- newIceServers.push(pcConfig.iceServers[i]);
- }
- }
- pcConfig.iceServers = newIceServers;
- }
- return new OrigPeerConnection(pcConfig, pcConstraints);
- };
- window.RTCPeerConnection.prototype = OrigPeerConnection.prototype;
- // wrap static methods. Currently just generateCertificate.
- if ('generateCertificate' in window.RTCPeerConnection) {
- Object.defineProperty(window.RTCPeerConnection, 'generateCertificate', {
- get: function() {
- return OrigPeerConnection.generateCertificate;
- }
- });
- }
- },
- shimTrackEventTransceiver: function(window) {
- // Add event.transceiver member over deprecated event.receiver
- if (typeof window === 'object' && window.RTCPeerConnection &&
- ('receiver' in window.RTCTrackEvent.prototype) &&
- // can't check 'transceiver' in window.RTCTrackEvent.prototype, as it is
- // defined for some reason even when window.RTCTransceiver is not.
- !window.RTCTransceiver) {
- Object.defineProperty(window.RTCTrackEvent.prototype, 'transceiver', {
- get: function() {
- return {receiver: this.receiver};
- }
- });
- }
- },
-
- shimCreateOfferLegacy: function(window) {
- var origCreateOffer = window.RTCPeerConnection.prototype.createOffer;
- window.RTCPeerConnection.prototype.createOffer = function(offerOptions) {
- var pc = this;
- if (offerOptions) {
- var audioTransceiver = pc.getTransceivers().find(function(transceiver) {
- return transceiver.sender.track &&
- transceiver.sender.track.kind === 'audio';
- });
- if (offerOptions.offerToReceiveAudio === false && audioTransceiver) {
- if (audioTransceiver.direction === 'sendrecv') {
- if (audioTransceiver.setDirection) {
- audioTransceiver.setDirection('sendonly');
- } else {
- audioTransceiver.direction = 'sendonly';
- }
- } else if (audioTransceiver.direction === 'recvonly') {
- if (audioTransceiver.setDirection) {
- audioTransceiver.setDirection('inactive');
- } else {
- audioTransceiver.direction = 'inactive';
- }
- }
- } else if (offerOptions.offerToReceiveAudio === true &&
- !audioTransceiver) {
- pc.addTransceiver('audio');
- }
-
- var videoTransceiver = pc.getTransceivers().find(function(transceiver) {
- return transceiver.sender.track &&
- transceiver.sender.track.kind === 'video';
- });
- if (offerOptions.offerToReceiveVideo === false && videoTransceiver) {
- if (videoTransceiver.direction === 'sendrecv') {
- videoTransceiver.setDirection('sendonly');
- } else if (videoTransceiver.direction === 'recvonly') {
- videoTransceiver.setDirection('inactive');
- }
- } else if (offerOptions.offerToReceiveVideo === true &&
- !videoTransceiver) {
- pc.addTransceiver('video');
- }
- }
- return origCreateOffer.apply(pc, arguments);
- };
- }
-};
-
-},{"../utils":13}],13:[function(require,module,exports){
-/*
- * Copyright (c) 2016 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.
- */
- /* eslint-env node */
-'use strict';
-
-var logDisabled_ = true;
-var deprecationWarnings_ = true;
-
-/**
- * Extract browser version out of the provided user agent string.
- *
- * @param {!string} uastring userAgent string.
- * @param {!string} expr Regular expression used as match criteria.
- * @param {!number} pos position in the version string to be returned.
- * @return {!number} browser version.
- */
-function extractVersion(uastring, expr, pos) {
- var match = uastring.match(expr);
- return match && match.length >= pos && parseInt(match[pos], 10);
-}
-
-// Wraps the peerconnection event eventNameToWrap in a function
-// which returns the modified event object.
-function wrapPeerConnectionEvent(window, eventNameToWrap, wrapper) {
- if (!window.RTCPeerConnection) {
- return;
- }
- var proto = window.RTCPeerConnection.prototype;
- var nativeAddEventListener = proto.addEventListener;
- proto.addEventListener = function(nativeEventName, cb) {
- if (nativeEventName !== eventNameToWrap) {
- return nativeAddEventListener.apply(this, arguments);
- }
- var wrappedCallback = function(e) {
- cb(wrapper(e));
- };
- this._eventMap = this._eventMap || {};
- this._eventMap[cb] = wrappedCallback;
- return nativeAddEventListener.apply(this, [nativeEventName,
- wrappedCallback]);
- };
-
- var nativeRemoveEventListener = proto.removeEventListener;
- proto.removeEventListener = function(nativeEventName, cb) {
- if (nativeEventName !== eventNameToWrap || !this._eventMap
- || !this._eventMap[cb]) {
- return nativeRemoveEventListener.apply(this, arguments);
- }
- var unwrappedCb = this._eventMap[cb];
- delete this._eventMap[cb];
- return nativeRemoveEventListener.apply(this, [nativeEventName,
- unwrappedCb]);
- };
-
- Object.defineProperty(proto, 'on' + eventNameToWrap, {
- get: function() {
- return this['_on' + eventNameToWrap];
- },
- set: function(cb) {
- if (this['_on' + eventNameToWrap]) {
- this.removeEventListener(eventNameToWrap,
- this['_on' + eventNameToWrap]);
- delete this['_on' + eventNameToWrap];
- }
- if (cb) {
- this.addEventListener(eventNameToWrap,
- this['_on' + eventNameToWrap] = cb);
- }
- }
- });
-}
-
-// Utility methods.
-module.exports = {
- extractVersion: extractVersion,
- wrapPeerConnectionEvent: wrapPeerConnectionEvent,
- disableLog: function(bool) {
- if (typeof bool !== 'boolean') {
- return new Error('Argument type: ' + typeof bool +
- '. Please use a boolean.');
- }
- logDisabled_ = bool;
- return (bool) ? 'adapter.js logging disabled' :
- 'adapter.js logging enabled';
- },
-
- /**
- * Disable or enable deprecation warnings
- * @param {!boolean} bool set to true to disable warnings.
- */
- disableWarnings: function(bool) {
- if (typeof bool !== 'boolean') {
- return new Error('Argument type: ' + typeof bool +
- '. Please use a boolean.');
- }
- deprecationWarnings_ = !bool;
- return 'adapter.js deprecation warnings ' + (bool ? 'disabled' : 'enabled');
- },
-
- log: function() {
- if (typeof window === 'object') {
- if (logDisabled_) {
- return;
- }
- if (typeof console !== 'undefined' && typeof console.log === 'function') {
- console.log.apply(console, arguments);
- }
- }
- },
-
- /**
- * Shows a deprecation warning suggesting the modern and spec-compatible API.
- */
- deprecated: function(oldMethod, newMethod) {
- if (!deprecationWarnings_) {
- return;
- }
- console.warn(oldMethod + ' is deprecated, please use ' + newMethod +
- ' instead.');
- },
-
- /**
- * Browser detector.
- *
- * @return {object} result containing browser and version
- * properties.
- */
- detectBrowser: function(window) {
- var navigator = window && window.navigator;
-
- // Returned result object.
- var result = {};
- result.browser = null;
- result.version = null;
-
- // Fail early if it's not a browser
- if (typeof window === 'undefined' || !window.navigator) {
- result.browser = 'Not a browser.';
- return result;
- }
-
- if (navigator.mozGetUserMedia) { // Firefox.
- result.browser = 'firefox';
- result.version = extractVersion(navigator.userAgent,
- /Firefox\/(\d+)\./, 1);
- } else if (navigator.webkitGetUserMedia) {
- // Chrome, Chromium, Webview, Opera.
- // Version matches Chrome/WebRTC version.
- result.browser = 'chrome';
- result.version = extractVersion(navigator.userAgent,
- /Chrom(e|ium)\/(\d+)\./, 2);
- } else if (navigator.mediaDevices &&
- navigator.userAgent.match(/Edge\/(\d+).(\d+)$/)) { // Edge.
- result.browser = 'edge';
- result.version = extractVersion(navigator.userAgent,
- /Edge\/(\d+).(\d+)$/, 2);
- } else if (navigator.mediaDevices &&
- navigator.userAgent.match(/AppleWebKit\/(\d+)\./)) { // Safari.
- result.browser = 'safari';
- result.version = extractVersion(navigator.userAgent,
- /AppleWebKit\/(\d+)\./, 1);
- } else { // Default fallthrough: not supported.
- result.browser = 'Not a supported browser.';
- return result;
- }
-
- return result;
- }
-};
-
-},{}]},{},[3])(3)
-});
\ No newline at end of file
+(function($){function findLine(sdpLines,prefix,substr){return findLineInRange(sdpLines,0,-1,prefix,substr);}
+function findLineInRange(sdpLines,startLine,endLine,prefix,substr){var realEndLine=(endLine!=-1)?endLine:sdpLines.length;for(var i=startLine;i=0;if(iOS){self.options.useVideo.setAttribute("playsinline",true);}}
+var element=self.options.useAudio;console.log("REMOTE STREAM",stream,element);FSRTCattachMediaStream(element,stream);self.remoteStream=stream;onRemoteStreamSuccess(self,stream);}
+function onOfferSDP(self,sdp){self.mediaData.SDP=self.stereoHack(sdp.sdp);console.log("Offer SDP");doCallback(self,"onOfferSDP");}
+$.FSRTC.prototype.answer=function(sdp,onSuccess,onError){this.peer.addAnswerSDP({type:"answer",sdp:sdp},onSuccess,onError);};$.FSRTC.prototype.stopPeer=function(){if(self.peer){console.log("stopping peer");self.peer.stop();}}
+$.FSRTC.prototype.stop=function(){var self=this;if(self.options.useVideo){self.options.useVideo.style.display='none';self.options.useVideo['src']='';}
+if(self.localStream&&!self.options.useStream){if(typeof self.localStream.stop=='function'){self.localStream.stop();}else{if(self.localStream.active){var tracks=self.localStream.getTracks();console.log(tracks);tracks.forEach(function(track,index){console.log(track);track.stop();})}}
+self.localStream=null;}
+if(self.options.localVideo){deactivateLocalVideo(self.options.localVideo);}
+if(self.options.localVideoStream&&!self.options.useStream){if(typeof self.options.localVideoStream.stop=='function'){self.options.localVideoStream.stop();}else{if(self.options.localVideoStream.active){var tracks=self.options.localVideoStream.getTracks();console.log(tracks);tracks.forEach(function(track,index){console.log(track);track.stop();})}}}
+if(self.peer){console.log("stopping peer");self.peer.stop();}};$.FSRTC.prototype.getMute=function(){var self=this;return self.audioEnabled;}
+$.FSRTC.prototype.setMute=function(what){var self=this;if(!self.localStream){return false;}
+var audioTracks=self.localStream.getAudioTracks();for(var i=0,len=audioTracks.length;i=w&&$.FSRTC.validRes[i][1]>=h){w=$.FSRTC.validRes[i][0];h=$.FSRTC.validRes[i][1];}}
+return[w,h];}
+var resList=[[160,120],[320,180],[320,240],[640,360],[640,480],[1280,720],[1920,1080]];var resI=0;var ttl=0;var checkRes=function(cam,func){if(resI>=resList.length){var res={'validRes':$.FSRTC.validRes,'bestResSupported':$.FSRTC.bestResSupported()};localStorage.setItem("res_"+cam,$.toJSON(res));if(func)return func(res);return;}
+w=resList[resI][0];h=resList[resI][1];resI++;var video={width:{exact:w},height:{exact:h}};if(cam!=="any"){video=assignMediaIdToConstraint(cam,video);}
+getUserMedia({constraints:{audio:ttl++==0,video:video},onsuccess:function(e){e.getTracks().forEach(function(track){track.stop();});console.info(w+"x"+h+" supported.");$.FSRTC.validRes.push([w,h]);checkRes(cam,func);},onerror:function(e){console.warn(w+"x"+h+" not supported.");checkRes(cam,func);}});}
+$.FSRTC.getValidRes=function(cam,func){var used=[];var cached=localStorage.getItem("res_"+cam);if(cached){var cache=$.parseJSON(cached);if(cache){$.FSRTC.validRes=cache.validRes;console.log("CACHED RES FOR CAM "+cam,cache);}else{console.error("INVALID CACHE");}
+return func?func(cache):null;}
+$.FSRTC.validRes=[];resI=0;checkRes(cam,func);}
+$.FSRTC.checkPerms=function(runtime,check_audio,check_video){getUserMedia({constraints:{audio:check_audio,video:check_video,},onsuccess:function(e){e.getTracks().forEach(function(track){track.stop();});console.info("media perm init complete");if(runtime){setTimeout(runtime,100,true);}},onerror:function(e){if(check_video&&check_audio){console.error("error, retesting with audio params only");return $.FSRTC.checkPerms(runtime,check_audio,false);}
+console.error("media perm init error");if(runtime){runtime(false)}}});}})(jQuery);(function($){$.JsonRpcClient=function(options){var self=this;this.options=$.extend({ajaxUrl:null,socketUrl:null,onmessage:null,login:null,passwd:null,sessid:null,loginParams:null,userVariables:null,getSocket:function(onmessage_cb){return self._getSocket(onmessage_cb);}},options);self.ws_cnt=0;this.wsOnMessage=function(event){self._wsOnMessage(event);};};$.JsonRpcClient.prototype._ws_socket=null;$.JsonRpcClient.prototype._ws_callbacks={};$.JsonRpcClient.prototype._current_id=1;$.JsonRpcClient.prototype.speedTest=function(bytes,cb){var socket=this.options.getSocket(this.wsOnMessage);if(socket!==null){this.speedCB=cb;this.speedBytes=bytes;socket.send("#SPU "+bytes);var loops=bytes/1024;var rem=bytes%1024;var i;var data=new Array(1024).join(".");for(i=0;i1){return false;}
+return true;};$.JsonRpcClient.prototype.closeSocket=function(){var self=this;if(self.socketReady()){self._ws_socket.onclose=function(w){console.log("Closing Socket");};self._ws_socket.close();}};$.JsonRpcClient.prototype.loginData=function(params){var self=this;self.options.login=params.login;self.options.passwd=params.passwd;self.options.loginParams=params.loginParams;self.options.userVariables=params.userVariables;};$.JsonRpcClient.prototype.connectSocket=function(onmessage_cb){var self=this;if(self.to){clearTimeout(self.to);}
+if(!self.socketReady()){self.authing=false;if(self._ws_socket){delete self._ws_socket;}
+self._ws_socket=new WebSocket(self.options.socketUrl);if(self._ws_socket){self._ws_socket.onmessage=onmessage_cb;self._ws_socket.onclose=function(w){if(!self.ws_sleep){self.ws_sleep=1000;}
+if(self.options.onWSClose){self.options.onWSClose(self);}
+if(self.ws_cnt>10&&self.options.wsFallbackURL){self.options.socketUrl=self.options.wsFallbackURL;}
+console.error("Websocket Lost "+self.ws_cnt+" sleep: "+self.ws_sleep+"msec");self.to=setTimeout(function(){console.log("Attempting Reconnection....");self.connectSocket(onmessage_cb);},self.ws_sleep);self.ws_cnt++;if(self.ws_sleep<3000&&(self.ws_cnt%10)===0){self.ws_sleep+=1000;}};self._ws_socket.onopen=function(){if(self.to){clearTimeout(self.to);}
+self.ws_sleep=1000;self.ws_cnt=0;if(self.options.onWSConnect){self.options.onWSConnect(self);}
+var req;while((req=$.JsonRpcClient.q.pop())){self._ws_socket.send(req);}};}}
+return self._ws_socket?true:false;};$.JsonRpcClient.prototype.stopRetrying=function(){if(self.to)
+clearTimeout(self.to);}
+$.JsonRpcClient.prototype._getSocket=function(onmessage_cb){if(this.options.socketUrl===null||!("WebSocket"in window))return null;this.connectSocket(onmessage_cb);return this._ws_socket;};$.JsonRpcClient.q=[];$.JsonRpcClient.prototype._wsCall=function(socket,request,success_cb,error_cb){var request_json=$.toJSON(request);if(socket.readyState<1){self=this;$.JsonRpcClient.q.push(request_json);}else{socket.send(request_json);}
+if('id'in request&&typeof success_cb!=='undefined'){this._ws_callbacks[request.id]={request:request_json,request_obj:request,success_cb:success_cb,error_cb:error_cb};}};$.JsonRpcClient.prototype._wsOnMessage=function(event){var response;if(event.data[0]=="#"&&event.data[1]=="S"&&event.data[2]=="P"){if(event.data[3]=="U"){this.up_dur=parseInt(event.data.substring(4));}else if(this.speedCB&&event.data[3]=="D"){this.down_dur=parseInt(event.data.substring(4));var up_kps=(((this.speedBytes*8)/(this.up_dur/1000))/1024).toFixed(0);var down_kps=(((this.speedBytes*8)/(this.down_dur/1000))/1024).toFixed(0);console.info("Speed Test: Up: "+up_kps+" Down: "+down_kps);var cb=this.speedCB;this.speedCB=null;cb(event,{upDur:this.up_dur,downDur:this.down_dur,upKPS:up_kps,downKPS:down_kps});}
+return;}
+try{response=$.parseJSON(event.data);if(typeof response==='object'&&'jsonrpc'in response&&response.jsonrpc==='2.0'){if('result'in response&&this._ws_callbacks[response.id]){var success_cb=this._ws_callbacks[response.id].success_cb;delete this._ws_callbacks[response.id];success_cb(response.result,this);return;}else if('error'in response&&this._ws_callbacks[response.id]){var error_cb=this._ws_callbacks[response.id].error_cb;var orig_req=this._ws_callbacks[response.id].request;if(!self.authing&&response.error.code==-32000&&self.options.login&&self.options.passwd){self.authing=true;this.call("login",{login:self.options.login,passwd:self.options.passwd,loginParams:self.options.loginParams,userVariables:self.options.userVariables},this._ws_callbacks[response.id].request_obj.method=="login"?function(e){self.authing=false;console.log("logged in");delete self._ws_callbacks[response.id];if(self.options.onWSLogin){self.options.onWSLogin(true,self);}}:function(e){self.authing=false;console.log("logged in, resending request id: "+response.id);var socket=self.options.getSocket(self.wsOnMessage);if(socket!==null){socket.send(orig_req);}
+if(self.options.onWSLogin){self.options.onWSLogin(true,self);}},function(e){console.log("error logging in, request id:",response.id);delete self._ws_callbacks[response.id];error_cb(response.error,this);if(self.options.onWSLogin){self.options.onWSLogin(false,self);}});return;}
+delete this._ws_callbacks[response.id];error_cb(response.error,this);return;}}}catch(err){console.log("ERROR: "+err);return;}
+if(typeof this.options.onmessage==='function'){event.eventData=response;if(!event.eventData){event.eventData={};}
+var reply=this.options.onmessage(event);if(reply&&typeof reply==="object"&&event.eventData.id){var msg={jsonrpc:"2.0",id:event.eventData.id,result:reply};var socket=self.options.getSocket(self.wsOnMessage);if(socket!==null){socket.send($.toJSON(msg));}}}};$.JsonRpcClient._batchObject=function(jsonrpcclient,all_done_cb,error_cb){this._requests=[];this.jsonrpcclient=jsonrpcclient;this.all_done_cb=all_done_cb;this.error_cb=typeof error_cb==='function'?error_cb:function(){};};$.JsonRpcClient._batchObject.prototype.call=function(method,params,success_cb,error_cb){if(!params){params={};}
+if(this.options.sessid){params.sessid=this.options.sessid;}
+if(!success_cb){success_cb=function(e){console.log("Success: ",e);};}
+if(!error_cb){error_cb=function(e){console.log("Error: ",e);};}
+this._requests.push({request:{jsonrpc:'2.0',method:method,params:params,id:this.jsonrpcclient._current_id++},success_cb:success_cb,error_cb:error_cb});};$.JsonRpcClient._batchObject.prototype.notify=function(method,params){if(this.options.sessid){params.sessid=this.options.sessid;}
+this._requests.push({request:{jsonrpc:'2.0',method:method,params:params}});};$.JsonRpcClient._batchObject.prototype._execute=function(){var self=this;if(this._requests.length===0)return;var batch_request=[];var handlers={};var i=0;var call;var success_cb;var error_cb;var socket=self.jsonrpcclient.options.getSocket(self.jsonrpcclient.wsOnMessage);if(socket!==null){for(i=0;i0){data.params.useVideo=true;}
+if(data.params.sdp&&data.params.sdp.indexOf("stereo=1")>0){data.params.useStereo=true;}
+dialog=new $.verto.dialog($.verto.enum.direction.inbound,verto,data.params);dialog.setState($.verto.enum.state.recovering);break;case'verto.invite':if(data.params.sdp&&data.params.sdp.indexOf("m=video")>0){data.params.wantVideo=true;}
+if(data.params.sdp&&data.params.sdp.indexOf("stereo=1")>0){data.params.useStereo=true;}
+dialog=new $.verto.dialog($.verto.enum.direction.inbound,verto,data.params);break;default:console.debug("INVALID METHOD OR NON-EXISTANT CALL REFERENCE IGNORED");break;}}
+return{method:data.method};}else{switch(data.method){case'verto.punt':verto.purge();verto.logout();break;case'verto.event':var list=null;var key=null;if(data.params){key=data.params.eventChannel;}
+if(key){list=verto.eventSUBS[key];if(!list){list=verto.eventSUBS[key.split(".")[0]];}}
+if(!list&&key&&key===verto.sessid){if(verto.callbacks.onMessage){verto.callbacks.onMessage(verto,null,$.verto.enum.message.pvtEvent,data.params);}}else if(!list&&key&&verto.dialogs[key]){verto.dialogs[key].sendMessage($.verto.enum.message.pvtEvent,data.params);}else if(!list){if(!key){key="UNDEFINED";}
+console.error("UNSUBBED or invalid EVENT "+key+" IGNORED");}else{for(var i in list){var sub=list[i];if(!sub||!sub.ready){console.error("invalid EVENT for "+key+" IGNORED");}else if(sub.handler){sub.handler(verto,data.params,sub.userData);}else if(verto.callbacks.onEvent){verto.callbacks.onEvent(verto,data.params,sub.userData);}else{console.log("EVENT:",data.params);}}}
+break;case"verto.info":if(verto.callbacks.onMessage){verto.callbacks.onMessage(verto,null,$.verto.enum.message.info,data.params.msg);}
+console.debug("MESSAGE from: "+data.params.msg.from,data.params.msg.body);break;case'verto.clientReady':if(verto.callbacks.onMessage){verto.callbacks.onMessage(verto,null,$.verto.enum.message.clientReady,data.params);}
+console.debug("CLIENT READY",data.params);break;default:console.error("INVALID METHOD OR NON-EXISTANT CALL REFERENCE IGNORED",data.method);break;}}};var del_array=function(array,name){var r=[];var len=array.length;for(var i=0;i=array.length){array.push(name);}else{var x=0;var n=[];var len=array.length;for(var i=0;i":"\n");});return str;};};$.verto.liveArray=function(verto,context,name,config){var la=this;var lastSerno=0;var binding=null;var user_obj=config.userObj;var local=false;hashArray.call(la);la._add=la.add;la._del=la.del;la._reorder=la.reorder;la._clear=la.clear;la.context=context;la.name=name;la.user_obj=user_obj;la.verto=verto;la.broadcast=function(channel,obj){verto.broadcast(channel,obj);};la.errs=0;la.clear=function(){la._clear();lastSerno=0;if(la.onChange){la.onChange(la,{action:"clear"});}};la.checkSerno=function(serno){if(serno<0){return true;}
+if(lastSerno>0&&serno!=(lastSerno+1)){if(la.onErr){la.onErr(la,{lastSerno:lastSerno,serno:serno});}
+la.errs++;console.debug(la.errs);if(la.errs<3){la.bootstrap(la.user_obj);}
+return false;}else{lastSerno=serno;return true;}};la.reorder=function(serno,a){if(la.checkSerno(serno)){la._reorder(a);if(la.onChange){la.onChange(la,{serno:serno,action:"reorder"});}}};la.init=function(serno,val,key,index){if(key===null||key===undefined){key=serno;}
+if(la.checkSerno(serno)){if(la.onChange){la.onChange(la,{serno:serno,action:"init",index:index,key:key,data:val});}}};la.bootObj=function(serno,val){if(la.checkSerno(serno)){for(var i in val){la._add(val[i][0],val[i][1]);}
+if(la.onChange){la.onChange(la,{serno:serno,action:"bootObj",data:val,redraw:true});}}};la.add=function(serno,val,key,index){if(key===null||key===undefined){key=serno;}
+if(la.checkSerno(serno)){var redraw=la._add(key,val,index);if(la.onChange){la.onChange(la,{serno:serno,action:"add",index:index,key:key,data:val,redraw:redraw});}}};la.modify=function(serno,val,key,index){if(key===null||key===undefined){key=serno;}
+if(la.checkSerno(serno)){la._add(key,val,index);if(la.onChange){la.onChange(la,{serno:serno,action:"modify",key:key,data:val,index:index});}}};la.del=function(serno,key,index){if(key===null||key===undefined){key=serno;}
+if(la.checkSerno(serno)){if(index===null||index<0||index===undefined){index=la.indexOf(key);}
+var ok=la._del(key);if(ok&&la.onChange){la.onChange(la,{serno:serno,action:"del",key:key,index:index});}}};var eventHandler=function(v,e,la){var packet=e.data;if(packet.name!=la.name){return;}
+switch(packet.action){case"init":la.init(packet.wireSerno,packet.data,packet.hashKey,packet.arrIndex);break;case"bootObj":la.bootObj(packet.wireSerno,packet.data);break;case"add":la.add(packet.wireSerno,packet.data,packet.hashKey,packet.arrIndex);break;case"modify":if(!(packet.arrIndex||packet.hashKey)){console.error("Invalid Packet",packet);}else{la.modify(packet.wireSerno,packet.data,packet.hashKey,packet.arrIndex);}
+break;case"del":if(!(packet.arrIndex||packet.hashKey)){console.error("Invalid Packet",packet);}else{la.del(packet.wireSerno,packet.hashKey,packet.arrIndex);}
+break;case"clear":la.clear();break;case"reorder":la.reorder(packet.wireSerno,packet.order);break;default:if(la.checkSerno(packet.wireSerno)){if(la.onChange){la.onChange(la,{serno:packet.wireSerno,action:packet.action,data:packet.data});}}
+break;}};if(la.context){binding=la.verto.subscribe(la.context,{handler:eventHandler,userData:la,subParams:config.subParams});}
+la.destroy=function(){la._clear();la.verto.unsubscribe(binding);};la.sendCommand=function(cmd,obj){var self=la;self.broadcast(self.context,{liveArray:{command:cmd,context:self.context,name:self.name,obj:obj}});};la.bootstrap=function(obj){var self=la;la.sendCommand("bootstrap",obj);};la.changepage=function(obj){var self=la;self.clear();self.broadcast(self.context,{liveArray:{command:"changepage",context:la.context,name:la.name,obj:obj}});};la.heartbeat=function(obj){var self=la;var callback=function(){self.heartbeat.call(self,obj);};self.broadcast(self.context,{liveArray:{command:"heartbeat",context:self.context,name:self.name,obj:obj}});self.hb_pid=setTimeout(callback,30000);};la.bootstrap(la.user_obj);};$.verto.liveTable=function(verto,context,name,jq,config){var dt;var la=new $.verto.liveArray(verto,context,name,{subParams:config.subParams});var lt=this;lt.liveArray=la;lt.dataTable=dt;lt.verto=verto;lt.destroy=function(){if(dt){dt.fnDestroy();}
+if(la){la.destroy();}
+dt=null;la=null;};la.onErr=function(obj,args){console.error("Error: ",obj,args);};function genRow(data){if(typeof(data[4])==="string"&&data[4].indexOf("{")>-1){var tmp=$.parseJSON(data[4]);data[4]=tmp.oldStatus;data[5]=null;}
+return data;}
+function genArray(obj){var data=obj.asArray();for(var i in data){data[i]=genRow(data[i]);}
+return data;}
+la.onChange=function(obj,args){var index=0;var iserr=0;if(!dt){if(!config.aoColumns){if(args.action!="init"){return;}
+config.aoColumns=[];for(var i in args.data){config.aoColumns.push({"sTitle":args.data[i]});}}
+dt=jq.dataTable(config);}
+if(dt&&(args.action=="del"||args.action=="modify")){index=args.index;if(index===undefined&&args.key){index=la.indexOf(args.key);}
+if(index===undefined){console.error("INVALID PACKET Missing INDEX\n",args);return;}}
+if(config.onChange){config.onChange(obj,args);}
+try{switch(args.action){case"bootObj":if(!args.data){console.error("missing data");return;}
+dt.fnClearTable();dt.fnAddData(genArray(obj));dt.fnAdjustColumnSizing();break;case"add":if(!args.data){console.error("missing data");return;}
+if(args.redraw>-1){dt.fnClearTable();dt.fnAddData(genArray(obj));}else{dt.fnAddData(genRow(args.data));}
+dt.fnAdjustColumnSizing();break;case"modify":if(!args.data){return;}
+dt.fnUpdate(genRow(args.data),index);dt.fnAdjustColumnSizing();break;case"del":dt.fnDeleteRow(index);dt.fnAdjustColumnSizing();break;case"clear":dt.fnClearTable();break;case"reorder":dt.fnClearTable();dt.fnAddData(genArray(obj));break;case"hide":jq.hide();break;case"show":jq.show();break;}}catch(err){console.error("ERROR: "+err);iserr++;}
+if(iserr){obj.errs++;if(obj.errs<3){obj.bootstrap(obj.user_obj);}}else{obj.errs=0;}};la.onChange(la,{action:"init"});};var CONFMAN_SERNO=1;$.verto.conf=function(verto,params){var conf=this;conf.params=$.extend({dialog:null,hasVid:false,laData:null,onBroadcast:null,onLaChange:null,onLaRow:null},params);conf.verto=verto;conf.serno=CONFMAN_SERNO++;createMainModeratorMethods();verto.subscribe(conf.params.laData.modChannel,{handler:function(v,e){if(conf.params.onBroadcast){conf.params.onBroadcast(verto,conf,e.data);}}});verto.subscribe(conf.params.laData.infoChannel,{handler:function(v,e){if(typeof(conf.params.infoCallback)==="function"){conf.params.infoCallback(v,e);}}});verto.subscribe(conf.params.laData.chatChannel,{handler:function(v,e){if(typeof(conf.params.chatCallback)==="function"){conf.params.chatCallback(v,e);}}});};$.verto.conf.prototype.modCommand=function(cmd,id,value){var conf=this;conf.verto.rpcClient.call("verto.broadcast",{"eventChannel":conf.params.laData.modChannel,"data":{"application":"conf-control","command":cmd,"id":id,"value":value}});};$.verto.conf.prototype.destroy=function(){var conf=this;conf.destroyed=true;conf.params.onBroadcast(conf.verto,conf,'destroy');if(conf.params.laData.modChannel){conf.verto.unsubscribe(conf.params.laData.modChannel);}
+if(conf.params.laData.chatChannel){conf.verto.unsubscribe(conf.params.laData.chatChannel);}
+if(conf.params.laData.infoChannel){conf.verto.unsubscribe(conf.params.laData.infoChannel);}};function createMainModeratorMethods(){$.verto.conf.prototype.listVideoLayouts=function(){this.modCommand("list-videoLayouts",null,null);};$.verto.conf.prototype.play=function(file){this.modCommand("play",null,file);};$.verto.conf.prototype.stop=function(){this.modCommand("stop",null,"all");};$.verto.conf.prototype.deaf=function(memberID){this.modCommand("deaf",parseInt(memberID));};$.verto.conf.prototype.undeaf=function(memberID){this.modCommand("undeaf",parseInt(memberID));};$.verto.conf.prototype.record=function(file){this.modCommand("recording",null,["start",file]);};$.verto.conf.prototype.stopRecord=function(){this.modCommand("recording",null,["stop","all"]);};$.verto.conf.prototype.snapshot=function(file){if(!this.params.hasVid){throw'Conference has no video';}
+this.modCommand("vid-write-png",null,file);};$.verto.conf.prototype.setVideoLayout=function(layout,canvasID){if(!this.params.hasVid){throw'Conference has no video';}
+if(canvasID){this.modCommand("vid-layout",null,[layout,canvasID]);}else{this.modCommand("vid-layout",null,layout);}};$.verto.conf.prototype.kick=function(memberID){this.modCommand("kick",parseInt(memberID));};$.verto.conf.prototype.muteMic=function(memberID){this.modCommand("tmute",parseInt(memberID));};$.verto.conf.prototype.muteVideo=function(memberID){if(!this.params.hasVid){throw'Conference has no video';}
+this.modCommand("tvmute",parseInt(memberID));};$.verto.conf.prototype.presenter=function(memberID){if(!this.params.hasVid){throw'Conference has no video';}
+this.modCommand("vid-res-id",parseInt(memberID),"presenter");};$.verto.conf.prototype.videoFloor=function(memberID){if(!this.params.hasVid){throw'Conference has no video';}
+this.modCommand("vid-floor",parseInt(memberID),"force");};$.verto.conf.prototype.banner=function(memberID,text){if(!this.params.hasVid){throw'Conference has no video';}
+this.modCommand("vid-banner",parseInt(memberID),escape(text));};$.verto.conf.prototype.volumeDown=function(memberID){this.modCommand("volume_out",parseInt(memberID),"down");};$.verto.conf.prototype.volumeUp=function(memberID){this.modCommand("volume_out",parseInt(memberID),"up");};$.verto.conf.prototype.gainDown=function(memberID){this.modCommand("volume_in",parseInt(memberID),"down");};$.verto.conf.prototype.gainUp=function(memberID){this.modCommand("volume_in",parseInt(memberID),"up");};$.verto.conf.prototype.transfer=function(memberID,exten){this.modCommand("transfer",parseInt(memberID),exten);};$.verto.conf.prototype.sendChat=function(message,type){var conf=this;conf.verto.rpcClient.call("verto.broadcast",{"eventChannel":conf.params.laData.chatChannel,"data":{"action":"send","message":message,"type":type}});};}
+$.verto.modfuncs={};$.verto.confMan=function(verto,params){var confMan=this;confMan.params=$.extend({tableID:null,statusID:null,mainModID:null,dialog:null,hasVid:false,laData:null,onBroadcast:null,onLaChange:null,onLaRow:null},params);confMan.verto=verto;confMan.serno=CONFMAN_SERNO++;confMan.canvasCount=confMan.params.laData.canvasCount;function genMainMod(jq){var play_id="play_"+confMan.serno;var stop_id="stop_"+confMan.serno;var recording_id="recording_"+confMan.serno;var snapshot_id="snapshot_"+confMan.serno;var rec_stop_id="recording_stop"+confMan.serno;var div_id="confman_"+confMan.serno;var html=" "+"Play "+"Stop "+"Record "+"Record Stop "+
+(confMan.params.hasVid?"PNG Snapshot ":"")+"
";jq.html(html);$.verto.modfuncs.change_video_layout=function(id,canvas_id){var val=$("#"+id+" option:selected").text();if(val!=="none"){confMan.modCommand("vid-layout",null,[val,canvas_id]);}};if(confMan.params.hasVid){for(var j=0;j "+"Video Layout Canvas "+(j+1)+" "+" ";jq.append(vlhtml);}
+$("#"+snapshot_id).click(function(){var file=prompt("Please enter file name","");if(file){confMan.modCommand("vid-write-png",null,file);}});}
+$("#"+play_id).click(function(){var file=prompt("Please enter file name","");if(file){confMan.modCommand("play",null,file);}});$("#"+stop_id).click(function(){confMan.modCommand("stop",null,"all");});$("#"+recording_id).click(function(){var file=prompt("Please enter file name","");if(file){confMan.modCommand("recording",null,["start",file]);}});$("#"+rec_stop_id).click(function(){confMan.modCommand("recording",null,["stop","all"]);});}
+function genControls(jq,rowid){var x=parseInt(rowid);var kick_id="kick_"+x;var canvas_in_next_id="canvas_in_next_"+x;var canvas_in_prev_id="canvas_in_prev_"+x;var canvas_out_next_id="canvas_out_next_"+x;var canvas_out_prev_id="canvas_out_prev_"+x;var canvas_in_set_id="canvas_in_set_"+x;var canvas_out_set_id="canvas_out_set_"+x;var layer_set_id="layer_set_"+x;var layer_next_id="layer_next_"+x;var layer_prev_id="layer_prev_"+x;var tmute_id="tmute_"+x;var tvmute_id="tvmute_"+x;var vbanner_id="vbanner_"+x;var tvpresenter_id="tvpresenter_"+x;var tvfloor_id="tvfloor_"+x;var box_id="box_"+x;var gainup_id="gain_in_up"+x;var gaindn_id="gain_in_dn"+x;var volup_id="vol_in_up"+x;var voldn_id="vol_in_dn"+x;var transfer_id="transfer"+x;var html="";html+="General Controls
";html+="Kick "+"Mute "+"Gain - "+"Gain + "+"Vol - "+"Vol + "+"Transfer ";if(confMan.params.hasVid){html+="Video Controls ";html+="VMute "+"Presenter "+"Vid Floor "+"Banner ";if(confMan.canvasCount>1){html+="Canvas Controls "+"Set Input Canvas "+"Prev Input Canvas "+"Next Input Canvas "+" "+"Set Watching Canvas "+"Prev Watching Canvas "+"Next Watching Canvas ";}
+html+=" "+"Set Layer "+"Prev Layer "+"Next Layer "+"";}
+jq.html(html);if(!jq.data("mouse")){$("#"+box_id).hide();}
+jq.mouseover(function(e){jq.data({"mouse":true});$("#"+box_id).show();});jq.mouseout(function(e){jq.data({"mouse":false});$("#"+box_id).hide();});$("#"+transfer_id).click(function(){var xten=prompt("Enter Extension");if(xten){confMan.modCommand("transfer",x,xten);}});$("#"+kick_id).click(function(){confMan.modCommand("kick",x);});$("#"+layer_set_id).click(function(){var cid=prompt("Please enter layer ID","");if(cid){confMan.modCommand("vid-layer",x,cid);}});$("#"+layer_next_id).click(function(){confMan.modCommand("vid-layer",x,"next");});$("#"+layer_prev_id).click(function(){confMan.modCommand("vid-layer",x,"prev");});$("#"+canvas_in_set_id).click(function(){var cid=prompt("Please enter canvas ID","");if(cid){confMan.modCommand("vid-canvas",x,cid);}});$("#"+canvas_out_set_id).click(function(){var cid=prompt("Please enter canvas ID","");if(cid){confMan.modCommand("vid-watching-canvas",x,cid);}});$("#"+canvas_in_next_id).click(function(){confMan.modCommand("vid-canvas",x,"next");});$("#"+canvas_in_prev_id).click(function(){confMan.modCommand("vid-canvas",x,"prev");});$("#"+canvas_out_next_id).click(function(){confMan.modCommand("vid-watching-canvas",x,"next");});$("#"+canvas_out_prev_id).click(function(){confMan.modCommand("vid-watching-canvas",x,"prev");});$("#"+tmute_id).click(function(){confMan.modCommand("tmute",x);});if(confMan.params.hasVid){$("#"+tvmute_id).click(function(){confMan.modCommand("tvmute",x);});$("#"+tvpresenter_id).click(function(){confMan.modCommand("vid-res-id",x,"presenter");});$("#"+tvfloor_id).click(function(){confMan.modCommand("vid-floor",x,"force");});$("#"+vbanner_id).click(function(){var text=prompt("Please enter text","");if(text){confMan.modCommand("vid-banner",x,escape(text));}});}
+$("#"+gainup_id).click(function(){confMan.modCommand("volume_in",x,"up");});$("#"+gaindn_id).click(function(){confMan.modCommand("volume_in",x,"down");});$("#"+volup_id).click(function(){confMan.modCommand("volume_out",x,"up");});$("#"+voldn_id).click(function(){confMan.modCommand("volume_out",x,"down");});return html;}
+var atitle="";var awidth=0;verto.subscribe(confMan.params.laData.infoChannel,{handler:function(v,e){if(typeof(confMan.params.infoCallback)==="function"){confMan.params.infoCallback(v,e);}}});verto.subscribe(confMan.params.laData.chatChannel,{handler:function(v,e){if(typeof(confMan.params.chatCallback)==="function"){confMan.params.chatCallback(v,e);}}});if(confMan.params.laData.role==="moderator"){atitle="Action";awidth=600;if(confMan.params.mainModID){genMainMod($(confMan.params.mainModID));$(confMan.params.displayID).html("Moderator Controls Ready ");}else{$(confMan.params.mainModID).html("");}
+verto.subscribe(confMan.params.laData.modChannel,{handler:function(v,e){if(confMan.params.onBroadcast){confMan.params.onBroadcast(verto,confMan,e.data);}
+if(e.data["conf-command"]==="list-videoLayouts"){for(var j=0;jb)?1:-1));});for(var i in options){$(vlselect_id).append(new Option(options[i],options[i]));x++;}}
+if(x){$(vlselect_id).selectmenu('refresh',true);}else{$(vlayout_id).hide();}}}else{if(!confMan.destroyed&&confMan.params.displayID){$(confMan.params.displayID).html(e.data.response+" ");if(confMan.lastTimeout){clearTimeout(confMan.lastTimeout);confMan.lastTimeout=0;}
+confMan.lastTimeout=setTimeout(function(){$(confMan.params.displayID).html(confMan.destroyed?"":"Moderator Controls Ready ");},4000);}}}});if(confMan.params.hasVid){confMan.modCommand("list-videoLayouts",null,null);}}
+var row_callback=null;if(confMan.params.laData.role==="moderator"){row_callback=function(nRow,aData,iDisplayIndex,iDisplayIndexFull){if(!aData[5]){var $row=$('td:eq(5)',nRow);genControls($row,aData);if(confMan.params.onLaRow){confMan.params.onLaRow(verto,confMan,$row,aData);}}};}
+confMan.lt=new $.verto.liveTable(verto,confMan.params.laData.laChannel,confMan.params.laData.laName,$(confMan.params.tableID),{subParams:{callID:confMan.params.dialog?confMan.params.dialog.callID:null},"onChange":function(obj,args){$(confMan.params.statusID).text("Conference Members: "+" ("+obj.arrayLen()+" Total)");if(confMan.params.onLaChange){confMan.params.onLaChange(verto,confMan,$.verto.enum.confEvent.laChange,obj,args);}},"aaData":[],"aoColumns":[{"sTitle":"ID","sWidth":"50"},{"sTitle":"Number","sWidth":"250"},{"sTitle":"Name","sWidth":"250"},{"sTitle":"Codec","sWidth":"100"},{"sTitle":"Status","sWidth":confMan.params.hasVid?"200px":"150px"},{"sTitle":atitle,"sWidth":awidth,}],"bAutoWidth":true,"bDestroy":true,"bSort":false,"bInfo":false,"bFilter":false,"bLengthChange":false,"bPaginate":false,"iDisplayLength":1400,"oLanguage":{"sEmptyTable":"The Conference is Empty....."},"fnRowCallback":row_callback});};$.verto.confMan.prototype.modCommand=function(cmd,id,value){var confMan=this;confMan.verto.rpcClient.call("verto.broadcast",{"eventChannel":confMan.params.laData.modChannel,"data":{"application":"conf-control","command":cmd,"id":id,"value":value}});};$.verto.confMan.prototype.sendChat=function(message,type){var confMan=this;confMan.verto.rpcClient.call("verto.broadcast",{"eventChannel":confMan.params.laData.chatChannel,"data":{"action":"send","message":message,"type":type}});};$.verto.confMan.prototype.destroy=function(){var confMan=this;confMan.destroyed=true;if(confMan.lt){confMan.lt.destroy();}
+if(confMan.params.laData.chatChannel){confMan.verto.unsubscribe(confMan.params.laData.chatChannel);}
+if(confMan.params.laData.modChannel){confMan.verto.unsubscribe(confMan.params.laData.modChannel);}
+if(confMan.params.mainModID){$(confMan.params.mainModID).html("");}};$.verto.dialog=function(direction,verto,params){var dialog=this;dialog.params=$.extend({useVideo:verto.options.useVideo,useStereo:verto.options.useStereo,screenShare:false,useCamera:false,useMic:verto.options.deviceParams.useMic,useMicLabel:verto.options.deviceParams.useMicLabel,useSpeak:verto.options.deviceParams.useSpeak,tag:verto.options.tag,localTag:verto.options.localTag,login:verto.options.login,videoParams:verto.options.videoParams,useStream:verto.options.useStream,},params);if(!dialog.params.screenShare){dialog.params.useCamera=verto.options.deviceParams.useCamera;dialog.params.useCameraLabel=verto.options.deviceParams.useCameraLabel;}
+dialog.verto=verto;dialog.direction=direction;dialog.lastState=null;dialog.state=dialog.lastState=$.verto.enum.state.new;dialog.callbacks=verto.callbacks;dialog.answered=false;dialog.attach=params.attach||false;dialog.screenShare=params.screenShare||false;dialog.useCamera=dialog.params.useCamera;dialog.useCameraLabel=dialog.params.useCameraLabel;dialog.useMic=dialog.params.useMic;dialog.useMicLabel=dialog.params.useMicLabel;dialog.useSpeak=dialog.params.useSpeak;if(dialog.params.callID){dialog.callID=dialog.params.callID;}else{dialog.callID=dialog.params.callID=generateGUID();}
+if(typeof(dialog.params.tag)==="function"){dialog.params.tag=dialog.params.tag();}
+if(dialog.params.tag){dialog.audioStream=document.getElementById(dialog.params.tag);if(dialog.params.useVideo){dialog.videoStream=dialog.audioStream;}}
+if(dialog.params.localTag){dialog.localVideo=document.getElementById(dialog.params.localTag);}
+dialog.verto.dialogs[dialog.callID]=dialog;var RTCcallbacks={};if(dialog.direction==$.verto.enum.direction.inbound){if(dialog.params.display_direction==="outbound"){dialog.params.remote_caller_id_name=dialog.params.caller_id_name;dialog.params.remote_caller_id_number=dialog.params.caller_id_number;}else{dialog.params.remote_caller_id_name=dialog.params.callee_id_name;dialog.params.remote_caller_id_number=dialog.params.callee_id_number;}
+if(!dialog.params.remote_caller_id_name){dialog.params.remote_caller_id_name="Nobody";}
+if(!dialog.params.remote_caller_id_number){dialog.params.remote_caller_id_number="UNKNOWN";}
+RTCcallbacks.onMessage=function(rtc,msg){console.debug(msg);};RTCcallbacks.onAnswerSDP=function(rtc,sdp){console.error("answer sdp",sdp);};}else{dialog.params.remote_caller_id_name="Outbound Call";dialog.params.remote_caller_id_number=dialog.params.destination_number;}
+RTCcallbacks.onICESDP=function(rtc){console.log("RECV "+rtc.type+" SDP",rtc.mediaData.SDP);if(dialog.state==$.verto.enum.state.requesting||dialog.state==$.verto.enum.state.answering||dialog.state==$.verto.enum.state.active){location.reload();return;}
+if(rtc.type=="offer"){if(dialog.state==$.verto.enum.state.active){dialog.setState($.verto.enum.state.requesting);dialog.sendMethod("verto.attach",{sdp:rtc.mediaData.SDP});}else{dialog.setState($.verto.enum.state.requesting);dialog.sendMethod("verto.invite",{sdp:rtc.mediaData.SDP});}}else{dialog.setState($.verto.enum.state.answering);dialog.sendMethod(dialog.attach?"verto.attach":"verto.answer",{sdp:dialog.rtc.mediaData.SDP});}};RTCcallbacks.onICE=function(rtc){if(rtc.type=="offer"){console.log("offer",rtc.mediaData.candidate);return;}};RTCcallbacks.onStream=function(rtc,stream){if(dialog.callbacks.permissionCallback&&typeof dialog.callbacks.permissionCallback.onGranted==='function'){dialog.callbacks.permissionCallback.onGranted(stream);}
+else if(dialog.verto.options.permissionCallback&&typeof dialog.verto.options.permissionCallback.onGranted==='function'){dialog.verto.options.permissionCallback.onGranted(stream);}
+console.log("stream started");};RTCcallbacks.onRemoteStream=function(rtc,stream){if(typeof dialog.callbacks.onRemoteStream==='function'){dialog.callbacks.onRemoteStream(stream,dialog);}
+console.log("remote stream started");};RTCcallbacks.onError=function(e){if(dialog.callbacks.permissionCallback&&typeof dialog.callbacks.permissionCallback.onDenied==='function'){dialog.callbacks.permissionCallback.onDenied();}
+else if(dialog.verto.options.permissionCallback&&typeof dialog.verto.options.permissionCallback.onDenied==='function'){dialog.verto.options.permissionCallback.onDenied();}
+console.error("ERROR:",e);dialog.hangup({cause:"Device or Permission Error"});};dialog.rtc=new $.FSRTC({callbacks:RTCcallbacks,localVideo:dialog.screenShare?null:dialog.localVideo,useVideo:dialog.params.useVideo?dialog.videoStream:null,useAudio:dialog.audioStream,useStereo:dialog.params.useStereo,videoParams:dialog.params.videoParams,audioParams:verto.options.audioParams,iceServers:verto.options.iceServers,screenShare:dialog.screenShare,useCamera:dialog.useCamera,useCameraLabel:dialog.useCameraLabel,useMic:dialog.useMic,useMicLabel:dialog.useMicLabel,useSpeak:dialog.useSpeak,turnServer:verto.options.turnServer,useStream:dialog.params.useStream});dialog.rtc.verto=dialog.verto;if(dialog.direction==$.verto.enum.direction.inbound){if(dialog.attach){dialog.answer();}else{dialog.ring();}}};$.verto.dialog.prototype.invite=function(){var dialog=this;dialog.rtc.call();};$.verto.dialog.prototype.sendMethod=function(method,obj){var dialog=this;obj.dialogParams={};for(var i in dialog.params){if(i=="sdp"&&method!="verto.invite"&&method!="verto.attach"){continue;}
+if((obj.noDialogParams&&i!="callID")){continue;}
+obj.dialogParams[i]=dialog.params[i];}
+delete obj.noDialogParams;dialog.verto.rpcClient.call(method,obj,function(e){dialog.processReply(method,true,e);},function(e){dialog.processReply(method,false,e);});};function checkStateChange(oldS,newS){if(newS==$.verto.enum.state.purge||$.verto.enum.states[oldS.name][newS.name]){return true;}
+return false;}
+function find_name(id){for(var i in $.verto.audioOutDevices){var source=$.verto.audioOutDevices[i];if(source.id===id){return(source.label);}}
+return id;}
+$.verto.dialog.prototype.setAudioPlaybackDevice=function(sinkId,callback,arg){var dialog=this;var element=dialog.audioStream;if(typeof element.sinkId!=='undefined'){var devname=find_name(sinkId);console.info("Dialog: "+dialog.callID+" Setting speaker:",element,devname);element.setSinkId(sinkId).then(function(){console.log("Dialog: "+dialog.callID+' Success, audio output device attached: '+sinkId);if(callback){callback(true,devname,arg);}}).catch(function(error){var errorMessage=error;if(error.name==='SecurityError'){errorMessage="Dialog: "+dialog.callID+' You need to use HTTPS for selecting audio output '+'device: '+error;}
+if(callback){callback(false,null,arg);}
+console.error(errorMessage);});}else{console.warn("Dialog: "+dialog.callID+' Browser does not support output device selection.');if(callback){callback(false,null,arg);}}}
+$.verto.dialog.prototype.setState=function(state){var dialog=this;if(dialog.state==$.verto.enum.state.ringing){dialog.stopRinging();}
+if(dialog.state==state||!checkStateChange(dialog.state,state)){console.error("Dialog "+dialog.callID+": INVALID state change from "+dialog.state.name+" to "+state.name);dialog.hangup();return false;}
+console.log("Dialog "+dialog.callID+": state change from "+dialog.state.name+" to "+state.name);dialog.lastState=dialog.state;dialog.state=state;if(dialog.callbacks.onDialogState){dialog.callbacks.onDialogState(this);}
+switch(dialog.state){case $.verto.enum.state.early:case $.verto.enum.state.active:var speaker=dialog.useSpeak;console.info("Using Speaker: ",speaker);if(speaker&&speaker!=="any"&&speaker!=="none"){setTimeout(function(){dialog.setAudioPlaybackDevice(speaker);},500);}
+break;case $.verto.enum.state.trying:setTimeout(function(){if(dialog.state==$.verto.enum.state.trying){dialog.setState($.verto.enum.state.hangup);}},30000);break;case $.verto.enum.state.purge:dialog.setState($.verto.enum.state.destroy);break;case $.verto.enum.state.hangup:if(dialog.lastState.val>$.verto.enum.state.requesting.val&&dialog.lastState.val<$.verto.enum.state.hangup.val){dialog.sendMethod("verto.bye",{});}
+dialog.setState($.verto.enum.state.destroy);break;case $.verto.enum.state.destroy:if(typeof(dialog.verto.options.tag)==="function"){$('#'+dialog.params.tag).remove();}
+delete dialog.verto.dialogs[dialog.callID];if(dialog.params.screenShare){dialog.rtc.stopPeer();}else{dialog.rtc.stop();}
+break;}
+return true;};$.verto.dialog.prototype.processReply=function(method,success,e){var dialog=this;switch(method){case"verto.answer":case"verto.attach":if(success){dialog.setState($.verto.enum.state.active);}else{dialog.hangup();}
+break;case"verto.invite":if(success){dialog.setState($.verto.enum.state.trying);}else{dialog.setState($.verto.enum.state.destroy);}
+break;case"verto.bye":dialog.hangup();break;case"verto.modify":if(e.holdState){if(e.holdState=="held"){if(dialog.state!=$.verto.enum.state.held){dialog.setState($.verto.enum.state.held);}}else if(e.holdState=="active"){if(dialog.state!=$.verto.enum.state.active){dialog.setState($.verto.enum.state.active);}}}
+if(success){}
+break;default:break;}};$.verto.dialog.prototype.hangup=function(params){var dialog=this;if(params){if(params.causeCode){dialog.causeCode=params.causeCode;}
+if(params.cause){dialog.cause=params.cause;}}
+if(!dialog.cause&&!dialog.causeCode){dialog.cause="NORMAL_CLEARING";}
+if(dialog.state.val>=$.verto.enum.state.new.val&&dialog.state.val<$.verto.enum.state.hangup.val){dialog.setState($.verto.enum.state.hangup);}else if(dialog.state.val<$.verto.enum.state.destroy){dialog.setState($.verto.enum.state.destroy);}};$.verto.dialog.prototype.stopRinging=function(){var dialog=this;if(dialog.verto.ringer){dialog.verto.ringer.stop();}};$.verto.dialog.prototype.indicateRing=function(){var dialog=this;if(dialog.verto.ringer){dialog.verto.ringer.attr("src",dialog.verto.options.ringFile)[0].play();setTimeout(function(){dialog.stopRinging();if(dialog.state==$.verto.enum.state.ringing){dialog.indicateRing();}},dialog.verto.options.ringSleep);}};$.verto.dialog.prototype.ring=function(){var dialog=this;dialog.setState($.verto.enum.state.ringing);dialog.indicateRing();};$.verto.dialog.prototype.useVideo=function(on){var dialog=this;dialog.params.useVideo=on;if(on){dialog.videoStream=dialog.audioStream;}else{dialog.videoStream=null;}
+dialog.rtc.useVideo(dialog.videoStream,dialog.localVideo);};$.verto.dialog.prototype.setMute=function(what){var dialog=this;return dialog.rtc.setMute(what);};$.verto.dialog.prototype.getMute=function(){var dialog=this;return dialog.rtc.getMute();};$.verto.dialog.prototype.setVideoMute=function(what){var dialog=this;return dialog.rtc.setVideoMute(what);};$.verto.dialog.prototype.getVideoMute=function(){var dialog=this;return dialog.rtc.getVideoMute();};$.verto.dialog.prototype.useStereo=function(on){var dialog=this;dialog.params.useStereo=on;dialog.rtc.useStereo(on);};$.verto.dialog.prototype.dtmf=function(digits){var dialog=this;if(digits){dialog.sendMethod("verto.info",{dtmf:digits});}};$.verto.dialog.prototype.rtt=function(obj){var dialog=this;var pobj={};if(!obj){return false;}
+pobj.code=obj.code;pobj.chars=obj.chars;if(pobj.chars||pobj.code){dialog.sendMethod("verto.info",{txt:obj,noDialogParams:true});}};$.verto.dialog.prototype.transfer=function(dest,params){var dialog=this;if(dest){dialog.sendMethod("verto.modify",{action:"transfer",destination:dest,params:params});}};$.verto.dialog.prototype.replace=function(replaceCallID,params){var dialog=this;if(replaceCallID){dialog.sendMethod("verto.modify",{action:"replace",replaceCallID:replaceCallID,params:params});}};$.verto.dialog.prototype.hold=function(params){var dialog=this;dialog.sendMethod("verto.modify",{action:"hold",params:params});};$.verto.dialog.prototype.unhold=function(params){var dialog=this;dialog.sendMethod("verto.modify",{action:"unhold",params:params});};$.verto.dialog.prototype.toggleHold=function(params){var dialog=this;dialog.sendMethod("verto.modify",{action:"toggleHold",params:params});};$.verto.dialog.prototype.message=function(msg){var dialog=this;var err=0;msg.from=dialog.params.login;if(!msg.to){console.error("Missing To");err++;}
+if(!msg.body){console.error("Missing Body");err++;}
+if(err){return false;}
+dialog.sendMethod("verto.info",{msg:msg});return true;};$.verto.dialog.prototype.answer=function(params){var dialog=this;if(!dialog.answered){if(!params){params={};}
+params.sdp=dialog.params.sdp;if(params){if(params.useVideo){dialog.useVideo(true);}
+dialog.params.callee_id_name=params.callee_id_name;dialog.params.callee_id_number=params.callee_id_number;if(params.useCamera){dialog.useCamera=params.useCamera;dialog.useCameraLabel=params.useCameraLabel;}
+if(params.useMic){dialog.useMic=params.useMic;dialog.useMic=params.useMicLabel;}
+if(params.useSpeak){dialog.useSpeak=params.useSpeak;}}
+dialog.rtc.createAnswer(params);dialog.answered=true;}};$.verto.dialog.prototype.handleAnswer=function(params){var dialog=this;dialog.gotAnswer=true;if(dialog.state.val>=$.verto.enum.state.active.val){return;}
+if(dialog.state.val>=$.verto.enum.state.early.val){dialog.setState($.verto.enum.state.active);}else{if(dialog.gotEarly){console.log("Dialog "+dialog.callID+" Got answer while still establishing early media, delaying...");}else{console.log("Dialog "+dialog.callID+" Answering Channel");dialog.rtc.answer(params.sdp,function(){dialog.setState($.verto.enum.state.active);},function(e){console.error(e);dialog.hangup();});console.log("Dialog "+dialog.callID+"ANSWER SDP",params.sdp);}}};$.verto.dialog.prototype.cidString=function(enc){var dialog=this;var party=dialog.params.remote_caller_id_name+(enc?" <":" <")+dialog.params.remote_caller_id_number+(enc?">":">");return party;};$.verto.dialog.prototype.sendMessage=function(msg,params){var dialog=this;if(dialog.callbacks.onMessage){dialog.callbacks.onMessage(dialog.verto,dialog,msg,params);}};$.verto.dialog.prototype.handleInfo=function(params){var dialog=this;dialog.sendMessage($.verto.enum.message.info,params);};$.verto.dialog.prototype.handleDisplay=function(params){var dialog=this;if(params.display_name){dialog.params.remote_caller_id_name=params.display_name;}
+if(params.display_number){dialog.params.remote_caller_id_number=params.display_number;}
+dialog.sendMessage($.verto.enum.message.display,{});};$.verto.dialog.prototype.handleMedia=function(params){var dialog=this;if(dialog.state.val>=$.verto.enum.state.early.val){return;}
+dialog.gotEarly=true;dialog.rtc.answer(params.sdp,function(){console.log("Dialog "+dialog.callID+"Establishing early media");dialog.setState($.verto.enum.state.early);if(dialog.gotAnswer){console.log("Dialog "+dialog.callID+"Answering Channel");dialog.setState($.verto.enum.state.active);}},function(e){console.error(e);dialog.hangup();});console.log("Dialog "+dialog.callID+"EARLY SDP",params.sdp);};$.verto.ENUM=function(s){var i=0,o={};s.split(" ").map(function(x){o[x]={name:x,val:i++};});return Object.freeze(o);};$.verto.enum={};$.verto.enum.states=Object.freeze({new:{requesting:1,recovering:1,ringing:1,destroy:1,answering:1,hangup:1},requesting:{trying:1,hangup:1,active:1},recovering:{answering:1,hangup:1},trying:{active:1,early:1,hangup:1},ringing:{answering:1,hangup:1},answering:{active:1,hangup:1},active:{answering:1,requesting:1,hangup:1,held:1},held:{hangup:1,active:1},early:{hangup:1,active:1},hangup:{destroy:1},destroy:{},purge:{destroy:1}});$.verto.enum.state=$.verto.ENUM("new requesting trying recovering ringing answering early active held hangup destroy purge");$.verto.enum.direction=$.verto.ENUM("inbound outbound");$.verto.enum.message=$.verto.ENUM("display info pvtEvent clientReady");$.verto.enum=Object.freeze($.verto.enum);$.verto.saved=[];$.verto.unloadJobs=[];var unloadEventName='beforeunload';var iOS=['iPad','iPhone','iPod'].indexOf(navigator.platform)>=0;if(iOS){unloadEventName='pagehide';}
+$(window).bind(unloadEventName,function(){for(var f in $.verto.unloadJobs){$.verto.unloadJobs[f]();}
+if($.verto.haltClosure)
+return $.verto.haltClosure();for(var i in $.verto.saved){var verto=$.verto.saved[i];if(verto){verto.purge();verto.logout();}}
+return $.verto.warnOnUnload;});$.verto.videoDevices=[];$.verto.audioInDevices=[];$.verto.audioOutDevices=[];var checkDevices=function(runtime){console.info("enumerating devices");var aud_in=[],aud_out=[],vid=[];var has_video=0,has_audio=0;var Xstream;function gotDevices(deviceInfos){for(var i=0;i!==deviceInfos.length;++i){var deviceInfo=deviceInfos[i];var text="";console.log(deviceInfo);console.log(deviceInfo.kind+": "+deviceInfo.label+" id = "+deviceInfo.deviceId);if(deviceInfo.kind==='audioinput'){text=deviceInfo.label||'microphone '+(aud_in.length+1);aud_in.push({id:deviceInfo.deviceId,kind:"audio_in",label:text});}else if(deviceInfo.kind==='audiooutput'){text=deviceInfo.label||'speaker '+(aud_out.length+1);aud_out.push({id:deviceInfo.deviceId,kind:"audio_out",label:text});}else if(deviceInfo.kind==='videoinput'){text=deviceInfo.label||'camera '+(vid.length+1);vid.push({id:deviceInfo.deviceId,kind:"video",label:text});}else{console.log('Some other kind of source/device: ',deviceInfo);}}
+$.verto.videoDevices=vid;$.verto.audioInDevices=aud_in;$.verto.audioOutDevices=aud_out;console.info("Audio IN Devices",$.verto.audioInDevices);console.info("Audio Out Devices",$.verto.audioOutDevices);console.info("Video Devices",$.verto.videoDevices);if(Xstream){Xstream.getTracks().forEach(function(track){track.stop();});}
+if(runtime){runtime(true);}}
+function handleError(error){console.log('device enumeration error: ',error);if(runtime)runtime(false);}
+function checkTypes(devs){for(var i=0;i!==devs.length;++i){if(devs[i].kind==='audioinput'){has_audio++;}else if(devs[i].kind==='videoinput'){has_video++;}}
+navigator.getUserMedia({audio:(has_audio>0?true:false),video:(has_video>0?true:false)},function(stream){Xstream=stream;navigator.mediaDevices.enumerateDevices().then(gotDevices).catch(handleError);},function(err){console.log("The following error occurred: "+err.name);});}
+navigator.mediaDevices.enumerateDevices().then(checkTypes).catch(handleError);};$.verto.refreshDevices=function(runtime){checkDevices(runtime);}
+$.verto.init=function(obj,runtime){if(!obj){obj={};}
+if(!obj.skipPermCheck&&!obj.skipDeviceCheck){$.FSRTC.checkPerms(function(status){checkDevices(runtime);},true,true);}else if(obj.skipPermCheck&&!obj.skipDeviceCheck){checkDevices(runtime);}else if(!obj.skipPermCheck&&obj.skipDeviceCheck){$.FSRTC.checkPerms(function(status){runtime(status);},true,true);}else{runtime(null);}}
+$.verto.genUUID=function(){return generateGUID();}})(jQuery);(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.adapter=f()}})(function(){var define,module,exports;return(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i0&&arguments[0]!==undefined?arguments[0]:{},window=_ref.window;var options=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{shimChrome:true,shimFirefox:true,shimEdge:true,shimSafari:true};var logging=utils.log;var browserDetails=utils.detectBrowser(window);var adapter={browserDetails:browserDetails,commonShim:commonShim,extractVersion:utils.extractVersion,disableLog:utils.disableLog,disableWarnings:utils.disableWarnings};switch(browserDetails.browser){case'chrome':if(!chromeShim||!chromeShim.shimPeerConnection||!options.shimChrome){logging('Chrome shim is not included in this adapter release.');return adapter;}
+logging('adapter.js shimming chrome.');adapter.browserShim=chromeShim;chromeShim.shimGetUserMedia(window);chromeShim.shimMediaStream(window);chromeShim.shimPeerConnection(window);chromeShim.shimOnTrack(window);chromeShim.shimAddTrackRemoveTrack(window);chromeShim.shimGetSendersWithDtmf(window);chromeShim.shimSenderReceiverGetStats(window);chromeShim.fixNegotiationNeeded(window);commonShim.shimRTCIceCandidate(window);commonShim.shimConnectionState(window);commonShim.shimMaxMessageSize(window);commonShim.shimSendThrowTypeError(window);commonShim.removeAllowExtmapMixed(window);break;case'firefox':if(!firefoxShim||!firefoxShim.shimPeerConnection||!options.shimFirefox){logging('Firefox shim is not included in this adapter release.');return adapter;}
+logging('adapter.js shimming firefox.');adapter.browserShim=firefoxShim;firefoxShim.shimGetUserMedia(window);firefoxShim.shimPeerConnection(window);firefoxShim.shimOnTrack(window);firefoxShim.shimRemoveStream(window);firefoxShim.shimSenderGetStats(window);firefoxShim.shimReceiverGetStats(window);firefoxShim.shimRTCDataChannel(window);commonShim.shimRTCIceCandidate(window);commonShim.shimConnectionState(window);commonShim.shimMaxMessageSize(window);commonShim.shimSendThrowTypeError(window);break;case'edge':if(!edgeShim||!edgeShim.shimPeerConnection||!options.shimEdge){logging('MS edge shim is not included in this adapter release.');return adapter;}
+logging('adapter.js shimming edge.');adapter.browserShim=edgeShim;edgeShim.shimGetUserMedia(window);edgeShim.shimGetDisplayMedia(window);edgeShim.shimPeerConnection(window);edgeShim.shimReplaceTrack(window);commonShim.shimMaxMessageSize(window);commonShim.shimSendThrowTypeError(window);break;case'safari':if(!safariShim||!options.shimSafari){logging('Safari shim is not included in this adapter release.');return adapter;}
+logging('adapter.js shimming safari.');adapter.browserShim=safariShim;safariShim.shimRTCIceServerUrls(window);safariShim.shimCreateOfferLegacy(window);safariShim.shimCallbacksAPI(window);safariShim.shimLocalStreamsAPI(window);safariShim.shimRemoteStreamsAPI(window);safariShim.shimTrackEventTransceiver(window);safariShim.shimGetUserMedia(window);commonShim.shimRTCIceCandidate(window);commonShim.shimMaxMessageSize(window);commonShim.shimSendThrowTypeError(window);commonShim.removeAllowExtmapMixed(window);break;default:logging('Unsupported browser!');break;}
+return adapter;}},{"./chrome/chrome_shim":3,"./common_shim":6,"./edge/edge_shim":7,"./firefox/firefox_shim":11,"./safari/safari_shim":14,"./utils":15}],3:[function(require,module,exports){'use strict';Object.defineProperty(exports,"__esModule",{value:true});exports.shimGetDisplayMedia=exports.shimGetUserMedia=undefined;var _typeof=typeof Symbol==="function"&&typeof Symbol.iterator==="symbol"?function(obj){return typeof obj;}:function(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj;};var _getusermedia=require('./getusermedia');Object.defineProperty(exports,'shimGetUserMedia',{enumerable:true,get:function get(){return _getusermedia.shimGetUserMedia;}});var _getdisplaymedia=require('./getdisplaymedia');Object.defineProperty(exports,'shimGetDisplayMedia',{enumerable:true,get:function get(){return _getdisplaymedia.shimGetDisplayMedia;}});exports.shimMediaStream=shimMediaStream;exports.shimOnTrack=shimOnTrack;exports.shimGetSendersWithDtmf=shimGetSendersWithDtmf;exports.shimSenderReceiverGetStats=shimSenderReceiverGetStats;exports.shimAddTrackRemoveTrackWithNative=shimAddTrackRemoveTrackWithNative;exports.shimAddTrackRemoveTrack=shimAddTrackRemoveTrack;exports.shimPeerConnection=shimPeerConnection;exports.fixNegotiationNeeded=fixNegotiationNeeded;var _utils=require('../utils.js');var utils=_interopRequireWildcard(_utils);function _interopRequireWildcard(obj){if(obj&&obj.__esModule){return obj;}else{var newObj={};if(obj!=null){for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key))newObj[key]=obj[key];}}newObj.default=obj;return newObj;}}
+function walkStats(stats,base,resultSet){if(!base||resultSet.has(base.id)){return;}
+resultSet.set(base.id,base);Object.keys(base).forEach(function(name){if(name.endsWith('Id')){walkStats(stats,stats.get(base[name]),resultSet);}else if(name.endsWith('Ids')){base[name].forEach(function(id){walkStats(stats,stats.get(id),resultSet);});}});}
+function filterStats(result,track,outbound){var streamStatsType=outbound?'outbound-rtp':'inbound-rtp';var filteredResult=new Map();if(track===null){return filteredResult;}
+var trackStats=[];result.forEach(function(value){if(value.type==='track'&&value.trackIdentifier===track.id){trackStats.push(value);}});trackStats.forEach(function(trackStat){result.forEach(function(stats){if(stats.type===streamStatsType&&stats.trackId===trackStat.id){walkStats(result,stats,filteredResult);}});});return filteredResult;}
+function shimMediaStream(window){window.MediaStream=window.MediaStream||window.webkitMediaStream;}
+function shimOnTrack(window){if((typeof window==='undefined'?'undefined':_typeof(window))==='object'&&window.RTCPeerConnection&&!('ontrack'in window.RTCPeerConnection.prototype)){Object.defineProperty(window.RTCPeerConnection.prototype,'ontrack',{get:function get(){return this._ontrack;},set:function set(f){if(this._ontrack){this.removeEventListener('track',this._ontrack);}
+this.addEventListener('track',this._ontrack=f);},enumerable:true,configurable:true});var origSetRemoteDescription=window.RTCPeerConnection.prototype.setRemoteDescription;window.RTCPeerConnection.prototype.setRemoteDescription=function(){var _this=this;if(!this._ontrackpoly){this._ontrackpoly=function(e){e.stream.addEventListener('addtrack',function(te){var receiver=void 0;if(window.RTCPeerConnection.prototype.getReceivers){receiver=_this.getReceivers().find(function(r){return r.track&&r.track.id===te.track.id;});}else{receiver={track:te.track};}
+var event=new Event('track');event.track=te.track;event.receiver=receiver;event.transceiver={receiver:receiver};event.streams=[e.stream];_this.dispatchEvent(event);});e.stream.getTracks().forEach(function(track){var receiver=void 0;if(window.RTCPeerConnection.prototype.getReceivers){receiver=_this.getReceivers().find(function(r){return r.track&&r.track.id===track.id;});}else{receiver={track:track};}
+var event=new Event('track');event.track=track;event.receiver=receiver;event.transceiver={receiver:receiver};event.streams=[e.stream];_this.dispatchEvent(event);});};this.addEventListener('addstream',this._ontrackpoly);}
+return origSetRemoteDescription.apply(this,arguments);};}else{utils.wrapPeerConnectionEvent(window,'track',function(e){if(!e.transceiver){Object.defineProperty(e,'transceiver',{value:{receiver:e.receiver}});}
+return e;});}}
+function shimGetSendersWithDtmf(window){if((typeof window==='undefined'?'undefined':_typeof(window))==='object'&&window.RTCPeerConnection&&!('getSenders'in window.RTCPeerConnection.prototype)&&'createDTMFSender'in window.RTCPeerConnection.prototype){var shimSenderWithDtmf=function shimSenderWithDtmf(pc,track){return{track:track,get dtmf(){if(this._dtmf===undefined){if(track.kind==='audio'){this._dtmf=pc.createDTMFSender(track);}else{this._dtmf=null;}}
+return this._dtmf;},_pc:pc};};if(!window.RTCPeerConnection.prototype.getSenders){window.RTCPeerConnection.prototype.getSenders=function(){this._senders=this._senders||[];return this._senders.slice();};var origAddTrack=window.RTCPeerConnection.prototype.addTrack;window.RTCPeerConnection.prototype.addTrack=function(track,stream){var sender=origAddTrack.apply(this,arguments);if(!sender){sender=shimSenderWithDtmf(this,track);this._senders.push(sender);}
+return sender;};var origRemoveTrack=window.RTCPeerConnection.prototype.removeTrack;window.RTCPeerConnection.prototype.removeTrack=function(sender){origRemoveTrack.apply(this,arguments);var idx=this._senders.indexOf(sender);if(idx!==-1){this._senders.splice(idx,1);}};}
+var origAddStream=window.RTCPeerConnection.prototype.addStream;window.RTCPeerConnection.prototype.addStream=function(stream){var _this2=this;this._senders=this._senders||[];origAddStream.apply(this,[stream]);stream.getTracks().forEach(function(track){_this2._senders.push(shimSenderWithDtmf(_this2,track));});};var origRemoveStream=window.RTCPeerConnection.prototype.removeStream;window.RTCPeerConnection.prototype.removeStream=function(stream){var _this3=this;this._senders=this._senders||[];origRemoveStream.apply(this,[stream]);stream.getTracks().forEach(function(track){var sender=_this3._senders.find(function(s){return s.track===track;});if(sender){_this3._senders.splice(_this3._senders.indexOf(sender),1);}});};}else if((typeof window==='undefined'?'undefined':_typeof(window))==='object'&&window.RTCPeerConnection&&'getSenders'in window.RTCPeerConnection.prototype&&'createDTMFSender'in window.RTCPeerConnection.prototype&&window.RTCRtpSender&&!('dtmf'in window.RTCRtpSender.prototype)){var origGetSenders=window.RTCPeerConnection.prototype.getSenders;window.RTCPeerConnection.prototype.getSenders=function(){var _this4=this;var senders=origGetSenders.apply(this,[]);senders.forEach(function(sender){return sender._pc=_this4;});return senders;};Object.defineProperty(window.RTCRtpSender.prototype,'dtmf',{get:function get(){if(this._dtmf===undefined){if(this.track.kind==='audio'){this._dtmf=this._pc.createDTMFSender(this.track);}else{this._dtmf=null;}}
+return this._dtmf;}});}}
+function shimSenderReceiverGetStats(window){if(!((typeof window==='undefined'?'undefined':_typeof(window))==='object'&&window.RTCPeerConnection&&window.RTCRtpSender&&window.RTCRtpReceiver)){return;}
+if(!('getStats'in window.RTCRtpSender.prototype)){var origGetSenders=window.RTCPeerConnection.prototype.getSenders;if(origGetSenders){window.RTCPeerConnection.prototype.getSenders=function(){var _this5=this;var senders=origGetSenders.apply(this,[]);senders.forEach(function(sender){return sender._pc=_this5;});return senders;};}
+var origAddTrack=window.RTCPeerConnection.prototype.addTrack;if(origAddTrack){window.RTCPeerConnection.prototype.addTrack=function(){var sender=origAddTrack.apply(this,arguments);sender._pc=this;return sender;};}
+window.RTCRtpSender.prototype.getStats=function(){var sender=this;return this._pc.getStats().then(function(result){return(filterStats(result,sender.track,true));});};}
+if(!('getStats'in window.RTCRtpReceiver.prototype)){var origGetReceivers=window.RTCPeerConnection.prototype.getReceivers;if(origGetReceivers){window.RTCPeerConnection.prototype.getReceivers=function(){var _this6=this;var receivers=origGetReceivers.apply(this,[]);receivers.forEach(function(receiver){return receiver._pc=_this6;});return receivers;};}
+utils.wrapPeerConnectionEvent(window,'track',function(e){e.receiver._pc=e.srcElement;return e;});window.RTCRtpReceiver.prototype.getStats=function(){var receiver=this;return this._pc.getStats().then(function(result){return filterStats(result,receiver.track,false);});};}
+if(!('getStats'in window.RTCRtpSender.prototype&&'getStats'in window.RTCRtpReceiver.prototype)){return;}
+var origGetStats=window.RTCPeerConnection.prototype.getStats;window.RTCPeerConnection.prototype.getStats=function(){if(arguments.length>0&&arguments[0]instanceof window.MediaStreamTrack){var track=arguments[0];var sender=void 0;var receiver=void 0;var err=void 0;this.getSenders().forEach(function(s){if(s.track===track){if(sender){err=true;}else{sender=s;}}});this.getReceivers().forEach(function(r){if(r.track===track){if(receiver){err=true;}else{receiver=r;}}
+return r.track===track;});if(err||sender&&receiver){return Promise.reject(new DOMException('There are more than one sender or receiver for the track.','InvalidAccessError'));}else if(sender){return sender.getStats();}else if(receiver){return receiver.getStats();}
+return Promise.reject(new DOMException('There is no sender or receiver for the track.','InvalidAccessError'));}
+return origGetStats.apply(this,arguments);};}
+function shimAddTrackRemoveTrackWithNative(window){window.RTCPeerConnection.prototype.getLocalStreams=function(){var _this7=this;this._shimmedLocalStreams=this._shimmedLocalStreams||{};return Object.keys(this._shimmedLocalStreams).map(function(streamId){return _this7._shimmedLocalStreams[streamId][0];});};var origAddTrack=window.RTCPeerConnection.prototype.addTrack;window.RTCPeerConnection.prototype.addTrack=function(track,stream){if(!stream){return origAddTrack.apply(this,arguments);}
+this._shimmedLocalStreams=this._shimmedLocalStreams||{};var sender=origAddTrack.apply(this,arguments);if(!this._shimmedLocalStreams[stream.id]){this._shimmedLocalStreams[stream.id]=[stream,sender];}else if(this._shimmedLocalStreams[stream.id].indexOf(sender)===-1){this._shimmedLocalStreams[stream.id].push(sender);}
+return sender;};var origAddStream=window.RTCPeerConnection.prototype.addStream;window.RTCPeerConnection.prototype.addStream=function(stream){var _this8=this;this._shimmedLocalStreams=this._shimmedLocalStreams||{};stream.getTracks().forEach(function(track){var alreadyExists=_this8.getSenders().find(function(s){return s.track===track;});if(alreadyExists){throw new DOMException('Track already exists.','InvalidAccessError');}});var existingSenders=this.getSenders();origAddStream.apply(this,arguments);var newSenders=this.getSenders().filter(function(newSender){return existingSenders.indexOf(newSender)===-1;});this._shimmedLocalStreams[stream.id]=[stream].concat(newSenders);};var origRemoveStream=window.RTCPeerConnection.prototype.removeStream;window.RTCPeerConnection.prototype.removeStream=function(stream){this._shimmedLocalStreams=this._shimmedLocalStreams||{};delete this._shimmedLocalStreams[stream.id];return origRemoveStream.apply(this,arguments);};var origRemoveTrack=window.RTCPeerConnection.prototype.removeTrack;window.RTCPeerConnection.prototype.removeTrack=function(sender){var _this9=this;this._shimmedLocalStreams=this._shimmedLocalStreams||{};if(sender){Object.keys(this._shimmedLocalStreams).forEach(function(streamId){var idx=_this9._shimmedLocalStreams[streamId].indexOf(sender);if(idx!==-1){_this9._shimmedLocalStreams[streamId].splice(idx,1);}
+if(_this9._shimmedLocalStreams[streamId].length===1){delete _this9._shimmedLocalStreams[streamId];}});}
+return origRemoveTrack.apply(this,arguments);};}
+function shimAddTrackRemoveTrack(window){if(!window.RTCPeerConnection){return;}
+var browserDetails=utils.detectBrowser(window);if(window.RTCPeerConnection.prototype.addTrack&&browserDetails.version>=65){return shimAddTrackRemoveTrackWithNative(window);}
+var origGetLocalStreams=window.RTCPeerConnection.prototype.getLocalStreams;window.RTCPeerConnection.prototype.getLocalStreams=function(){var _this10=this;var nativeStreams=origGetLocalStreams.apply(this);this._reverseStreams=this._reverseStreams||{};return nativeStreams.map(function(stream){return _this10._reverseStreams[stream.id];});};var origAddStream=window.RTCPeerConnection.prototype.addStream;window.RTCPeerConnection.prototype.addStream=function(stream){var _this11=this;this._streams=this._streams||{};this._reverseStreams=this._reverseStreams||{};stream.getTracks().forEach(function(track){var alreadyExists=_this11.getSenders().find(function(s){return s.track===track;});if(alreadyExists){throw new DOMException('Track already exists.','InvalidAccessError');}});if(!this._reverseStreams[stream.id]){var newStream=new window.MediaStream(stream.getTracks());this._streams[stream.id]=newStream;this._reverseStreams[newStream.id]=stream;stream=newStream;}
+origAddStream.apply(this,[stream]);};var origRemoveStream=window.RTCPeerConnection.prototype.removeStream;window.RTCPeerConnection.prototype.removeStream=function(stream){this._streams=this._streams||{};this._reverseStreams=this._reverseStreams||{};origRemoveStream.apply(this,[this._streams[stream.id]||stream]);delete this._reverseStreams[this._streams[stream.id]?this._streams[stream.id].id:stream.id];delete this._streams[stream.id];};window.RTCPeerConnection.prototype.addTrack=function(track,stream){var _this12=this;if(this.signalingState==='closed'){throw new DOMException('The RTCPeerConnection\'s signalingState is \'closed\'.','InvalidStateError');}
+var streams=[].slice.call(arguments,1);if(streams.length!==1||!streams[0].getTracks().find(function(t){return t===track;})){throw new DOMException('The adapter.js addTrack polyfill only supports a single '+' stream which is associated with the specified track.','NotSupportedError');}
+var alreadyExists=this.getSenders().find(function(s){return s.track===track;});if(alreadyExists){throw new DOMException('Track already exists.','InvalidAccessError');}
+this._streams=this._streams||{};this._reverseStreams=this._reverseStreams||{};var oldStream=this._streams[stream.id];if(oldStream){oldStream.addTrack(track);Promise.resolve().then(function(){_this12.dispatchEvent(new Event('negotiationneeded'));});}else{var newStream=new window.MediaStream([track]);this._streams[stream.id]=newStream;this._reverseStreams[newStream.id]=stream;this.addStream(newStream);}
+return this.getSenders().find(function(s){return s.track===track;});};function replaceInternalStreamId(pc,description){var sdp=description.sdp;Object.keys(pc._reverseStreams||[]).forEach(function(internalId){var externalStream=pc._reverseStreams[internalId];var internalStream=pc._streams[externalStream.id];sdp=sdp.replace(new RegExp(internalStream.id,'g'),externalStream.id);});return new RTCSessionDescription({type:description.type,sdp:sdp});}
+function replaceExternalStreamId(pc,description){var sdp=description.sdp;Object.keys(pc._reverseStreams||[]).forEach(function(internalId){var externalStream=pc._reverseStreams[internalId];var internalStream=pc._streams[externalStream.id];sdp=sdp.replace(new RegExp(externalStream.id,'g'),internalStream.id);});return new RTCSessionDescription({type:description.type,sdp:sdp});}
+['createOffer','createAnswer'].forEach(function(method){var nativeMethod=window.RTCPeerConnection.prototype[method];window.RTCPeerConnection.prototype[method]=function(){var _this13=this;var args=arguments;var isLegacyCall=arguments.length&&typeof arguments[0]==='function';if(isLegacyCall){return nativeMethod.apply(this,[function(description){var desc=replaceInternalStreamId(_this13,description);args[0].apply(null,[desc]);},function(err){if(args[1]){args[1].apply(null,err);}},arguments[2]]);}
+return nativeMethod.apply(this,arguments).then(function(description){return replaceInternalStreamId(_this13,description);});};});var origSetLocalDescription=window.RTCPeerConnection.prototype.setLocalDescription;window.RTCPeerConnection.prototype.setLocalDescription=function(){if(!arguments.length||!arguments[0].type){return origSetLocalDescription.apply(this,arguments);}
+arguments[0]=replaceExternalStreamId(this,arguments[0]);return origSetLocalDescription.apply(this,arguments);};var origLocalDescription=Object.getOwnPropertyDescriptor(window.RTCPeerConnection.prototype,'localDescription');Object.defineProperty(window.RTCPeerConnection.prototype,'localDescription',{get:function get(){var description=origLocalDescription.get.apply(this);if(description.type===''){return description;}
+return replaceInternalStreamId(this,description);}});window.RTCPeerConnection.prototype.removeTrack=function(sender){var _this14=this;if(this.signalingState==='closed'){throw new DOMException('The RTCPeerConnection\'s signalingState is \'closed\'.','InvalidStateError');}
+if(!sender._pc){throw new DOMException('Argument 1 of RTCPeerConnection.removeTrack '+'does not implement interface RTCRtpSender.','TypeError');}
+var isLocal=sender._pc===this;if(!isLocal){throw new DOMException('Sender was not created by this connection.','InvalidAccessError');}
+this._streams=this._streams||{};var stream=void 0;Object.keys(this._streams).forEach(function(streamid){var hasTrack=_this14._streams[streamid].getTracks().find(function(track){return sender.track===track;});if(hasTrack){stream=_this14._streams[streamid];}});if(stream){if(stream.getTracks().length===1){this.removeStream(this._reverseStreams[stream.id]);}else{stream.removeTrack(sender.track);}
+this.dispatchEvent(new Event('negotiationneeded'));}};}
+function shimPeerConnection(window){if(!window.RTCPeerConnection&&window.webkitRTCPeerConnection){window.RTCPeerConnection=window.webkitRTCPeerConnection;}
+if(!window.RTCPeerConnection){return;}
+var origGetStats=window.RTCPeerConnection.prototype.getStats;window.RTCPeerConnection.prototype.getStats=function(selector,successCallback,errorCallback){var _this15=this;var args=arguments;if(arguments.length>0&&typeof selector==='function'){return origGetStats.apply(this,arguments);}
+if(origGetStats.length===0&&(arguments.length===0||typeof arguments[0]!=='function')){return origGetStats.apply(this,[]);}
+var fixChromeStats_=function fixChromeStats_(response){var standardReport={};var reports=response.result();reports.forEach(function(report){var standardStats={id:report.id,timestamp:report.timestamp,type:{localcandidate:'local-candidate',remotecandidate:'remote-candidate'}[report.type]||report.type};report.names().forEach(function(name){standardStats[name]=report.stat(name);});standardReport[standardStats.id]=standardStats;});return standardReport;};var makeMapStats=function makeMapStats(stats){return new Map(Object.keys(stats).map(function(key){return[key,stats[key]];}));};if(arguments.length>=2){var successCallbackWrapper_=function successCallbackWrapper_(response){args[1](makeMapStats(fixChromeStats_(response)));};return origGetStats.apply(this,[successCallbackWrapper_,arguments[0]]);}
+return new Promise(function(resolve,reject){origGetStats.apply(_this15,[function(response){resolve(makeMapStats(fixChromeStats_(response)));},reject]);}).then(successCallback,errorCallback);};['setLocalDescription','setRemoteDescription','addIceCandidate'].forEach(function(method){var nativeMethod=window.RTCPeerConnection.prototype[method];window.RTCPeerConnection.prototype[method]=function(){arguments[0]=new(method==='addIceCandidate'?window.RTCIceCandidate:window.RTCSessionDescription)(arguments[0]);return nativeMethod.apply(this,arguments);};});var nativeAddIceCandidate=window.RTCPeerConnection.prototype.addIceCandidate;window.RTCPeerConnection.prototype.addIceCandidate=function(){if(!arguments[0]){if(arguments[1]){arguments[1].apply(null);}
+return Promise.resolve();}
+return nativeAddIceCandidate.apply(this,arguments);};}
+function fixNegotiationNeeded(window){utils.wrapPeerConnectionEvent(window,'negotiationneeded',function(e){var pc=e.target;if(pc.signalingState!=='stable'){return;}
+return e;});}},{"../utils.js":15,"./getdisplaymedia":4,"./getusermedia":5}],4:[function(require,module,exports){'use strict';Object.defineProperty(exports,"__esModule",{value:true});exports.shimGetDisplayMedia=shimGetDisplayMedia;function shimGetDisplayMedia(window,getSourceId){if(window.navigator.mediaDevices&&'getDisplayMedia'in window.navigator.mediaDevices){return;}
+if(!window.navigator.mediaDevices){return;}
+if(typeof getSourceId!=='function'){console.error('shimGetDisplayMedia: getSourceId argument is not '+'a function');return;}
+window.navigator.mediaDevices.getDisplayMedia=function(constraints){return getSourceId(constraints).then(function(sourceId){var widthSpecified=constraints.video&&constraints.video.width;var heightSpecified=constraints.video&&constraints.video.height;var frameRateSpecified=constraints.video&&constraints.video.frameRate;constraints.video={mandatory:{chromeMediaSource:'desktop',chromeMediaSourceId:sourceId,maxFrameRate:frameRateSpecified||3}};if(widthSpecified){constraints.video.mandatory.maxWidth=widthSpecified;}
+if(heightSpecified){constraints.video.mandatory.maxHeight=heightSpecified;}
+return window.navigator.mediaDevices.getUserMedia(constraints);});};}},{}],5:[function(require,module,exports){'use strict';Object.defineProperty(exports,"__esModule",{value:true});var _typeof=typeof Symbol==="function"&&typeof Symbol.iterator==="symbol"?function(obj){return typeof obj;}:function(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj;};exports.shimGetUserMedia=shimGetUserMedia;var _utils=require('../utils.js');var utils=_interopRequireWildcard(_utils);function _interopRequireWildcard(obj){if(obj&&obj.__esModule){return obj;}else{var newObj={};if(obj!=null){for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key))newObj[key]=obj[key];}}newObj.default=obj;return newObj;}}
+var logging=utils.log;function shimGetUserMedia(window){var navigator=window&&window.navigator;if(!navigator.mediaDevices){return;}
+var browserDetails=utils.detectBrowser(window);var constraintsToChrome_=function constraintsToChrome_(c){if((typeof c==='undefined'?'undefined':_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 oldname_(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;};var shimConstraints_=function shimConstraints_(constraints,func){if(browserDetails.version>=61){return func(constraints);}
+constraints=JSON.parse(JSON.stringify(constraints));if(constraints&&_typeof(constraints.audio)==='object'){var remap=function remap(obj,a,b){if(a in obj&&!(b in obj)){obj[b]=obj[a];delete obj[a];}};constraints=JSON.parse(JSON.stringify(constraints));remap(constraints.audio,'autoGainControl','googAutoGainControl');remap(constraints.audio,'noiseSuppression','googNoiseSuppression');constraints.audio=constraintsToChrome_(constraints.audio);}
+if(constraints&&_typeof(constraints.video)==='object'){var face=constraints.video.facingMode;face=face&&((typeof face==='undefined'?'undefined':_typeof(face))==='object'?face:{ideal:face});var getSupportedFacingModeLies=browserDetails.version<66;if(face&&(face.exact==='user'||face.exact==='environment'||face.ideal==='user'||face.ideal==='environment')&&!(navigator.mediaDevices.getSupportedConstraints&&navigator.mediaDevices.getSupportedConstraints().facingMode&&!getSupportedFacingModeLies)){delete constraints.video.facingMode;var matches=void 0;if(face.exact==='environment'||face.ideal==='environment'){matches=['back','rear'];}else if(face.exact==='user'||face.ideal==='user'){matches=['front'];}
+if(matches){return navigator.mediaDevices.enumerateDevices().then(function(devices){devices=devices.filter(function(d){return d.kind==='videoinput';});var dev=devices.find(function(d){return matches.some(function(match){return d.label.toLowerCase().includes(match);});});if(!dev&&devices.length&&matches.includes('back')){dev=devices[devices.length-1];}
+if(dev){constraints.video.deviceId=face.exact?{exact:dev.deviceId}:{ideal:dev.deviceId};}
+constraints.video=constraintsToChrome_(constraints.video);logging('chrome: '+JSON.stringify(constraints));return func(constraints);});}}
+constraints.video=constraintsToChrome_(constraints.video);}
+logging('chrome: '+JSON.stringify(constraints));return func(constraints);};var shimError_=function shimError_(e){if(browserDetails.version>=64){return e;}
+return{name:{PermissionDeniedError:'NotAllowedError',PermissionDismissedError:'NotAllowedError',InvalidStateError:'NotAllowedError',DevicesNotFoundError:'NotFoundError',ConstraintNotSatisfiedError:'OverconstrainedError',TrackStartError:'NotReadableError',MediaDeviceFailedDueToShutdown:'NotAllowedError',MediaDeviceKillSwitchOn:'NotAllowedError',TabCaptureError:'AbortError',ScreenCaptureError:'AbortError',DeviceCaptureError:'AbortError'}[e.name]||e.name,message:e.message,constraint:e.constraint||e.constraintName,toString:function toString(){return this.name+(this.message&&': ')+this.message;}};};var getUserMedia_=function getUserMedia_(constraints,onSuccess,onError){shimConstraints_(constraints,function(c){navigator.webkitGetUserMedia(c,onSuccess,function(e){if(onError){onError(shimError_(e));}});});};navigator.getUserMedia=getUserMedia_.bind(navigator);var origGetUserMedia=navigator.mediaDevices.getUserMedia.bind(navigator.mediaDevices);navigator.mediaDevices.getUserMedia=function(cs){return shimConstraints_(cs,function(c){return origGetUserMedia(c).then(function(stream){if(c.audio&&!stream.getAudioTracks().length||c.video&&!stream.getVideoTracks().length){stream.getTracks().forEach(function(track){track.stop();});throw new DOMException('','NotFoundError');}
+return stream;},function(e){return Promise.reject(shimError_(e));});});};}},{"../utils.js":15}],6:[function(require,module,exports){'use strict';Object.defineProperty(exports,"__esModule",{value:true});var _typeof=typeof Symbol==="function"&&typeof Symbol.iterator==="symbol"?function(obj){return typeof obj;}:function(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj;};exports.shimRTCIceCandidate=shimRTCIceCandidate;exports.shimMaxMessageSize=shimMaxMessageSize;exports.shimSendThrowTypeError=shimSendThrowTypeError;exports.shimConnectionState=shimConnectionState;exports.removeAllowExtmapMixed=removeAllowExtmapMixed;var _sdp=require('sdp');var _sdp2=_interopRequireDefault(_sdp);var _utils=require('./utils');var utils=_interopRequireWildcard(_utils);function _interopRequireWildcard(obj){if(obj&&obj.__esModule){return obj;}else{var newObj={};if(obj!=null){for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key))newObj[key]=obj[key];}}newObj.default=obj;return newObj;}}
+function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj};}
+function shimRTCIceCandidate(window){if(!window.RTCIceCandidate||window.RTCIceCandidate&&'foundation'in window.RTCIceCandidate.prototype){return;}
+var NativeRTCIceCandidate=window.RTCIceCandidate;window.RTCIceCandidate=function(args){if((typeof args==='undefined'?'undefined':_typeof(args))==='object'&&args.candidate&&args.candidate.indexOf('a=')===0){args=JSON.parse(JSON.stringify(args));args.candidate=args.candidate.substr(2);}
+if(args.candidate&&args.candidate.length){var nativeCandidate=new NativeRTCIceCandidate(args);var parsedCandidate=_sdp2.default.parseCandidate(args.candidate);var augmentedCandidate=Object.assign(nativeCandidate,parsedCandidate);augmentedCandidate.toJSON=function(){return{candidate:augmentedCandidate.candidate,sdpMid:augmentedCandidate.sdpMid,sdpMLineIndex:augmentedCandidate.sdpMLineIndex,usernameFragment:augmentedCandidate.usernameFragment};};return augmentedCandidate;}
+return new NativeRTCIceCandidate(args);};window.RTCIceCandidate.prototype=NativeRTCIceCandidate.prototype;utils.wrapPeerConnectionEvent(window,'icecandidate',function(e){if(e.candidate){Object.defineProperty(e,'candidate',{value:new window.RTCIceCandidate(e.candidate),writable:'false'});}
+return e;});}
+function shimMaxMessageSize(window){if(window.RTCSctpTransport||!window.RTCPeerConnection){return;}
+var browserDetails=utils.detectBrowser(window);if(!('sctp'in window.RTCPeerConnection.prototype)){Object.defineProperty(window.RTCPeerConnection.prototype,'sctp',{get:function get(){return typeof this._sctp==='undefined'?null:this._sctp;}});}
+var sctpInDescription=function sctpInDescription(description){var sections=_sdp2.default.splitSections(description.sdp);sections.shift();return sections.some(function(mediaSection){var mLine=_sdp2.default.parseMLine(mediaSection);return mLine&&mLine.kind==='application'&&mLine.protocol.indexOf('SCTP')!==-1;});};var getRemoteFirefoxVersion=function getRemoteFirefoxVersion(description){var match=description.sdp.match(/mozilla...THIS_IS_SDPARTA-(\d+)/);if(match===null||match.length<2){return-1;}
+var version=parseInt(match[1],10);return version!==version?-1:version;};var getCanSendMaxMessageSize=function getCanSendMaxMessageSize(remoteIsFirefox){var canSendMaxMessageSize=65536;if(browserDetails.browser==='firefox'){if(browserDetails.version<57){if(remoteIsFirefox===-1){canSendMaxMessageSize=16384;}else{canSendMaxMessageSize=2147483637;}}else if(browserDetails.version<60){canSendMaxMessageSize=browserDetails.version===57?65535:65536;}else{canSendMaxMessageSize=2147483637;}}
+return canSendMaxMessageSize;};var getMaxMessageSize=function getMaxMessageSize(description,remoteIsFirefox){var maxMessageSize=65536;if(browserDetails.browser==='firefox'&&browserDetails.version===57){maxMessageSize=65535;}
+var match=_sdp2.default.matchPrefix(description.sdp,'a=max-message-size:');if(match.length>0){maxMessageSize=parseInt(match[0].substr(19),10);}else if(browserDetails.browser==='firefox'&&remoteIsFirefox!==-1){maxMessageSize=2147483637;}
+return maxMessageSize;};var origSetRemoteDescription=window.RTCPeerConnection.prototype.setRemoteDescription;window.RTCPeerConnection.prototype.setRemoteDescription=function(){this._sctp=null;if(sctpInDescription(arguments[0])){var isFirefox=getRemoteFirefoxVersion(arguments[0]);var canSendMMS=getCanSendMaxMessageSize(isFirefox);var remoteMMS=getMaxMessageSize(arguments[0],isFirefox);var maxMessageSize=void 0;if(canSendMMS===0&&remoteMMS===0){maxMessageSize=Number.POSITIVE_INFINITY;}else if(canSendMMS===0||remoteMMS===0){maxMessageSize=Math.max(canSendMMS,remoteMMS);}else{maxMessageSize=Math.min(canSendMMS,remoteMMS);}
+var sctp={};Object.defineProperty(sctp,'maxMessageSize',{get:function get(){return maxMessageSize;}});this._sctp=sctp;}
+return origSetRemoteDescription.apply(this,arguments);};}
+function shimSendThrowTypeError(window){if(!(window.RTCPeerConnection&&'createDataChannel'in window.RTCPeerConnection.prototype)){return;}
+function wrapDcSend(dc,pc){var origDataChannelSend=dc.send;dc.send=function(){var data=arguments[0];var length=data.length||data.size||data.byteLength;if(dc.readyState==='open'&&pc.sctp&&length>pc.sctp.maxMessageSize){throw new TypeError('Message too large (can send a maximum of '+pc.sctp.maxMessageSize+' bytes)');}
+return origDataChannelSend.apply(dc,arguments);};}
+var origCreateDataChannel=window.RTCPeerConnection.prototype.createDataChannel;window.RTCPeerConnection.prototype.createDataChannel=function(){var dataChannel=origCreateDataChannel.apply(this,arguments);wrapDcSend(dataChannel,this);return dataChannel;};utils.wrapPeerConnectionEvent(window,'datachannel',function(e){wrapDcSend(e.channel,e.target);return e;});}
+function shimConnectionState(window){if(!window.RTCPeerConnection||'connectionState'in window.RTCPeerConnection.prototype){return;}
+var proto=window.RTCPeerConnection.prototype;Object.defineProperty(proto,'connectionState',{get:function get(){return{completed:'connected',checking:'connecting'}[this.iceConnectionState]||this.iceConnectionState;},enumerable:true,configurable:true});Object.defineProperty(proto,'onconnectionstatechange',{get:function get(){return this._onconnectionstatechange||null;},set:function set(cb){if(this._onconnectionstatechange){this.removeEventListener('connectionstatechange',this._onconnectionstatechange);delete this._onconnectionstatechange;}
+if(cb){this.addEventListener('connectionstatechange',this._onconnectionstatechange=cb);}},enumerable:true,configurable:true});['setLocalDescription','setRemoteDescription'].forEach(function(method){var origMethod=proto[method];proto[method]=function(){if(!this._connectionstatechangepoly){this._connectionstatechangepoly=function(e){var pc=e.target;if(pc._lastConnectionState!==pc.connectionState){pc._lastConnectionState=pc.connectionState;var newEvent=new Event('connectionstatechange',e);pc.dispatchEvent(newEvent);}
+return e;};this.addEventListener('iceconnectionstatechange',this._connectionstatechangepoly);}
+return origMethod.apply(this,arguments);};});}
+function removeAllowExtmapMixed(window){if(!window.RTCPeerConnection){return;}
+var browserDetails=utils.detectBrowser(window);if(browserDetails.browser==='chrome'&&browserDetails.version>=71){return;}
+var nativeSRD=window.RTCPeerConnection.prototype.setRemoteDescription;window.RTCPeerConnection.prototype.setRemoteDescription=function(desc){if(desc&&desc.sdp&&desc.sdp.indexOf('\na=extmap-allow-mixed')!==-1){desc.sdp=desc.sdp.split('\n').filter(function(line){return line.trim()!=='a=extmap-allow-mixed';}).join('\n');}
+return nativeSRD.apply(this,arguments);};}},{"./utils":15,"sdp":17}],7:[function(require,module,exports){'use strict';Object.defineProperty(exports,"__esModule",{value:true});exports.shimGetDisplayMedia=exports.shimGetUserMedia=undefined;var _getusermedia=require('./getusermedia');Object.defineProperty(exports,'shimGetUserMedia',{enumerable:true,get:function get(){return _getusermedia.shimGetUserMedia;}});var _getdisplaymedia=require('./getdisplaymedia');Object.defineProperty(exports,'shimGetDisplayMedia',{enumerable:true,get:function get(){return _getdisplaymedia.shimGetDisplayMedia;}});exports.shimPeerConnection=shimPeerConnection;exports.shimReplaceTrack=shimReplaceTrack;var _utils=require('../utils');var utils=_interopRequireWildcard(_utils);var _filtericeservers=require('./filtericeservers');var _rtcpeerconnectionShim=require('rtcpeerconnection-shim');var _rtcpeerconnectionShim2=_interopRequireDefault(_rtcpeerconnectionShim);function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj};}
+function _interopRequireWildcard(obj){if(obj&&obj.__esModule){return obj;}else{var newObj={};if(obj!=null){for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key))newObj[key]=obj[key];}}newObj.default=obj;return newObj;}}
+function shimPeerConnection(window){var browserDetails=utils.detectBrowser(window);if(window.RTCIceGatherer){if(!window.RTCIceCandidate){window.RTCIceCandidate=function(args){return args;};}
+if(!window.RTCSessionDescription){window.RTCSessionDescription=function(args){return args;};}
+if(browserDetails.version<15025){var origMSTEnabled=Object.getOwnPropertyDescriptor(window.MediaStreamTrack.prototype,'enabled');Object.defineProperty(window.MediaStreamTrack.prototype,'enabled',{set:function set(value){origMSTEnabled.set.call(this,value);var ev=new Event('enabled');ev.enabled=value;this.dispatchEvent(ev);}});}}
+if(window.RTCRtpSender&&!('dtmf'in window.RTCRtpSender.prototype)){Object.defineProperty(window.RTCRtpSender.prototype,'dtmf',{get:function get(){if(this._dtmf===undefined){if(this.track.kind==='audio'){this._dtmf=new window.RTCDtmfSender(this);}else if(this.track.kind==='video'){this._dtmf=null;}}
+return this._dtmf;}});}
+if(window.RTCDtmfSender&&!window.RTCDTMFSender){window.RTCDTMFSender=window.RTCDtmfSender;}
+var RTCPeerConnectionShim=(0,_rtcpeerconnectionShim2.default)(window,browserDetails.version);window.RTCPeerConnection=function(config){if(config&&config.iceServers){config.iceServers=(0,_filtericeservers.filterIceServers)(config.iceServers,browserDetails.version);utils.log('ICE servers after filtering:',config.iceServers);}
+return new RTCPeerConnectionShim(config);};window.RTCPeerConnection.prototype=RTCPeerConnectionShim.prototype;}
+function shimReplaceTrack(window){if(window.RTCRtpSender&&!('replaceTrack'in window.RTCRtpSender.prototype)){window.RTCRtpSender.prototype.replaceTrack=window.RTCRtpSender.prototype.setTrack;}}},{"../utils":15,"./filtericeservers":8,"./getdisplaymedia":9,"./getusermedia":10,"rtcpeerconnection-shim":16}],8:[function(require,module,exports){'use strict';Object.defineProperty(exports,"__esModule",{value:true});exports.filterIceServers=filterIceServers;var _utils=require('../utils');var utils=_interopRequireWildcard(_utils);function _interopRequireWildcard(obj){if(obj&&obj.__esModule){return obj;}else{var newObj={};if(obj!=null){for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key))newObj[key]=obj[key];}}newObj.default=obj;return newObj;}}
+function filterIceServers(iceServers,edgeVersion){var hasTurn=false;iceServers=JSON.parse(JSON.stringify(iceServers));return iceServers.filter(function(server){if(server&&(server.urls||server.url)){var urls=server.urls||server.url;if(server.url&&!server.urls){utils.deprecated('RTCIceServer.url','RTCIceServer.urls');}
+var isString=typeof urls==='string';if(isString){urls=[urls];}
+urls=urls.filter(function(url){if(url.indexOf('stun:')===0){return false;}
+var validTurn=url.startsWith('turn')&&!url.startsWith('turn:[')&&url.includes('transport=udp');if(validTurn&&!hasTurn){hasTurn=true;return true;}
+return validTurn&&!hasTurn;});delete server.url;server.urls=isString?urls[0]:urls;return!!urls.length;}});}},{"../utils":15}],9:[function(require,module,exports){'use strict';Object.defineProperty(exports,"__esModule",{value:true});exports.shimGetDisplayMedia=shimGetDisplayMedia;function shimGetDisplayMedia(window){if(!('getDisplayMedia'in window.navigator)){return;}
+if(!window.navigator.mediaDevices){return;}
+if(window.navigator.mediaDevices&&'getDisplayMedia'in window.navigator.mediaDevices){return;}
+window.navigator.mediaDevices.getDisplayMedia=window.navigator.getDisplayMedia.bind(window.navigator.mediaDevices);}},{}],10:[function(require,module,exports){'use strict';Object.defineProperty(exports,"__esModule",{value:true});exports.shimGetUserMedia=shimGetUserMedia;function shimGetUserMedia(window){var navigator=window&&window.navigator;var shimError_=function shimError_(e){return{name:{PermissionDeniedError:'NotAllowedError'}[e.name]||e.name,message:e.message,constraint:e.constraint,toString:function toString(){return this.name;}};};var origGetUserMedia=navigator.mediaDevices.getUserMedia.bind(navigator.mediaDevices);navigator.mediaDevices.getUserMedia=function(c){return origGetUserMedia(c).catch(function(e){return Promise.reject(shimError_(e));});};}},{}],11:[function(require,module,exports){'use strict';Object.defineProperty(exports,"__esModule",{value:true});exports.shimGetDisplayMedia=exports.shimGetUserMedia=undefined;var _typeof=typeof Symbol==="function"&&typeof Symbol.iterator==="symbol"?function(obj){return typeof obj;}:function(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj;};var _getusermedia=require('./getusermedia');Object.defineProperty(exports,'shimGetUserMedia',{enumerable:true,get:function get(){return _getusermedia.shimGetUserMedia;}});var _getdisplaymedia=require('./getdisplaymedia');Object.defineProperty(exports,'shimGetDisplayMedia',{enumerable:true,get:function get(){return _getdisplaymedia.shimGetDisplayMedia;}});exports.shimOnTrack=shimOnTrack;exports.shimPeerConnection=shimPeerConnection;exports.shimSenderGetStats=shimSenderGetStats;exports.shimReceiverGetStats=shimReceiverGetStats;exports.shimRemoveStream=shimRemoveStream;exports.shimRTCDataChannel=shimRTCDataChannel;var _utils=require('../utils');var utils=_interopRequireWildcard(_utils);function _interopRequireWildcard(obj){if(obj&&obj.__esModule){return obj;}else{var newObj={};if(obj!=null){for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key))newObj[key]=obj[key];}}newObj.default=obj;return newObj;}}
+function shimOnTrack(window){if((typeof window==='undefined'?'undefined':_typeof(window))==='object'&&window.RTCTrackEvent&&'receiver'in window.RTCTrackEvent.prototype&&!('transceiver'in window.RTCTrackEvent.prototype)){Object.defineProperty(window.RTCTrackEvent.prototype,'transceiver',{get:function get(){return{receiver:this.receiver};}});}}
+function shimPeerConnection(window){var browserDetails=utils.detectBrowser(window);if((typeof window==='undefined'?'undefined':_typeof(window))!=='object'||!(window.RTCPeerConnection||window.mozRTCPeerConnection)){return;}
+if(!window.RTCPeerConnection&&window.mozRTCPeerConnection){window.RTCPeerConnection=window.mozRTCPeerConnection;}
+['setLocalDescription','setRemoteDescription','addIceCandidate'].forEach(function(method){var nativeMethod=window.RTCPeerConnection.prototype[method];window.RTCPeerConnection.prototype[method]=function(){arguments[0]=new(method==='addIceCandidate'?window.RTCIceCandidate:window.RTCSessionDescription)(arguments[0]);return nativeMethod.apply(this,arguments);};});var nativeAddIceCandidate=window.RTCPeerConnection.prototype.addIceCandidate;window.RTCPeerConnection.prototype.addIceCandidate=function(){if(!arguments[0]){if(arguments[1]){arguments[1].apply(null);}
+return Promise.resolve();}
+return nativeAddIceCandidate.apply(this,arguments);};var modernStatsTypes={inboundrtp:'inbound-rtp',outboundrtp:'outbound-rtp',candidatepair:'candidate-pair',localcandidate:'local-candidate',remotecandidate:'remote-candidate'};var nativeGetStats=window.RTCPeerConnection.prototype.getStats;window.RTCPeerConnection.prototype.getStats=function(selector,onSucc,onErr){return nativeGetStats.apply(this,[selector||null]).then(function(stats){if(browserDetails.version<53&&!onSucc){try{stats.forEach(function(stat){stat.type=modernStatsTypes[stat.type]||stat.type;});}catch(e){if(e.name!=='TypeError'){throw e;}
+stats.forEach(function(stat,i){stats.set(i,Object.assign({},stat,{type:modernStatsTypes[stat.type]||stat.type}));});}}
+return stats;}).then(onSucc,onErr);};}
+function shimSenderGetStats(window){if(!((typeof window==='undefined'?'undefined':_typeof(window))==='object'&&window.RTCPeerConnection&&window.RTCRtpSender)){return;}
+if(window.RTCRtpSender&&'getStats'in window.RTCRtpSender.prototype){return;}
+var origGetSenders=window.RTCPeerConnection.prototype.getSenders;if(origGetSenders){window.RTCPeerConnection.prototype.getSenders=function(){var _this=this;var senders=origGetSenders.apply(this,[]);senders.forEach(function(sender){return sender._pc=_this;});return senders;};}
+var origAddTrack=window.RTCPeerConnection.prototype.addTrack;if(origAddTrack){window.RTCPeerConnection.prototype.addTrack=function(){var sender=origAddTrack.apply(this,arguments);sender._pc=this;return sender;};}
+window.RTCRtpSender.prototype.getStats=function(){return this.track?this._pc.getStats(this.track):Promise.resolve(new Map());};}
+function shimReceiverGetStats(window){if(!((typeof window==='undefined'?'undefined':_typeof(window))==='object'&&window.RTCPeerConnection&&window.RTCRtpSender)){return;}
+if(window.RTCRtpSender&&'getStats'in window.RTCRtpReceiver.prototype){return;}
+var origGetReceivers=window.RTCPeerConnection.prototype.getReceivers;if(origGetReceivers){window.RTCPeerConnection.prototype.getReceivers=function(){var _this2=this;var receivers=origGetReceivers.apply(this,[]);receivers.forEach(function(receiver){return receiver._pc=_this2;});return receivers;};}
+utils.wrapPeerConnectionEvent(window,'track',function(e){e.receiver._pc=e.srcElement;return e;});window.RTCRtpReceiver.prototype.getStats=function(){return this._pc.getStats(this.track);};}
+function shimRemoveStream(window){if(!window.RTCPeerConnection||'removeStream'in window.RTCPeerConnection.prototype){return;}
+window.RTCPeerConnection.prototype.removeStream=function(stream){var _this3=this;utils.deprecated('removeStream','removeTrack');this.getSenders().forEach(function(sender){if(sender.track&&stream.getTracks().includes(sender.track)){_this3.removeTrack(sender);}});};}
+function shimRTCDataChannel(window){if(window.DataChannel&&!window.RTCDataChannel){window.RTCDataChannel=window.DataChannel;}}},{"../utils":15,"./getdisplaymedia":12,"./getusermedia":13}],12:[function(require,module,exports){'use strict';Object.defineProperty(exports,"__esModule",{value:true});exports.shimGetDisplayMedia=shimGetDisplayMedia;function shimGetDisplayMedia(window,preferredMediaSource){if(window.navigator.mediaDevices&&'getDisplayMedia'in window.navigator.mediaDevices){return;}
+if(!window.navigator.mediaDevices){return;}
+window.navigator.mediaDevices.getDisplayMedia=function(constraints){if(!(constraints&&constraints.video)){var err=new DOMException('getDisplayMedia without video '+'constraints is undefined');err.name='NotFoundError';err.code=8;return Promise.reject(err);}
+if(constraints.video===true){constraints.video={mediaSource:preferredMediaSource};}else{constraints.video.mediaSource=preferredMediaSource;}
+return window.navigator.mediaDevices.getUserMedia(constraints);};}},{}],13:[function(require,module,exports){'use strict';Object.defineProperty(exports,"__esModule",{value:true});var _typeof=typeof Symbol==="function"&&typeof Symbol.iterator==="symbol"?function(obj){return typeof obj;}:function(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj;};exports.shimGetUserMedia=shimGetUserMedia;var _utils=require('../utils');var utils=_interopRequireWildcard(_utils);function _interopRequireWildcard(obj){if(obj&&obj.__esModule){return obj;}else{var newObj={};if(obj!=null){for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key))newObj[key]=obj[key];}}newObj.default=obj;return newObj;}}
+function shimGetUserMedia(window){var browserDetails=utils.detectBrowser(window);var navigator=window&&window.navigator;var MediaStreamTrack=window&&window.MediaStreamTrack;navigator.getUserMedia=function(constraints,onSuccess,onError){utils.deprecated('navigator.getUserMedia','navigator.mediaDevices.getUserMedia');navigator.mediaDevices.getUserMedia(constraints).then(onSuccess,onError);};if(!(browserDetails.version>55&&'autoGainControl'in navigator.mediaDevices.getSupportedConstraints())){var remap=function remap(obj,a,b){if(a in obj&&!(b in obj)){obj[b]=obj[a];delete obj[a];}};var nativeGetUserMedia=navigator.mediaDevices.getUserMedia.bind(navigator.mediaDevices);navigator.mediaDevices.getUserMedia=function(c){if((typeof c==='undefined'?'undefined':_typeof(c))==='object'&&_typeof(c.audio)==='object'){c=JSON.parse(JSON.stringify(c));remap(c.audio,'autoGainControl','mozAutoGainControl');remap(c.audio,'noiseSuppression','mozNoiseSuppression');}
+return nativeGetUserMedia(c);};if(MediaStreamTrack&&MediaStreamTrack.prototype.getSettings){var nativeGetSettings=MediaStreamTrack.prototype.getSettings;MediaStreamTrack.prototype.getSettings=function(){var obj=nativeGetSettings.apply(this,arguments);remap(obj,'mozAutoGainControl','autoGainControl');remap(obj,'mozNoiseSuppression','noiseSuppression');return obj;};}
+if(MediaStreamTrack&&MediaStreamTrack.prototype.applyConstraints){var nativeApplyConstraints=MediaStreamTrack.prototype.applyConstraints;MediaStreamTrack.prototype.applyConstraints=function(c){if(this.kind==='audio'&&(typeof c==='undefined'?'undefined':_typeof(c))==='object'){c=JSON.parse(JSON.stringify(c));remap(c,'autoGainControl','mozAutoGainControl');remap(c,'noiseSuppression','mozNoiseSuppression');}
+return nativeApplyConstraints.apply(this,[c]);};}}}},{"../utils":15}],14:[function(require,module,exports){'use strict';Object.defineProperty(exports,"__esModule",{value:true});var _typeof=typeof Symbol==="function"&&typeof Symbol.iterator==="symbol"?function(obj){return typeof obj;}:function(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj;};exports.shimLocalStreamsAPI=shimLocalStreamsAPI;exports.shimRemoteStreamsAPI=shimRemoteStreamsAPI;exports.shimCallbacksAPI=shimCallbacksAPI;exports.shimGetUserMedia=shimGetUserMedia;exports.shimConstraints=shimConstraints;exports.shimRTCIceServerUrls=shimRTCIceServerUrls;exports.shimTrackEventTransceiver=shimTrackEventTransceiver;exports.shimCreateOfferLegacy=shimCreateOfferLegacy;var _utils=require('../utils');var utils=_interopRequireWildcard(_utils);function _interopRequireWildcard(obj){if(obj&&obj.__esModule){return obj;}else{var newObj={};if(obj!=null){for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key))newObj[key]=obj[key];}}newObj.default=obj;return newObj;}}
+function shimLocalStreamsAPI(window){if((typeof window==='undefined'?'undefined':_typeof(window))!=='object'||!window.RTCPeerConnection){return;}
+if(!('getLocalStreams'in window.RTCPeerConnection.prototype)){window.RTCPeerConnection.prototype.getLocalStreams=function(){if(!this._localStreams){this._localStreams=[];}
+return this._localStreams;};}
+if(!('addStream'in window.RTCPeerConnection.prototype)){var _addTrack=window.RTCPeerConnection.prototype.addTrack;window.RTCPeerConnection.prototype.addStream=function(stream){var _this=this;if(!this._localStreams){this._localStreams=[];}
+if(!this._localStreams.includes(stream)){this._localStreams.push(stream);}
+stream.getTracks().forEach(function(track){return _addTrack.call(_this,track,stream);});};window.RTCPeerConnection.prototype.addTrack=function(track,stream){if(stream){if(!this._localStreams){this._localStreams=[stream];}else if(!this._localStreams.includes(stream)){this._localStreams.push(stream);}}
+return _addTrack.call(this,track,stream);};}
+if(!('removeStream'in window.RTCPeerConnection.prototype)){window.RTCPeerConnection.prototype.removeStream=function(stream){var _this2=this;if(!this._localStreams){this._localStreams=[];}
+var index=this._localStreams.indexOf(stream);if(index===-1){return;}
+this._localStreams.splice(index,1);var tracks=stream.getTracks();this.getSenders().forEach(function(sender){if(tracks.includes(sender.track)){_this2.removeTrack(sender);}});};}}
+function shimRemoteStreamsAPI(window){if((typeof window==='undefined'?'undefined':_typeof(window))!=='object'||!window.RTCPeerConnection){return;}
+if(!('getRemoteStreams'in window.RTCPeerConnection.prototype)){window.RTCPeerConnection.prototype.getRemoteStreams=function(){return this._remoteStreams?this._remoteStreams:[];};}
+if(!('onaddstream'in window.RTCPeerConnection.prototype)){Object.defineProperty(window.RTCPeerConnection.prototype,'onaddstream',{get:function get(){return this._onaddstream;},set:function set(f){var _this3=this;if(this._onaddstream){this.removeEventListener('addstream',this._onaddstream);this.removeEventListener('track',this._onaddstreampoly);}
+this.addEventListener('addstream',this._onaddstream=f);this.addEventListener('track',this._onaddstreampoly=function(e){e.streams.forEach(function(stream){if(!_this3._remoteStreams){_this3._remoteStreams=[];}
+if(_this3._remoteStreams.includes(stream)){return;}
+_this3._remoteStreams.push(stream);var event=new Event('addstream');event.stream=stream;_this3.dispatchEvent(event);});});}});var origSetRemoteDescription=window.RTCPeerConnection.prototype.setRemoteDescription;window.RTCPeerConnection.prototype.setRemoteDescription=function(){var pc=this;if(!this._onaddstreampoly){this.addEventListener('track',this._onaddstreampoly=function(e){e.streams.forEach(function(stream){if(!pc._remoteStreams){pc._remoteStreams=[];}
+if(pc._remoteStreams.indexOf(stream)>=0){return;}
+pc._remoteStreams.push(stream);var event=new Event('addstream');event.stream=stream;pc.dispatchEvent(event);});});}
+return origSetRemoteDescription.apply(pc,arguments);};}}
+function shimCallbacksAPI(window){if((typeof window==='undefined'?'undefined':_typeof(window))!=='object'||!window.RTCPeerConnection){return;}
+var prototype=window.RTCPeerConnection.prototype;var createOffer=prototype.createOffer;var createAnswer=prototype.createAnswer;var setLocalDescription=prototype.setLocalDescription;var setRemoteDescription=prototype.setRemoteDescription;var addIceCandidate=prototype.addIceCandidate;prototype.createOffer=function(successCallback,failureCallback){var options=arguments.length>=2?arguments[2]:arguments[0];var promise=createOffer.apply(this,[options]);if(!failureCallback){return promise;}
+promise.then(successCallback,failureCallback);return Promise.resolve();};prototype.createAnswer=function(successCallback,failureCallback){var options=arguments.length>=2?arguments[2]:arguments[0];var promise=createAnswer.apply(this,[options]);if(!failureCallback){return promise;}
+promise.then(successCallback,failureCallback);return Promise.resolve();};var withCallback=function withCallback(description,successCallback,failureCallback){var promise=setLocalDescription.apply(this,[description]);if(!failureCallback){return promise;}
+promise.then(successCallback,failureCallback);return Promise.resolve();};prototype.setLocalDescription=withCallback;withCallback=function withCallback(description,successCallback,failureCallback){var promise=setRemoteDescription.apply(this,[description]);if(!failureCallback){return promise;}
+promise.then(successCallback,failureCallback);return Promise.resolve();};prototype.setRemoteDescription=withCallback;withCallback=function withCallback(candidate,successCallback,failureCallback){var promise=addIceCandidate.apply(this,[candidate]);if(!failureCallback){return promise;}
+promise.then(successCallback,failureCallback);return Promise.resolve();};prototype.addIceCandidate=withCallback;}
+function shimGetUserMedia(window){var navigator=window&&window.navigator;if(navigator.mediaDevices&&navigator.mediaDevices.getUserMedia){var mediaDevices=navigator.mediaDevices;var _getUserMedia=mediaDevices.getUserMedia.bind(mediaDevices);navigator.mediaDevices.getUserMedia=function(constraints){return _getUserMedia(shimConstraints(constraints));};}
+if(!navigator.getUserMedia&&navigator.mediaDevices&&navigator.mediaDevices.getUserMedia){navigator.getUserMedia=function(constraints,cb,errcb){navigator.mediaDevices.getUserMedia(constraints).then(cb,errcb);}.bind(navigator);}}
+function shimConstraints(constraints){if(constraints&&constraints.video!==undefined){return Object.assign({},constraints,{video:utils.compactObject(constraints.video)});}
+return constraints;}
+function shimRTCIceServerUrls(window){var OrigPeerConnection=window.RTCPeerConnection;window.RTCPeerConnection=function(pcConfig,pcConstraints){if(pcConfig&&pcConfig.iceServers){var newIceServers=[];for(var i=0;i=pos&&parseInt(match[pos],10);}
+function wrapPeerConnectionEvent(window,eventNameToWrap,wrapper){if(!window.RTCPeerConnection){return;}
+var proto=window.RTCPeerConnection.prototype;var nativeAddEventListener=proto.addEventListener;proto.addEventListener=function(nativeEventName,cb){if(nativeEventName!==eventNameToWrap){return nativeAddEventListener.apply(this,arguments);}
+var wrappedCallback=function wrappedCallback(e){var modifiedEvent=wrapper(e);if(modifiedEvent){cb(modifiedEvent);}};this._eventMap=this._eventMap||{};this._eventMap[cb]=wrappedCallback;return nativeAddEventListener.apply(this,[nativeEventName,wrappedCallback]);};var nativeRemoveEventListener=proto.removeEventListener;proto.removeEventListener=function(nativeEventName,cb){if(nativeEventName!==eventNameToWrap||!this._eventMap||!this._eventMap[cb]){return nativeRemoveEventListener.apply(this,arguments);}
+var unwrappedCb=this._eventMap[cb];delete this._eventMap[cb];return nativeRemoveEventListener.apply(this,[nativeEventName,unwrappedCb]);};Object.defineProperty(proto,'on'+eventNameToWrap,{get:function get(){return this['_on'+eventNameToWrap];},set:function set(cb){if(this['_on'+eventNameToWrap]){this.removeEventListener(eventNameToWrap,this['_on'+eventNameToWrap]);delete this['_on'+eventNameToWrap];}
+if(cb){this.addEventListener(eventNameToWrap,this['_on'+eventNameToWrap]=cb);}},enumerable:true,configurable:true});}
+function disableLog(bool){if(typeof bool!=='boolean'){return new Error('Argument type: '+(typeof bool==='undefined'?'undefined':_typeof(bool))+'. Please use a boolean.');}
+logDisabled_=bool;return bool?'adapter.js logging disabled':'adapter.js logging enabled';}
+function disableWarnings(bool){if(typeof bool!=='boolean'){return new Error('Argument type: '+(typeof bool==='undefined'?'undefined':_typeof(bool))+'. Please use a boolean.');}
+deprecationWarnings_=!bool;return'adapter.js deprecation warnings '+(bool?'disabled':'enabled');}
+function log(){if((typeof window==='undefined'?'undefined':_typeof(window))==='object'){if(logDisabled_){return;}
+if(typeof console!=='undefined'&&typeof console.log==='function'){console.log.apply(console,arguments);}}}
+function deprecated(oldMethod,newMethod){if(!deprecationWarnings_){return;}
+console.warn(oldMethod+' is deprecated, please use '+newMethod+' instead.');}
+function detectBrowser(window){var navigator=window.navigator;var result={browser:null,version:null};if(typeof window==='undefined'||!window.navigator){result.browser='Not a browser.';return result;}
+if(navigator.mozGetUserMedia){result.browser='firefox';result.version=extractVersion(navigator.userAgent,/Firefox\/(\d+)\./,1);}else if(navigator.webkitGetUserMedia){result.browser='chrome';result.version=extractVersion(navigator.userAgent,/Chrom(e|ium)\/(\d+)\./,2);}else if(navigator.mediaDevices&&navigator.userAgent.match(/Edge\/(\d+).(\d+)$/)){result.browser='edge';result.version=extractVersion(navigator.userAgent,/Edge\/(\d+).(\d+)$/,2);}else if(window.RTCPeerConnection&&navigator.userAgent.match(/AppleWebKit\/(\d+)\./)){result.browser='safari';result.version=extractVersion(navigator.userAgent,/AppleWebKit\/(\d+)\./,1);}else{result.browser='Not a supported browser.';return result;}
+return result;}
+function compactObject(data){if((typeof data==='undefined'?'undefined':_typeof(data))!=='object'){return data;}
+return Object.keys(data).reduce(function(accumulator,key){var isObject=_typeof(data[key])==='object';var value=isObject?compactObject(data[key]):data[key];var isEmptyObject=isObject&&!Object.keys(value).length;if(value===undefined||isEmptyObject){return accumulator;}
+return Object.assign(accumulator,_defineProperty({},key,value));},{});}},{}],16:[function(require,module,exports){'use strict';var SDPUtils=require('sdp');function fixStatsType(stat){return{inboundrtp:'inbound-rtp',outboundrtp:'outbound-rtp',candidatepair:'candidate-pair',localcandidate:'local-candidate',remotecandidate:'remote-candidate'}[stat.type]||stat.type;}
+function writeMediaSection(transceiver,caps,type,stream,dtlsRole){var sdp=SDPUtils.writeRtpDescription(transceiver.kind,caps);sdp+=SDPUtils.writeIceParameters(transceiver.iceGatherer.getLocalParameters());sdp+=SDPUtils.writeDtlsParameters(transceiver.dtlsTransport.getLocalParameters(),type==='offer'?'actpass':dtlsRole||'active');sdp+='a=mid:'+transceiver.mid+'\r\n';if(transceiver.rtpSender&&transceiver.rtpReceiver){sdp+='a=sendrecv\r\n';}else if(transceiver.rtpSender){sdp+='a=sendonly\r\n';}else if(transceiver.rtpReceiver){sdp+='a=recvonly\r\n';}else{sdp+='a=inactive\r\n';}
+if(transceiver.rtpSender){var trackId=transceiver.rtpSender._initialTrackId||transceiver.rtpSender.track.id;transceiver.rtpSender._initialTrackId=trackId;var msid='msid:'+(stream?stream.id:'-')+' '+
+trackId+'\r\n';sdp+='a='+msid;sdp+='a=ssrc:'+transceiver.sendEncodingParameters[0].ssrc+' '+msid;if(transceiver.sendEncodingParameters[0].rtx){sdp+='a=ssrc:'+transceiver.sendEncodingParameters[0].rtx.ssrc+' '+msid;sdp+='a=ssrc-group:FID '+
+transceiver.sendEncodingParameters[0].ssrc+' '+
+transceiver.sendEncodingParameters[0].rtx.ssrc+'\r\n';}}
+sdp+='a=ssrc:'+transceiver.sendEncodingParameters[0].ssrc+' cname:'+SDPUtils.localCName+'\r\n';if(transceiver.rtpSender&&transceiver.sendEncodingParameters[0].rtx){sdp+='a=ssrc:'+transceiver.sendEncodingParameters[0].rtx.ssrc+' cname:'+SDPUtils.localCName+'\r\n';}
+return sdp;}
+function filterIceServers(iceServers,edgeVersion){var hasTurn=false;iceServers=JSON.parse(JSON.stringify(iceServers));return iceServers.filter(function(server){if(server&&(server.urls||server.url)){var urls=server.urls||server.url;if(server.url&&!server.urls){console.warn('RTCIceServer.url is deprecated! Use urls instead.');}
+var isString=typeof urls==='string';if(isString){urls=[urls];}
+urls=urls.filter(function(url){var validTurn=url.indexOf('turn:')===0&&url.indexOf('transport=udp')!==-1&&url.indexOf('turn:[')===-1&&!hasTurn;if(validTurn){hasTurn=true;return true;}
+return url.indexOf('stun:')===0&&edgeVersion>=14393&&url.indexOf('?transport=udp')===-1;});delete server.url;server.urls=isString?urls[0]:urls;return!!urls.length;}});}
+function getCommonCapabilities(localCapabilities,remoteCapabilities){var commonCapabilities={codecs:[],headerExtensions:[],fecMechanisms:[]};var findCodecByPayloadType=function(pt,codecs){pt=parseInt(pt,10);for(var i=0;i0;i--){this._iceGatherers.push(new window.RTCIceGatherer({iceServers:config.iceServers,gatherPolicy:config.iceTransportPolicy}));}}else{config.iceCandidatePoolSize=0;}
+this._config=config;this.transceivers=[];this._sdpSessionId=SDPUtils.generateSessionId();this._sdpSessionVersion=0;this._dtlsRole=undefined;this._isClosed=false;};Object.defineProperty(RTCPeerConnection.prototype,'localDescription',{configurable:true,get:function(){return this._localDescription;}});Object.defineProperty(RTCPeerConnection.prototype,'remoteDescription',{configurable:true,get:function(){return this._remoteDescription;}});RTCPeerConnection.prototype.onicecandidate=null;RTCPeerConnection.prototype.onaddstream=null;RTCPeerConnection.prototype.ontrack=null;RTCPeerConnection.prototype.onremovestream=null;RTCPeerConnection.prototype.onsignalingstatechange=null;RTCPeerConnection.prototype.oniceconnectionstatechange=null;RTCPeerConnection.prototype.onconnectionstatechange=null;RTCPeerConnection.prototype.onicegatheringstatechange=null;RTCPeerConnection.prototype.onnegotiationneeded=null;RTCPeerConnection.prototype.ondatachannel=null;RTCPeerConnection.prototype._dispatchEvent=function(name,event){if(this._isClosed){return;}
+this.dispatchEvent(event);if(typeof this['on'+name]==='function'){this['on'+name](event);}};RTCPeerConnection.prototype._emitGatheringStateChange=function(){var event=new Event('icegatheringstatechange');this._dispatchEvent('icegatheringstatechange',event);};RTCPeerConnection.prototype.getConfiguration=function(){return this._config;};RTCPeerConnection.prototype.getLocalStreams=function(){return this.localStreams;};RTCPeerConnection.prototype.getRemoteStreams=function(){return this.remoteStreams;};RTCPeerConnection.prototype._createTransceiver=function(kind,doNotAdd){var hasBundleTransport=this.transceivers.length>0;var transceiver={track:null,iceGatherer:null,iceTransport:null,dtlsTransport:null,localCapabilities:null,remoteCapabilities:null,rtpSender:null,rtpReceiver:null,kind:kind,mid:null,sendEncodingParameters:null,recvEncodingParameters:null,stream:null,associatedRemoteMediaStreams:[],wantReceive:true};if(this.usingBundle&&hasBundleTransport){transceiver.iceTransport=this.transceivers[0].iceTransport;transceiver.dtlsTransport=this.transceivers[0].dtlsTransport;}else{var transports=this._createIceAndDtlsTransports();transceiver.iceTransport=transports.iceTransport;transceiver.dtlsTransport=transports.dtlsTransport;}
+if(!doNotAdd){this.transceivers.push(transceiver);}
+return transceiver;};RTCPeerConnection.prototype.addTrack=function(track,stream){if(this._isClosed){throw makeError('InvalidStateError','Attempted to call addTrack on a closed peerconnection.');}
+var alreadyExists=this.transceivers.find(function(s){return s.track===track;});if(alreadyExists){throw makeError('InvalidAccessError','Track already exists.');}
+var transceiver;for(var i=0;i=15025){stream.getTracks().forEach(function(track){pc.addTrack(track,stream);});}else{var clonedStream=stream.clone();stream.getTracks().forEach(function(track,idx){var clonedTrack=clonedStream.getTracks()[idx];track.addEventListener('enabled',function(event){clonedTrack.enabled=event.enabled;});});clonedStream.getTracks().forEach(function(track){pc.addTrack(track,clonedStream);});}};RTCPeerConnection.prototype.removeTrack=function(sender){if(this._isClosed){throw makeError('InvalidStateError','Attempted to call removeTrack on a closed peerconnection.');}
+if(!(sender instanceof window.RTCRtpSender)){throw new TypeError('Argument 1 of RTCPeerConnection.removeTrack '+'does not implement interface RTCRtpSender.');}
+var transceiver=this.transceivers.find(function(t){return t.rtpSender===sender;});if(!transceiver){throw makeError('InvalidAccessError','Sender was not created by this connection.');}
+var stream=transceiver.stream;transceiver.rtpSender.stop();transceiver.rtpSender=null;transceiver.track=null;transceiver.stream=null;var localStreams=this.transceivers.map(function(t){return t.stream;});if(localStreams.indexOf(stream)===-1&&this.localStreams.indexOf(stream)>-1){this.localStreams.splice(this.localStreams.indexOf(stream),1);}
+this._maybeFireNegotiationNeeded();};RTCPeerConnection.prototype.removeStream=function(stream){var pc=this;stream.getTracks().forEach(function(track){var sender=pc.getSenders().find(function(s){return s.track===track;});if(sender){pc.removeTrack(sender);}});};RTCPeerConnection.prototype.getSenders=function(){return this.transceivers.filter(function(transceiver){return!!transceiver.rtpSender;}).map(function(transceiver){return transceiver.rtpSender;});};RTCPeerConnection.prototype.getReceivers=function(){return this.transceivers.filter(function(transceiver){return!!transceiver.rtpReceiver;}).map(function(transceiver){return transceiver.rtpReceiver;});};RTCPeerConnection.prototype._createIceGatherer=function(sdpMLineIndex,usingBundle){var pc=this;if(usingBundle&&sdpMLineIndex>0){return this.transceivers[0].iceGatherer;}else if(this._iceGatherers.length){return this._iceGatherers.shift();}
+var iceGatherer=new window.RTCIceGatherer({iceServers:this._config.iceServers,gatherPolicy:this._config.iceTransportPolicy});Object.defineProperty(iceGatherer,'state',{value:'new',writable:true});this.transceivers[sdpMLineIndex].bufferedCandidateEvents=[];this.transceivers[sdpMLineIndex].bufferCandidates=function(event){var end=!event.candidate||Object.keys(event.candidate).length===0;iceGatherer.state=end?'completed':'gathering';if(pc.transceivers[sdpMLineIndex].bufferedCandidateEvents!==null){pc.transceivers[sdpMLineIndex].bufferedCandidateEvents.push(event);}};iceGatherer.addEventListener('localcandidate',this.transceivers[sdpMLineIndex].bufferCandidates);return iceGatherer;};RTCPeerConnection.prototype._gather=function(mid,sdpMLineIndex){var pc=this;var iceGatherer=this.transceivers[sdpMLineIndex].iceGatherer;if(iceGatherer.onlocalcandidate){return;}
+var bufferedCandidateEvents=this.transceivers[sdpMLineIndex].bufferedCandidateEvents;this.transceivers[sdpMLineIndex].bufferedCandidateEvents=null;iceGatherer.removeEventListener('localcandidate',this.transceivers[sdpMLineIndex].bufferCandidates);iceGatherer.onlocalcandidate=function(evt){if(pc.usingBundle&&sdpMLineIndex>0){return;}
+var event=new Event('icecandidate');event.candidate={sdpMid:mid,sdpMLineIndex:sdpMLineIndex};var cand=evt.candidate;var end=!cand||Object.keys(cand).length===0;if(end){if(iceGatherer.state==='new'||iceGatherer.state==='gathering'){iceGatherer.state='completed';}}else{if(iceGatherer.state==='new'){iceGatherer.state='gathering';}
+cand.component=1;cand.ufrag=iceGatherer.getLocalParameters().usernameFragment;var serializedCandidate=SDPUtils.writeCandidate(cand);event.candidate=Object.assign(event.candidate,SDPUtils.parseCandidate(serializedCandidate));event.candidate.candidate=serializedCandidate;event.candidate.toJSON=function(){return{candidate:event.candidate.candidate,sdpMid:event.candidate.sdpMid,sdpMLineIndex:event.candidate.sdpMLineIndex,usernameFragment:event.candidate.usernameFragment};};}
+var sections=SDPUtils.getMediaSections(pc._localDescription.sdp);if(!end){sections[event.candidate.sdpMLineIndex]+='a='+event.candidate.candidate+'\r\n';}else{sections[event.candidate.sdpMLineIndex]+='a=end-of-candidates\r\n';}
+pc._localDescription.sdp=SDPUtils.getDescription(pc._localDescription.sdp)+
+sections.join('');var complete=pc.transceivers.every(function(transceiver){return transceiver.iceGatherer&&transceiver.iceGatherer.state==='completed';});if(pc.iceGatheringState!=='gathering'){pc.iceGatheringState='gathering';pc._emitGatheringStateChange();}
+if(!end){pc._dispatchEvent('icecandidate',event);}
+if(complete){pc._dispatchEvent('icecandidate',new Event('icecandidate'));pc.iceGatheringState='complete';pc._emitGatheringStateChange();}};window.setTimeout(function(){bufferedCandidateEvents.forEach(function(e){iceGatherer.onlocalcandidate(e);});},0);};RTCPeerConnection.prototype._createIceAndDtlsTransports=function(){var pc=this;var iceTransport=new window.RTCIceTransport(null);iceTransport.onicestatechange=function(){pc._updateIceConnectionState();pc._updateConnectionState();};var dtlsTransport=new window.RTCDtlsTransport(iceTransport);dtlsTransport.ondtlsstatechange=function(){pc._updateConnectionState();};dtlsTransport.onerror=function(){Object.defineProperty(dtlsTransport,'state',{value:'failed',writable:true});pc._updateConnectionState();};return{iceTransport:iceTransport,dtlsTransport:dtlsTransport};};RTCPeerConnection.prototype._disposeIceAndDtlsTransports=function(sdpMLineIndex){var iceGatherer=this.transceivers[sdpMLineIndex].iceGatherer;if(iceGatherer){delete iceGatherer.onlocalcandidate;delete this.transceivers[sdpMLineIndex].iceGatherer;}
+var iceTransport=this.transceivers[sdpMLineIndex].iceTransport;if(iceTransport){delete iceTransport.onicestatechange;delete this.transceivers[sdpMLineIndex].iceTransport;}
+var dtlsTransport=this.transceivers[sdpMLineIndex].dtlsTransport;if(dtlsTransport){delete dtlsTransport.ondtlsstatechange;delete dtlsTransport.onerror;delete this.transceivers[sdpMLineIndex].dtlsTransport;}};RTCPeerConnection.prototype._transceive=function(transceiver,send,recv){var params=getCommonCapabilities(transceiver.localCapabilities,transceiver.remoteCapabilities);if(send&&transceiver.rtpSender){params.encodings=transceiver.sendEncodingParameters;params.rtcp={cname:SDPUtils.localCName,compound:transceiver.rtcpParameters.compound};if(transceiver.recvEncodingParameters.length){params.rtcp.ssrc=transceiver.recvEncodingParameters[0].ssrc;}
+transceiver.rtpSender.send(params);}
+if(recv&&transceiver.rtpReceiver&¶ms.codecs.length>0){if(transceiver.kind==='video'&&transceiver.recvEncodingParameters&&edgeVersion<15019){transceiver.recvEncodingParameters.forEach(function(p){delete p.rtx;});}
+if(transceiver.recvEncodingParameters.length){params.encodings=transceiver.recvEncodingParameters;}else{params.encodings=[{}];}
+params.rtcp={compound:transceiver.rtcpParameters.compound};if(transceiver.rtcpParameters.cname){params.rtcp.cname=transceiver.rtcpParameters.cname;}
+if(transceiver.sendEncodingParameters.length){params.rtcp.ssrc=transceiver.sendEncodingParameters[0].ssrc;}
+transceiver.rtpReceiver.receive(params);}};RTCPeerConnection.prototype.setLocalDescription=function(description){var pc=this;if(['offer','answer'].indexOf(description.type)===-1){return Promise.reject(makeError('TypeError','Unsupported type "'+description.type+'"'));}
+if(!isActionAllowedInSignalingState('setLocalDescription',description.type,pc.signalingState)||pc._isClosed){return Promise.reject(makeError('InvalidStateError','Can not set local '+description.type+' in state '+pc.signalingState));}
+var sections;var sessionpart;if(description.type==='offer'){sections=SDPUtils.splitSections(description.sdp);sessionpart=sections.shift();sections.forEach(function(mediaSection,sdpMLineIndex){var caps=SDPUtils.parseRtpParameters(mediaSection);pc.transceivers[sdpMLineIndex].localCapabilities=caps;});pc.transceivers.forEach(function(transceiver,sdpMLineIndex){pc._gather(transceiver.mid,sdpMLineIndex);});}else if(description.type==='answer'){sections=SDPUtils.splitSections(pc._remoteDescription.sdp);sessionpart=sections.shift();var isIceLite=SDPUtils.matchPrefix(sessionpart,'a=ice-lite').length>0;sections.forEach(function(mediaSection,sdpMLineIndex){var transceiver=pc.transceivers[sdpMLineIndex];var iceGatherer=transceiver.iceGatherer;var iceTransport=transceiver.iceTransport;var dtlsTransport=transceiver.dtlsTransport;var localCapabilities=transceiver.localCapabilities;var remoteCapabilities=transceiver.remoteCapabilities;var rejected=SDPUtils.isRejected(mediaSection)&&SDPUtils.matchPrefix(mediaSection,'a=bundle-only').length===0;if(!rejected&&!transceiver.rejected){var remoteIceParameters=SDPUtils.getIceParameters(mediaSection,sessionpart);var remoteDtlsParameters=SDPUtils.getDtlsParameters(mediaSection,sessionpart);if(isIceLite){remoteDtlsParameters.role='server';}
+if(!pc.usingBundle||sdpMLineIndex===0){pc._gather(transceiver.mid,sdpMLineIndex);if(iceTransport.state==='new'){iceTransport.start(iceGatherer,remoteIceParameters,isIceLite?'controlling':'controlled');}
+if(dtlsTransport.state==='new'){dtlsTransport.start(remoteDtlsParameters);}}
+var params=getCommonCapabilities(localCapabilities,remoteCapabilities);pc._transceive(transceiver,params.codecs.length>0,false);}});}
+pc._localDescription={type:description.type,sdp:description.sdp};if(description.type==='offer'){pc._updateSignalingState('have-local-offer');}else{pc._updateSignalingState('stable');}
+return Promise.resolve();};RTCPeerConnection.prototype.setRemoteDescription=function(description){var pc=this;if(['offer','answer'].indexOf(description.type)===-1){return Promise.reject(makeError('TypeError','Unsupported type "'+description.type+'"'));}
+if(!isActionAllowedInSignalingState('setRemoteDescription',description.type,pc.signalingState)||pc._isClosed){return Promise.reject(makeError('InvalidStateError','Can not set remote '+description.type+' in state '+pc.signalingState));}
+var streams={};pc.remoteStreams.forEach(function(stream){streams[stream.id]=stream;});var receiverList=[];var sections=SDPUtils.splitSections(description.sdp);var sessionpart=sections.shift();var isIceLite=SDPUtils.matchPrefix(sessionpart,'a=ice-lite').length>0;var usingBundle=SDPUtils.matchPrefix(sessionpart,'a=group:BUNDLE ').length>0;pc.usingBundle=usingBundle;var iceOptions=SDPUtils.matchPrefix(sessionpart,'a=ice-options:')[0];if(iceOptions){pc.canTrickleIceCandidates=iceOptions.substr(14).split(' ').indexOf('trickle')>=0;}else{pc.canTrickleIceCandidates=false;}
+sections.forEach(function(mediaSection,sdpMLineIndex){var lines=SDPUtils.splitLines(mediaSection);var kind=SDPUtils.getKind(mediaSection);var rejected=SDPUtils.isRejected(mediaSection)&&SDPUtils.matchPrefix(mediaSection,'a=bundle-only').length===0;var protocol=lines[0].substr(2).split(' ')[2];var direction=SDPUtils.getDirection(mediaSection,sessionpart);var remoteMsid=SDPUtils.parseMsid(mediaSection);var mid=SDPUtils.getMid(mediaSection)||SDPUtils.generateIdentifier();if(rejected||(kind==='application'&&(protocol==='DTLS/SCTP'||protocol==='UDP/DTLS/SCTP'))){pc.transceivers[sdpMLineIndex]={mid:mid,kind:kind,protocol:protocol,rejected:true};return;}
+if(!rejected&&pc.transceivers[sdpMLineIndex]&&pc.transceivers[sdpMLineIndex].rejected){pc.transceivers[sdpMLineIndex]=pc._createTransceiver(kind,true);}
+var transceiver;var iceGatherer;var iceTransport;var dtlsTransport;var rtpReceiver;var sendEncodingParameters;var recvEncodingParameters;var localCapabilities;var track;var remoteCapabilities=SDPUtils.parseRtpParameters(mediaSection);var remoteIceParameters;var remoteDtlsParameters;if(!rejected){remoteIceParameters=SDPUtils.getIceParameters(mediaSection,sessionpart);remoteDtlsParameters=SDPUtils.getDtlsParameters(mediaSection,sessionpart);remoteDtlsParameters.role='client';}
+recvEncodingParameters=SDPUtils.parseRtpEncodingParameters(mediaSection);var rtcpParameters=SDPUtils.parseRtcpParameters(mediaSection);var isComplete=SDPUtils.matchPrefix(mediaSection,'a=end-of-candidates',sessionpart).length>0;var cands=SDPUtils.matchPrefix(mediaSection,'a=candidate:').map(function(cand){return SDPUtils.parseCandidate(cand);}).filter(function(cand){return cand.component===1;});if((description.type==='offer'||description.type==='answer')&&!rejected&&usingBundle&&sdpMLineIndex>0&&pc.transceivers[sdpMLineIndex]){pc._disposeIceAndDtlsTransports(sdpMLineIndex);pc.transceivers[sdpMLineIndex].iceGatherer=pc.transceivers[0].iceGatherer;pc.transceivers[sdpMLineIndex].iceTransport=pc.transceivers[0].iceTransport;pc.transceivers[sdpMLineIndex].dtlsTransport=pc.transceivers[0].dtlsTransport;if(pc.transceivers[sdpMLineIndex].rtpSender){pc.transceivers[sdpMLineIndex].rtpSender.setTransport(pc.transceivers[0].dtlsTransport);}
+if(pc.transceivers[sdpMLineIndex].rtpReceiver){pc.transceivers[sdpMLineIndex].rtpReceiver.setTransport(pc.transceivers[0].dtlsTransport);}}
+if(description.type==='offer'&&!rejected){transceiver=pc.transceivers[sdpMLineIndex]||pc._createTransceiver(kind);transceiver.mid=mid;if(!transceiver.iceGatherer){transceiver.iceGatherer=pc._createIceGatherer(sdpMLineIndex,usingBundle);}
+if(cands.length&&transceiver.iceTransport.state==='new'){if(isComplete&&(!usingBundle||sdpMLineIndex===0)){transceiver.iceTransport.setRemoteCandidates(cands);}else{cands.forEach(function(candidate){maybeAddCandidate(transceiver.iceTransport,candidate);});}}
+localCapabilities=window.RTCRtpReceiver.getCapabilities(kind);if(edgeVersion<15019){localCapabilities.codecs=localCapabilities.codecs.filter(function(codec){return codec.name!=='rtx';});}
+sendEncodingParameters=transceiver.sendEncodingParameters||[{ssrc:(2*sdpMLineIndex+2)*1001}];var isNewTrack=false;if(direction==='sendrecv'||direction==='sendonly'){isNewTrack=!transceiver.rtpReceiver;rtpReceiver=transceiver.rtpReceiver||new window.RTCRtpReceiver(transceiver.dtlsTransport,kind);if(isNewTrack){var stream;track=rtpReceiver.track;if(remoteMsid&&remoteMsid.stream==='-'){}else if(remoteMsid){if(!streams[remoteMsid.stream]){streams[remoteMsid.stream]=new window.MediaStream();Object.defineProperty(streams[remoteMsid.stream],'id',{get:function(){return remoteMsid.stream;}});}
+Object.defineProperty(track,'id',{get:function(){return remoteMsid.track;}});stream=streams[remoteMsid.stream];}else{if(!streams.default){streams.default=new window.MediaStream();}
+stream=streams.default;}
+if(stream){addTrackToStreamAndFireEvent(track,stream);transceiver.associatedRemoteMediaStreams.push(stream);}
+receiverList.push([track,rtpReceiver,stream]);}}else if(transceiver.rtpReceiver&&transceiver.rtpReceiver.track){transceiver.associatedRemoteMediaStreams.forEach(function(s){var nativeTrack=s.getTracks().find(function(t){return t.id===transceiver.rtpReceiver.track.id;});if(nativeTrack){removeTrackFromStreamAndFireEvent(nativeTrack,s);}});transceiver.associatedRemoteMediaStreams=[];}
+transceiver.localCapabilities=localCapabilities;transceiver.remoteCapabilities=remoteCapabilities;transceiver.rtpReceiver=rtpReceiver;transceiver.rtcpParameters=rtcpParameters;transceiver.sendEncodingParameters=sendEncodingParameters;transceiver.recvEncodingParameters=recvEncodingParameters;pc._transceive(pc.transceivers[sdpMLineIndex],false,isNewTrack);}else if(description.type==='answer'&&!rejected){transceiver=pc.transceivers[sdpMLineIndex];iceGatherer=transceiver.iceGatherer;iceTransport=transceiver.iceTransport;dtlsTransport=transceiver.dtlsTransport;rtpReceiver=transceiver.rtpReceiver;sendEncodingParameters=transceiver.sendEncodingParameters;localCapabilities=transceiver.localCapabilities;pc.transceivers[sdpMLineIndex].recvEncodingParameters=recvEncodingParameters;pc.transceivers[sdpMLineIndex].remoteCapabilities=remoteCapabilities;pc.transceivers[sdpMLineIndex].rtcpParameters=rtcpParameters;if(cands.length&&iceTransport.state==='new'){if((isIceLite||isComplete)&&(!usingBundle||sdpMLineIndex===0)){iceTransport.setRemoteCandidates(cands);}else{cands.forEach(function(candidate){maybeAddCandidate(transceiver.iceTransport,candidate);});}}
+if(!usingBundle||sdpMLineIndex===0){if(iceTransport.state==='new'){iceTransport.start(iceGatherer,remoteIceParameters,'controlling');}
+if(dtlsTransport.state==='new'){dtlsTransport.start(remoteDtlsParameters);}}
+var commonCapabilities=getCommonCapabilities(transceiver.localCapabilities,transceiver.remoteCapabilities);var hasRtx=commonCapabilities.codecs.filter(function(c){return c.name.toLowerCase()==='rtx';}).length;if(!hasRtx&&transceiver.sendEncodingParameters[0].rtx){delete transceiver.sendEncodingParameters[0].rtx;}
+pc._transceive(transceiver,direction==='sendrecv'||direction==='recvonly',direction==='sendrecv'||direction==='sendonly');if(rtpReceiver&&(direction==='sendrecv'||direction==='sendonly')){track=rtpReceiver.track;if(remoteMsid){if(!streams[remoteMsid.stream]){streams[remoteMsid.stream]=new window.MediaStream();}
+addTrackToStreamAndFireEvent(track,streams[remoteMsid.stream]);receiverList.push([track,rtpReceiver,streams[remoteMsid.stream]]);}else{if(!streams.default){streams.default=new window.MediaStream();}
+addTrackToStreamAndFireEvent(track,streams.default);receiverList.push([track,rtpReceiver,streams.default]);}}else{delete transceiver.rtpReceiver;}}});if(pc._dtlsRole===undefined){pc._dtlsRole=description.type==='offer'?'active':'passive';}
+pc._remoteDescription={type:description.type,sdp:description.sdp};if(description.type==='offer'){pc._updateSignalingState('have-remote-offer');}else{pc._updateSignalingState('stable');}
+Object.keys(streams).forEach(function(sid){var stream=streams[sid];if(stream.getTracks().length){if(pc.remoteStreams.indexOf(stream)===-1){pc.remoteStreams.push(stream);var event=new Event('addstream');event.stream=stream;window.setTimeout(function(){pc._dispatchEvent('addstream',event);});}
+receiverList.forEach(function(item){var track=item[0];var receiver=item[1];if(stream.id!==item[2].id){return;}
+fireAddTrack(pc,track,receiver,[stream]);});}});receiverList.forEach(function(item){if(item[2]){return;}
+fireAddTrack(pc,item[0],item[1],[]);});window.setTimeout(function(){if(!(pc&&pc.transceivers)){return;}
+pc.transceivers.forEach(function(transceiver){if(transceiver.iceTransport&&transceiver.iceTransport.state==='new'&&transceiver.iceTransport.getRemoteCandidates().length>0){console.warn('Timeout for addRemoteCandidate. Consider sending '+'an end-of-candidates notification');transceiver.iceTransport.addRemoteCandidate({});}});},4000);return Promise.resolve();};RTCPeerConnection.prototype.close=function(){this.transceivers.forEach(function(transceiver){if(transceiver.iceTransport){transceiver.iceTransport.stop();}
+if(transceiver.dtlsTransport){transceiver.dtlsTransport.stop();}
+if(transceiver.rtpSender){transceiver.rtpSender.stop();}
+if(transceiver.rtpReceiver){transceiver.rtpReceiver.stop();}});this._isClosed=true;this._updateSignalingState('closed');};RTCPeerConnection.prototype._updateSignalingState=function(newState){this.signalingState=newState;var event=new Event('signalingstatechange');this._dispatchEvent('signalingstatechange',event);};RTCPeerConnection.prototype._maybeFireNegotiationNeeded=function(){var pc=this;if(this.signalingState!=='stable'||this.needNegotiation===true){return;}
+this.needNegotiation=true;window.setTimeout(function(){if(pc.needNegotiation){pc.needNegotiation=false;var event=new Event('negotiationneeded');pc._dispatchEvent('negotiationneeded',event);}},0);};RTCPeerConnection.prototype._updateIceConnectionState=function(){var newState;var states={'new':0,closed:0,checking:0,connected:0,completed:0,disconnected:0,failed:0};this.transceivers.forEach(function(transceiver){if(transceiver.iceTransport&&!transceiver.rejected){states[transceiver.iceTransport.state]++;}});newState='new';if(states.failed>0){newState='failed';}else if(states.checking>0){newState='checking';}else if(states.disconnected>0){newState='disconnected';}else if(states.new>0){newState='new';}else if(states.connected>0){newState='connected';}else if(states.completed>0){newState='completed';}
+if(newState!==this.iceConnectionState){this.iceConnectionState=newState;var event=new Event('iceconnectionstatechange');this._dispatchEvent('iceconnectionstatechange',event);}};RTCPeerConnection.prototype._updateConnectionState=function(){var newState;var states={'new':0,closed:0,connecting:0,connected:0,completed:0,disconnected:0,failed:0};this.transceivers.forEach(function(transceiver){if(transceiver.iceTransport&&transceiver.dtlsTransport&&!transceiver.rejected){states[transceiver.iceTransport.state]++;states[transceiver.dtlsTransport.state]++;}});states.connected+=states.completed;newState='new';if(states.failed>0){newState='failed';}else if(states.connecting>0){newState='connecting';}else if(states.disconnected>0){newState='disconnected';}else if(states.new>0){newState='new';}else if(states.connected>0){newState='connected';}
+if(newState!==this.connectionState){this.connectionState=newState;var event=new Event('connectionstatechange');this._dispatchEvent('connectionstatechange',event);}};RTCPeerConnection.prototype.createOffer=function(){var pc=this;if(pc._isClosed){return Promise.reject(makeError('InvalidStateError','Can not call createOffer after close'));}
+var numAudioTracks=pc.transceivers.filter(function(t){return t.kind==='audio';}).length;var numVideoTracks=pc.transceivers.filter(function(t){return t.kind==='video';}).length;var offerOptions=arguments[0];if(offerOptions){if(offerOptions.mandatory||offerOptions.optional){throw new TypeError('Legacy mandatory/optional constraints not supported.');}
+if(offerOptions.offerToReceiveAudio!==undefined){if(offerOptions.offerToReceiveAudio===true){numAudioTracks=1;}else if(offerOptions.offerToReceiveAudio===false){numAudioTracks=0;}else{numAudioTracks=offerOptions.offerToReceiveAudio;}}
+if(offerOptions.offerToReceiveVideo!==undefined){if(offerOptions.offerToReceiveVideo===true){numVideoTracks=1;}else if(offerOptions.offerToReceiveVideo===false){numVideoTracks=0;}else{numVideoTracks=offerOptions.offerToReceiveVideo;}}}
+pc.transceivers.forEach(function(transceiver){if(transceiver.kind==='audio'){numAudioTracks--;if(numAudioTracks<0){transceiver.wantReceive=false;}}else if(transceiver.kind==='video'){numVideoTracks--;if(numVideoTracks<0){transceiver.wantReceive=false;}}});while(numAudioTracks>0||numVideoTracks>0){if(numAudioTracks>0){pc._createTransceiver('audio');numAudioTracks--;}
+if(numVideoTracks>0){pc._createTransceiver('video');numVideoTracks--;}}
+var sdp=SDPUtils.writeSessionBoilerplate(pc._sdpSessionId,pc._sdpSessionVersion++);pc.transceivers.forEach(function(transceiver,sdpMLineIndex){var track=transceiver.track;var kind=transceiver.kind;var mid=transceiver.mid||SDPUtils.generateIdentifier();transceiver.mid=mid;if(!transceiver.iceGatherer){transceiver.iceGatherer=pc._createIceGatherer(sdpMLineIndex,pc.usingBundle);}
+var localCapabilities=window.RTCRtpSender.getCapabilities(kind);if(edgeVersion<15019){localCapabilities.codecs=localCapabilities.codecs.filter(function(codec){return codec.name!=='rtx';});}
+localCapabilities.codecs.forEach(function(codec){if(codec.name==='H264'&&codec.parameters['level-asymmetry-allowed']===undefined){codec.parameters['level-asymmetry-allowed']='1';}
+if(transceiver.remoteCapabilities&&transceiver.remoteCapabilities.codecs){transceiver.remoteCapabilities.codecs.forEach(function(remoteCodec){if(codec.name.toLowerCase()===remoteCodec.name.toLowerCase()&&codec.clockRate===remoteCodec.clockRate){codec.preferredPayloadType=remoteCodec.payloadType;}});}});localCapabilities.headerExtensions.forEach(function(hdrExt){var remoteExtensions=transceiver.remoteCapabilities&&transceiver.remoteCapabilities.headerExtensions||[];remoteExtensions.forEach(function(rHdrExt){if(hdrExt.uri===rHdrExt.uri){hdrExt.id=rHdrExt.id;}});});var sendEncodingParameters=transceiver.sendEncodingParameters||[{ssrc:(2*sdpMLineIndex+1)*1001}];if(track){if(edgeVersion>=15019&&kind==='video'&&!sendEncodingParameters[0].rtx){sendEncodingParameters[0].rtx={ssrc:sendEncodingParameters[0].ssrc+1};}}
+if(transceiver.wantReceive){transceiver.rtpReceiver=new window.RTCRtpReceiver(transceiver.dtlsTransport,kind);}
+transceiver.localCapabilities=localCapabilities;transceiver.sendEncodingParameters=sendEncodingParameters;});if(pc._config.bundlePolicy!=='max-compat'){sdp+='a=group:BUNDLE '+pc.transceivers.map(function(t){return t.mid;}).join(' ')+'\r\n';}
+sdp+='a=ice-options:trickle\r\n';pc.transceivers.forEach(function(transceiver,sdpMLineIndex){sdp+=writeMediaSection(transceiver,transceiver.localCapabilities,'offer',transceiver.stream,pc._dtlsRole);sdp+='a=rtcp-rsize\r\n';if(transceiver.iceGatherer&&pc.iceGatheringState!=='new'&&(sdpMLineIndex===0||!pc.usingBundle)){transceiver.iceGatherer.getLocalCandidates().forEach(function(cand){cand.component=1;sdp+='a='+SDPUtils.writeCandidate(cand)+'\r\n';});if(transceiver.iceGatherer.state==='completed'){sdp+='a=end-of-candidates\r\n';}}});var desc=new window.RTCSessionDescription({type:'offer',sdp:sdp});return Promise.resolve(desc);};RTCPeerConnection.prototype.createAnswer=function(){var pc=this;if(pc._isClosed){return Promise.reject(makeError('InvalidStateError','Can not call createAnswer after close'));}
+if(!(pc.signalingState==='have-remote-offer'||pc.signalingState==='have-local-pranswer')){return Promise.reject(makeError('InvalidStateError','Can not call createAnswer in signalingState '+pc.signalingState));}
+var sdp=SDPUtils.writeSessionBoilerplate(pc._sdpSessionId,pc._sdpSessionVersion++);if(pc.usingBundle){sdp+='a=group:BUNDLE '+pc.transceivers.map(function(t){return t.mid;}).join(' ')+'\r\n';}
+sdp+='a=ice-options:trickle\r\n';var mediaSectionsInOffer=SDPUtils.getMediaSections(pc._remoteDescription.sdp).length;pc.transceivers.forEach(function(transceiver,sdpMLineIndex){if(sdpMLineIndex+1>mediaSectionsInOffer){return;}
+if(transceiver.rejected){if(transceiver.kind==='application'){if(transceiver.protocol==='DTLS/SCTP'){sdp+='m=application 0 DTLS/SCTP 5000\r\n';}else{sdp+='m=application 0 '+transceiver.protocol+' webrtc-datachannel\r\n';}}else if(transceiver.kind==='audio'){sdp+='m=audio 0 UDP/TLS/RTP/SAVPF 0\r\n'+'a=rtpmap:0 PCMU/8000\r\n';}else if(transceiver.kind==='video'){sdp+='m=video 0 UDP/TLS/RTP/SAVPF 120\r\n'+'a=rtpmap:120 VP8/90000\r\n';}
+sdp+='c=IN IP4 0.0.0.0\r\n'+'a=inactive\r\n'+'a=mid:'+transceiver.mid+'\r\n';return;}
+if(transceiver.stream){var localTrack;if(transceiver.kind==='audio'){localTrack=transceiver.stream.getAudioTracks()[0];}else if(transceiver.kind==='video'){localTrack=transceiver.stream.getVideoTracks()[0];}
+if(localTrack){if(edgeVersion>=15019&&transceiver.kind==='video'&&!transceiver.sendEncodingParameters[0].rtx){transceiver.sendEncodingParameters[0].rtx={ssrc:transceiver.sendEncodingParameters[0].ssrc+1};}}}
+var commonCapabilities=getCommonCapabilities(transceiver.localCapabilities,transceiver.remoteCapabilities);var hasRtx=commonCapabilities.codecs.filter(function(c){return c.name.toLowerCase()==='rtx';}).length;if(!hasRtx&&transceiver.sendEncodingParameters[0].rtx){delete transceiver.sendEncodingParameters[0].rtx;}
+sdp+=writeMediaSection(transceiver,commonCapabilities,'answer',transceiver.stream,pc._dtlsRole);if(transceiver.rtcpParameters&&transceiver.rtcpParameters.reducedSize){sdp+='a=rtcp-rsize\r\n';}});var desc=new window.RTCSessionDescription({type:'answer',sdp:sdp});return Promise.resolve(desc);};RTCPeerConnection.prototype.addIceCandidate=function(candidate){var pc=this;var sections;if(candidate&&!(candidate.sdpMLineIndex!==undefined||candidate.sdpMid)){return Promise.reject(new TypeError('sdpMLineIndex or sdpMid required'));}
+return new Promise(function(resolve,reject){if(!pc._remoteDescription){return reject(makeError('InvalidStateError','Can not add ICE candidate without a remote description'));}else if(!candidate||candidate.candidate===''){for(var j=0;j0?SDPUtils.parseCandidate(candidate.candidate):{};if(cand.protocol==='tcp'&&(cand.port===0||cand.port===9)){return resolve();}
+if(cand.component&&cand.component!==1){return resolve();}
+if(sdpMLineIndex===0||(sdpMLineIndex>0&&transceiver.iceTransport!==pc.transceivers[0].iceTransport)){if(!maybeAddCandidate(transceiver.iceTransport,cand)){return reject(makeError('OperationError','Can not add ICE candidate'));}}
+var candidateString=candidate.candidate.trim();if(candidateString.indexOf('a=')===0){candidateString=candidateString.substr(2);}
+sections=SDPUtils.getMediaSections(pc._remoteDescription.sdp);sections[sdpMLineIndex]+='a='+
+(cand.type?candidateString:'end-of-candidates')
++'\r\n';pc._remoteDescription.sdp=SDPUtils.getDescription(pc._remoteDescription.sdp)+
+sections.join('');}else{return reject(makeError('OperationError','Can not add ICE candidate'));}}
+resolve();});};RTCPeerConnection.prototype.getStats=function(selector){if(selector&&selector instanceof window.MediaStreamTrack){var senderOrReceiver=null;this.transceivers.forEach(function(transceiver){if(transceiver.rtpSender&&transceiver.rtpSender.track===selector){senderOrReceiver=transceiver.rtpSender;}else if(transceiver.rtpReceiver&&transceiver.rtpReceiver.track===selector){senderOrReceiver=transceiver.rtpReceiver;}});if(!senderOrReceiver){throw makeError('InvalidAccessError','Invalid selector.');}
+return senderOrReceiver.getStats();}
+var promises=[];this.transceivers.forEach(function(transceiver){['rtpSender','rtpReceiver','iceGatherer','iceTransport','dtlsTransport'].forEach(function(method){if(transceiver[method]){promises.push(transceiver[method].getStats());}});});return Promise.all(promises).then(function(allStats){var results=new Map();allStats.forEach(function(stats){stats.forEach(function(stat){results.set(stat.id,stat);});});return results;});};var ortcObjects=['RTCRtpSender','RTCRtpReceiver','RTCIceGatherer','RTCIceTransport','RTCDtlsTransport'];ortcObjects.forEach(function(ortcObjectName){var obj=window[ortcObjectName];if(obj&&obj.prototype&&obj.prototype.getStats){var nativeGetstats=obj.prototype.getStats;obj.prototype.getStats=function(){return nativeGetstats.apply(this).then(function(nativeStats){var mapStats=new Map();Object.keys(nativeStats).forEach(function(id){nativeStats[id].type=fixStatsType(nativeStats[id]);mapStats.set(id,nativeStats[id]);});return mapStats;});};}});var methods=['createOffer','createAnswer'];methods.forEach(function(method){var nativeMethod=RTCPeerConnection.prototype[method];RTCPeerConnection.prototype[method]=function(){var args=arguments;if(typeof args[0]==='function'||typeof args[1]==='function'){return nativeMethod.apply(this,[arguments[2]]).then(function(description){if(typeof args[0]==='function'){args[0].apply(null,[description]);}},function(error){if(typeof args[1]==='function'){args[1].apply(null,[error]);}});}
+return nativeMethod.apply(this,arguments);};});methods=['setLocalDescription','setRemoteDescription','addIceCandidate'];methods.forEach(function(method){var nativeMethod=RTCPeerConnection.prototype[method];RTCPeerConnection.prototype[method]=function(){var args=arguments;if(typeof args[1]==='function'||typeof args[2]==='function'){return nativeMethod.apply(this,arguments).then(function(){if(typeof args[1]==='function'){args[1].apply(null);}},function(error){if(typeof args[2]==='function'){args[2].apply(null,[error]);}});}
+return nativeMethod.apply(this,arguments);};});['getStats'].forEach(function(method){var nativeMethod=RTCPeerConnection.prototype[method];RTCPeerConnection.prototype[method]=function(){var args=arguments;if(typeof args[1]==='function'){return nativeMethod.apply(this,arguments).then(function(){if(typeof args[1]==='function'){args[1].apply(null);}});}
+return nativeMethod.apply(this,arguments);};});return RTCPeerConnection;};},{"sdp":17}],17:[function(require,module,exports){'use strict';var SDPUtils={};SDPUtils.generateIdentifier=function(){return Math.random().toString(36).substr(2,10);};SDPUtils.localCName=SDPUtils.generateIdentifier();SDPUtils.splitLines=function(blob){return blob.trim().split('\n').map(function(line){return line.trim();});};SDPUtils.splitSections=function(blob){var parts=blob.split('\nm=');return parts.map(function(part,index){return(index>0?'m='+part:part).trim()+'\r\n';});};SDPUtils.getDescription=function(blob){var sections=SDPUtils.splitSections(blob);return sections&§ions[0];};SDPUtils.getMediaSections=function(blob){var sections=SDPUtils.splitSections(blob);sections.shift();return sections;};SDPUtils.matchPrefix=function(blob,prefix){return SDPUtils.splitLines(blob).filter(function(line){return line.indexOf(prefix)===0;});};SDPUtils.parseCandidate=function(line){var parts;if(line.indexOf('a=candidate:')===0){parts=line.substring(12).split(' ');}else{parts=line.substring(10).split(' ');}
+var candidate={foundation:parts[0],component:parseInt(parts[1],10),protocol:parts[2].toLowerCase(),priority:parseInt(parts[3],10),ip:parts[4],address:parts[4],port:parseInt(parts[5],10),type:parts[7]};for(var i=8;i0?parts[0].split('/')[1]:'sendrecv',uri:parts[1]};};SDPUtils.writeExtmap=function(headerExtension){return'a=extmap:'+(headerExtension.id||headerExtension.preferredId)+
+(headerExtension.direction&&headerExtension.direction!=='sendrecv'?'/'+headerExtension.direction:'')+' '+headerExtension.uri+'\r\n';};SDPUtils.parseFmtp=function(line){var parsed={};var kv;var parts=line.substr(line.indexOf(' ')+1).split(';');for(var j=0;j-1){parts.attribute=line.substr(sp+1,colon-sp-1);parts.value=line.substr(colon+1);}else{parts.attribute=line.substr(sp+1);}
+return parts;};SDPUtils.parseSsrcGroup=function(line){var parts=line.substr(13).split(' ');return{semantics:parts.shift(),ssrcs:parts.map(function(ssrc){return parseInt(ssrc,10);})};};SDPUtils.getMid=function(mediaSection){var mid=SDPUtils.matchPrefix(mediaSection,'a=mid:')[0];if(mid){return mid.substr(6);}};SDPUtils.parseFingerprint=function(line){var parts=line.substr(14).split(' ');return{algorithm:parts[0].toLowerCase(),value:parts[1]};};SDPUtils.getDtlsParameters=function(mediaSection,sessionpart){var lines=SDPUtils.matchPrefix(mediaSection+sessionpart,'a=fingerprint:');return{role:'auto',fingerprints:lines.map(SDPUtils.parseFingerprint)};};SDPUtils.writeDtlsParameters=function(params,setupType){var sdp='a=setup:'+setupType+'\r\n';params.fingerprints.forEach(function(fp){sdp+='a=fingerprint:'+fp.algorithm+' '+fp.value+'\r\n';});return sdp;};SDPUtils.getIceParameters=function(mediaSection,sessionpart){var lines=SDPUtils.splitLines(mediaSection);lines=lines.concat(SDPUtils.splitLines(sessionpart));var iceParameters={usernameFragment:lines.filter(function(line){return line.indexOf('a=ice-ufrag:')===0;})[0].substr(12),password:lines.filter(function(line){return line.indexOf('a=ice-pwd:')===0;})[0].substr(10)};return iceParameters;};SDPUtils.writeIceParameters=function(params){return'a=ice-ufrag:'+params.usernameFragment+'\r\n'+'a=ice-pwd:'+params.password+'\r\n';};SDPUtils.parseRtpParameters=function(mediaSection){var description={codecs:[],headerExtensions:[],fecMechanisms:[],rtcp:[]};var lines=SDPUtils.splitLines(mediaSection);var mline=lines[0].split(' ');for(var i=3;i0?'9':'0';sdp+=' UDP/TLS/RTP/SAVPF ';sdp+=caps.codecs.map(function(codec){if(codec.preferredPayloadType!==undefined){return codec.preferredPayloadType;}
+return codec.payloadType;}).join(' ')+'\r\n';sdp+='c=IN IP4 0.0.0.0\r\n';sdp+='a=rtcp:9 IN IP4 0.0.0.0\r\n';caps.codecs.forEach(function(codec){sdp+=SDPUtils.writeRtpMap(codec);sdp+=SDPUtils.writeFmtp(codec);sdp+=SDPUtils.writeRtcpFb(codec);});var maxptime=0;caps.codecs.forEach(function(codec){if(codec.maxptime>maxptime){maxptime=codec.maxptime;}});if(maxptime>0){sdp+='a=maxptime:'+maxptime+'\r\n';}
+sdp+='a=rtcp-mux\r\n';if(caps.headerExtensions){caps.headerExtensions.forEach(function(extension){sdp+=SDPUtils.writeExtmap(extension);});}
+return sdp;};SDPUtils.parseRtpEncodingParameters=function(mediaSection){var encodingParameters=[];var description=SDPUtils.parseRtpParameters(mediaSection);var hasRed=description.fecMechanisms.indexOf('RED')!==-1;var hasUlpfec=description.fecMechanisms.indexOf('ULPFEC')!==-1;var ssrcs=SDPUtils.matchPrefix(mediaSection,'a=ssrc:').map(function(line){return SDPUtils.parseSsrcMedia(line);}).filter(function(parts){return parts.attribute==='cname';});var primarySsrc=ssrcs.length>0&&ssrcs[0].ssrc;var secondarySsrc;var flows=SDPUtils.matchPrefix(mediaSection,'a=ssrc-group:FID').map(function(line){var parts=line.substr(17).split(' ');return parts.map(function(part){return parseInt(part,10);});});if(flows.length>0&&flows[0].length>1&&flows[0][0]===primarySsrc){secondarySsrc=flows[0][1];}
+description.codecs.forEach(function(codec){if(codec.name.toUpperCase()==='RTX'&&codec.parameters.apt){var encParam={ssrc:primarySsrc,codecPayloadType:parseInt(codec.parameters.apt,10)};if(primarySsrc&&secondarySsrc){encParam.rtx={ssrc:secondarySsrc};}
+encodingParameters.push(encParam);if(hasRed){encParam=JSON.parse(JSON.stringify(encParam));encParam.fec={ssrc:primarySsrc,mechanism:hasUlpfec?'red+ulpfec':'red'};encodingParameters.push(encParam);}}});if(encodingParameters.length===0&&primarySsrc){encodingParameters.push({ssrc:primarySsrc});}
+var bandwidth=SDPUtils.matchPrefix(mediaSection,'b=');if(bandwidth.length){if(bandwidth[0].indexOf('b=TIAS:')===0){bandwidth=parseInt(bandwidth[0].substr(7),10);}else if(bandwidth[0].indexOf('b=AS:')===0){bandwidth=parseInt(bandwidth[0].substr(5),10)*1000*0.95
+-(50*40*8);}else{bandwidth=undefined;}
+encodingParameters.forEach(function(params){params.maxBitrate=bandwidth;});}
+return encodingParameters;};SDPUtils.parseRtcpParameters=function(mediaSection){var rtcpParameters={};var remoteSsrc=SDPUtils.matchPrefix(mediaSection,'a=ssrc:').map(function(line){return SDPUtils.parseSsrcMedia(line);}).filter(function(obj){return obj.attribute==='cname';})[0];if(remoteSsrc){rtcpParameters.cname=remoteSsrc.value;rtcpParameters.ssrc=remoteSsrc.ssrc;}
+var rsize=SDPUtils.matchPrefix(mediaSection,'a=rtcp-rsize');rtcpParameters.reducedSize=rsize.length>0;rtcpParameters.compound=rsize.length===0;var mux=SDPUtils.matchPrefix(mediaSection,'a=rtcp-mux');rtcpParameters.mux=mux.length>0;return rtcpParameters;};SDPUtils.parseMsid=function(mediaSection){var parts;var spec=SDPUtils.matchPrefix(mediaSection,'a=msid:');if(spec.length===1){parts=spec[0].substr(7).split(' ');return{stream:parts[0],track:parts[1]};}
+var planB=SDPUtils.matchPrefix(mediaSection,'a=ssrc:').map(function(line){return SDPUtils.parseSsrcMedia(line);}).filter(function(msidParts){return msidParts.attribute==='msid';});if(planB.length>0){parts=planB[0].value.split(' ');return{stream:parts[0],track:parts[1]};}};SDPUtils.generateSessionId=function(){return Math.random().toString().substr(2,21);};SDPUtils.writeSessionBoilerplate=function(sessId,sessVer,sessUser){var sessionId;var version=sessVer!==undefined?sessVer:2;if(sessId){sessionId=sessId;}else{sessionId=SDPUtils.generateSessionId();}
+var user=sessUser||'thisisadapterortc';return'v=0\r\n'+'o='+user+' '+sessionId+' '+version+' IN IP4 127.0.0.1\r\n'+'s=-\r\n'+'t=0 0\r\n';};SDPUtils.writeMediaSection=function(transceiver,caps,type,stream){var sdp=SDPUtils.writeRtpDescription(transceiver.kind,caps);sdp+=SDPUtils.writeIceParameters(transceiver.iceGatherer.getLocalParameters());sdp+=SDPUtils.writeDtlsParameters(transceiver.dtlsTransport.getLocalParameters(),type==='offer'?'actpass':'active');sdp+='a=mid:'+transceiver.mid+'\r\n';if(transceiver.direction){sdp+='a='+transceiver.direction+'\r\n';}else if(transceiver.rtpSender&&transceiver.rtpReceiver){sdp+='a=sendrecv\r\n';}else if(transceiver.rtpSender){sdp+='a=sendonly\r\n';}else if(transceiver.rtpReceiver){sdp+='a=recvonly\r\n';}else{sdp+='a=inactive\r\n';}
+if(transceiver.rtpSender){var msid='msid:'+stream.id+' '+
+transceiver.rtpSender.track.id+'\r\n';sdp+='a='+msid;sdp+='a=ssrc:'+transceiver.sendEncodingParameters[0].ssrc+' '+msid;if(transceiver.sendEncodingParameters[0].rtx){sdp+='a=ssrc:'+transceiver.sendEncodingParameters[0].rtx.ssrc+' '+msid;sdp+='a=ssrc-group:FID '+
+transceiver.sendEncodingParameters[0].ssrc+' '+
+transceiver.sendEncodingParameters[0].rtx.ssrc+'\r\n';}}
+sdp+='a=ssrc:'+transceiver.sendEncodingParameters[0].ssrc+' cname:'+SDPUtils.localCName+'\r\n';if(transceiver.rtpSender&&transceiver.sendEncodingParameters[0].rtx){sdp+='a=ssrc:'+transceiver.sendEncodingParameters[0].rtx.ssrc+' cname:'+SDPUtils.localCName+'\r\n';}
+return sdp;};SDPUtils.getDirection=function(mediaSection,sessionpart){var lines=SDPUtils.splitLines(mediaSection);for(var i=0;i 0 && arguments[0] !== undefined ? arguments[0] : {},
+ window = _ref.window;
+
+ var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
+ shimChrome: true,
+ shimFirefox: true,
+ shimEdge: true,
+ shimSafari: true
+ };
+
+ // Utils.
+ var logging = utils.log;
+ var browserDetails = utils.detectBrowser(window);
+
+ var adapter = {
+ browserDetails: browserDetails,
+ commonShim: commonShim,
+ extractVersion: utils.extractVersion,
+ disableLog: utils.disableLog,
+ disableWarnings: utils.disableWarnings
+ };
+
+ // Shim browser if found.
+ switch (browserDetails.browser) {
+ case 'chrome':
+ if (!chromeShim || !chromeShim.shimPeerConnection || !options.shimChrome) {
+ logging('Chrome shim is not included in this adapter release.');
+ return adapter;
+ }
+ logging('adapter.js shimming chrome.');
+ // Export to the adapter global object visible in the browser.
+ adapter.browserShim = chromeShim;
+
+ chromeShim.shimGetUserMedia(window);
+ chromeShim.shimMediaStream(window);
+ chromeShim.shimPeerConnection(window);
+ chromeShim.shimOnTrack(window);
+ chromeShim.shimAddTrackRemoveTrack(window);
+ chromeShim.shimGetSendersWithDtmf(window);
+ chromeShim.shimSenderReceiverGetStats(window);
+ chromeShim.fixNegotiationNeeded(window);
+
+ commonShim.shimRTCIceCandidate(window);
+ commonShim.shimConnectionState(window);
+ commonShim.shimMaxMessageSize(window);
+ commonShim.shimSendThrowTypeError(window);
+ commonShim.removeAllowExtmapMixed(window);
+ break;
+ case 'firefox':
+ if (!firefoxShim || !firefoxShim.shimPeerConnection || !options.shimFirefox) {
+ logging('Firefox shim is not included in this adapter release.');
+ return adapter;
+ }
+ logging('adapter.js shimming firefox.');
+ // Export to the adapter global object visible in the browser.
+ adapter.browserShim = firefoxShim;
+
+ firefoxShim.shimGetUserMedia(window);
+ firefoxShim.shimPeerConnection(window);
+ firefoxShim.shimOnTrack(window);
+ firefoxShim.shimRemoveStream(window);
+ firefoxShim.shimSenderGetStats(window);
+ firefoxShim.shimReceiverGetStats(window);
+ firefoxShim.shimRTCDataChannel(window);
+
+ commonShim.shimRTCIceCandidate(window);
+ commonShim.shimConnectionState(window);
+ commonShim.shimMaxMessageSize(window);
+ commonShim.shimSendThrowTypeError(window);
+ break;
+ case 'edge':
+ if (!edgeShim || !edgeShim.shimPeerConnection || !options.shimEdge) {
+ logging('MS edge shim is not included in this adapter release.');
+ return adapter;
+ }
+ logging('adapter.js shimming edge.');
+ // Export to the adapter global object visible in the browser.
+ adapter.browserShim = edgeShim;
+
+ edgeShim.shimGetUserMedia(window);
+ edgeShim.shimGetDisplayMedia(window);
+ edgeShim.shimPeerConnection(window);
+ edgeShim.shimReplaceTrack(window);
+
+ // the edge shim implements the full RTCIceCandidate object.
+
+ commonShim.shimMaxMessageSize(window);
+ commonShim.shimSendThrowTypeError(window);
+ break;
+ case 'safari':
+ if (!safariShim || !options.shimSafari) {
+ logging('Safari shim is not included in this adapter release.');
+ return adapter;
+ }
+ logging('adapter.js shimming safari.');
+ // Export to the adapter global object visible in the browser.
+ adapter.browserShim = safariShim;
+
+ safariShim.shimRTCIceServerUrls(window);
+ safariShim.shimCreateOfferLegacy(window);
+ safariShim.shimCallbacksAPI(window);
+ safariShim.shimLocalStreamsAPI(window);
+ safariShim.shimRemoteStreamsAPI(window);
+ safariShim.shimTrackEventTransceiver(window);
+ safariShim.shimGetUserMedia(window);
+
+ commonShim.shimRTCIceCandidate(window);
+ commonShim.shimMaxMessageSize(window);
+ commonShim.shimSendThrowTypeError(window);
+ commonShim.removeAllowExtmapMixed(window);
+ break;
+ default:
+ logging('Unsupported browser!');
+ break;
+ }
+
+ return adapter;
+}
+
+// Browser shims.
+
+},{"./chrome/chrome_shim":3,"./common_shim":6,"./edge/edge_shim":7,"./firefox/firefox_shim":11,"./safari/safari_shim":14,"./utils":15}],3:[function(require,module,exports){
+
+/*
+ * Copyright (c) 2016 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.
+ */
+/* eslint-env node */
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.shimGetDisplayMedia = exports.shimGetUserMedia = undefined;
+
+var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
+
+var _getusermedia = require('./getusermedia');
+
+Object.defineProperty(exports, 'shimGetUserMedia', {
+ enumerable: true,
+ get: function get() {
+ return _getusermedia.shimGetUserMedia;
+ }
+});
+
+var _getdisplaymedia = require('./getdisplaymedia');
+
+Object.defineProperty(exports, 'shimGetDisplayMedia', {
+ enumerable: true,
+ get: function get() {
+ return _getdisplaymedia.shimGetDisplayMedia;
+ }
+});
+exports.shimMediaStream = shimMediaStream;
+exports.shimOnTrack = shimOnTrack;
+exports.shimGetSendersWithDtmf = shimGetSendersWithDtmf;
+exports.shimSenderReceiverGetStats = shimSenderReceiverGetStats;
+exports.shimAddTrackRemoveTrackWithNative = shimAddTrackRemoveTrackWithNative;
+exports.shimAddTrackRemoveTrack = shimAddTrackRemoveTrack;
+exports.shimPeerConnection = shimPeerConnection;
+exports.fixNegotiationNeeded = fixNegotiationNeeded;
+
+var _utils = require('../utils.js');
+
+var utils = _interopRequireWildcard(_utils);
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
+
+/* iterates the stats graph recursively. */
+function walkStats(stats, base, resultSet) {
+ if (!base || resultSet.has(base.id)) {
+ return;
+ }
+ resultSet.set(base.id, base);
+ Object.keys(base).forEach(function (name) {
+ if (name.endsWith('Id')) {
+ walkStats(stats, stats.get(base[name]), resultSet);
+ } else if (name.endsWith('Ids')) {
+ base[name].forEach(function (id) {
+ walkStats(stats, stats.get(id), resultSet);
+ });
+ }
+ });
+}
+
+/* filter getStats for a sender/receiver track. */
+function filterStats(result, track, outbound) {
+ var streamStatsType = outbound ? 'outbound-rtp' : 'inbound-rtp';
+ var filteredResult = new Map();
+ if (track === null) {
+ return filteredResult;
+ }
+ var trackStats = [];
+ result.forEach(function (value) {
+ if (value.type === 'track' && value.trackIdentifier === track.id) {
+ trackStats.push(value);
+ }
+ });
+ trackStats.forEach(function (trackStat) {
+ result.forEach(function (stats) {
+ if (stats.type === streamStatsType && stats.trackId === trackStat.id) {
+ walkStats(result, stats, filteredResult);
+ }
+ });
+ });
+ return filteredResult;
+}
+
+function shimMediaStream(window) {
+ window.MediaStream = window.MediaStream || window.webkitMediaStream;
+}
+
+function shimOnTrack(window) {
+ if ((typeof window === 'undefined' ? 'undefined' : _typeof(window)) === 'object' && window.RTCPeerConnection && !('ontrack' in window.RTCPeerConnection.prototype)) {
+ Object.defineProperty(window.RTCPeerConnection.prototype, 'ontrack', {
+ get: function get() {
+ return this._ontrack;
+ },
+ set: function set(f) {
+ if (this._ontrack) {
+ this.removeEventListener('track', this._ontrack);
+ }
+ this.addEventListener('track', this._ontrack = f);
+ },
+
+ enumerable: true,
+ configurable: true
+ });
+ var origSetRemoteDescription = window.RTCPeerConnection.prototype.setRemoteDescription;
+ window.RTCPeerConnection.prototype.setRemoteDescription = function () {
+ var _this = this;
+
+ if (!this._ontrackpoly) {
+ this._ontrackpoly = function (e) {
+ // onaddstream does not fire when a track is added to an existing
+ // stream. But stream.onaddtrack is implemented so we use that.
+ e.stream.addEventListener('addtrack', function (te) {
+ var receiver = void 0;
+ if (window.RTCPeerConnection.prototype.getReceivers) {
+ receiver = _this.getReceivers().find(function (r) {
+ return r.track && r.track.id === te.track.id;
+ });
+ } else {
+ receiver = { track: te.track };
+ }
+
+ var event = new Event('track');
+ event.track = te.track;
+ event.receiver = receiver;
+ event.transceiver = { receiver: receiver };
+ event.streams = [e.stream];
+ _this.dispatchEvent(event);
+ });
+ e.stream.getTracks().forEach(function (track) {
+ var receiver = void 0;
+ if (window.RTCPeerConnection.prototype.getReceivers) {
+ receiver = _this.getReceivers().find(function (r) {
+ return r.track && r.track.id === track.id;
+ });
+ } else {
+ receiver = { track: track };
+ }
+ var event = new Event('track');
+ event.track = track;
+ event.receiver = receiver;
+ event.transceiver = { receiver: receiver };
+ event.streams = [e.stream];
+ _this.dispatchEvent(event);
+ });
+ };
+ this.addEventListener('addstream', this._ontrackpoly);
+ }
+ return origSetRemoteDescription.apply(this, arguments);
+ };
+ } else {
+ // even if RTCRtpTransceiver is in window, it is only used and
+ // emitted in unified-plan. Unfortunately this means we need
+ // to unconditionally wrap the event.
+ utils.wrapPeerConnectionEvent(window, 'track', function (e) {
+ if (!e.transceiver) {
+ Object.defineProperty(e, 'transceiver', { value: { receiver: e.receiver } });
+ }
+ return e;
+ });
+ }
+}
+
+function shimGetSendersWithDtmf(window) {
+ // Overrides addTrack/removeTrack, depends on shimAddTrackRemoveTrack.
+ if ((typeof window === 'undefined' ? 'undefined' : _typeof(window)) === 'object' && window.RTCPeerConnection && !('getSenders' in window.RTCPeerConnection.prototype) && 'createDTMFSender' in window.RTCPeerConnection.prototype) {
+ var shimSenderWithDtmf = function shimSenderWithDtmf(pc, track) {
+ return {
+ track: track,
+ get dtmf() {
+ if (this._dtmf === undefined) {
+ if (track.kind === 'audio') {
+ this._dtmf = pc.createDTMFSender(track);
+ } else {
+ this._dtmf = null;
+ }
+ }
+ return this._dtmf;
+ },
+ _pc: pc
+ };
+ };
+
+ // augment addTrack when getSenders is not available.
+ if (!window.RTCPeerConnection.prototype.getSenders) {
+ window.RTCPeerConnection.prototype.getSenders = function () {
+ this._senders = this._senders || [];
+ return this._senders.slice(); // return a copy of the internal state.
+ };
+ var origAddTrack = window.RTCPeerConnection.prototype.addTrack;
+ window.RTCPeerConnection.prototype.addTrack = function (track, stream) {
+ var sender = origAddTrack.apply(this, arguments);
+ if (!sender) {
+ sender = shimSenderWithDtmf(this, track);
+ this._senders.push(sender);
+ }
+ return sender;
+ };
+
+ var origRemoveTrack = window.RTCPeerConnection.prototype.removeTrack;
+ window.RTCPeerConnection.prototype.removeTrack = function (sender) {
+ origRemoveTrack.apply(this, arguments);
+ var idx = this._senders.indexOf(sender);
+ if (idx !== -1) {
+ this._senders.splice(idx, 1);
+ }
+ };
+ }
+ var origAddStream = window.RTCPeerConnection.prototype.addStream;
+ window.RTCPeerConnection.prototype.addStream = function (stream) {
+ var _this2 = this;
+
+ this._senders = this._senders || [];
+ origAddStream.apply(this, [stream]);
+ stream.getTracks().forEach(function (track) {
+ _this2._senders.push(shimSenderWithDtmf(_this2, track));
+ });
+ };
+
+ var origRemoveStream = window.RTCPeerConnection.prototype.removeStream;
+ window.RTCPeerConnection.prototype.removeStream = function (stream) {
+ var _this3 = this;
+
+ this._senders = this._senders || [];
+ origRemoveStream.apply(this, [stream]);
+
+ stream.getTracks().forEach(function (track) {
+ var sender = _this3._senders.find(function (s) {
+ return s.track === track;
+ });
+ if (sender) {
+ // remove sender
+ _this3._senders.splice(_this3._senders.indexOf(sender), 1);
+ }
+ });
+ };
+ } else if ((typeof window === 'undefined' ? 'undefined' : _typeof(window)) === 'object' && window.RTCPeerConnection && 'getSenders' in window.RTCPeerConnection.prototype && 'createDTMFSender' in window.RTCPeerConnection.prototype && window.RTCRtpSender && !('dtmf' in window.RTCRtpSender.prototype)) {
+ var origGetSenders = window.RTCPeerConnection.prototype.getSenders;
+ window.RTCPeerConnection.prototype.getSenders = function () {
+ var _this4 = this;
+
+ var senders = origGetSenders.apply(this, []);
+ senders.forEach(function (sender) {
+ return sender._pc = _this4;
+ });
+ return senders;
+ };
+
+ Object.defineProperty(window.RTCRtpSender.prototype, 'dtmf', {
+ get: function get() {
+ if (this._dtmf === undefined) {
+ if (this.track.kind === 'audio') {
+ this._dtmf = this._pc.createDTMFSender(this.track);
+ } else {
+ this._dtmf = null;
+ }
+ }
+ return this._dtmf;
+ }
+ });
+ }
+}
+
+function shimSenderReceiverGetStats(window) {
+ if (!((typeof window === 'undefined' ? 'undefined' : _typeof(window)) === 'object' && window.RTCPeerConnection && window.RTCRtpSender && window.RTCRtpReceiver)) {
+ return;
+ }
+
+ // shim sender stats.
+ if (!('getStats' in window.RTCRtpSender.prototype)) {
+ var origGetSenders = window.RTCPeerConnection.prototype.getSenders;
+ if (origGetSenders) {
+ window.RTCPeerConnection.prototype.getSenders = function () {
+ var _this5 = this;
+
+ var senders = origGetSenders.apply(this, []);
+ senders.forEach(function (sender) {
+ return sender._pc = _this5;
+ });
+ return senders;
+ };
+ }
+
+ var origAddTrack = window.RTCPeerConnection.prototype.addTrack;
+ if (origAddTrack) {
+ window.RTCPeerConnection.prototype.addTrack = function () {
+ var sender = origAddTrack.apply(this, arguments);
+ sender._pc = this;
+ return sender;
+ };
+ }
+ window.RTCRtpSender.prototype.getStats = function () {
+ var sender = this;
+ return this._pc.getStats().then(function (result) {
+ return (
+ /* Note: this will include stats of all senders that
+ * send a track with the same id as sender.track as
+ * it is not possible to identify the RTCRtpSender.
+ */
+ filterStats(result, sender.track, true)
+ );
+ });
+ };
+ }
+
+ // shim receiver stats.
+ if (!('getStats' in window.RTCRtpReceiver.prototype)) {
+ var origGetReceivers = window.RTCPeerConnection.prototype.getReceivers;
+ if (origGetReceivers) {
+ window.RTCPeerConnection.prototype.getReceivers = function () {
+ var _this6 = this;
+
+ var receivers = origGetReceivers.apply(this, []);
+ receivers.forEach(function (receiver) {
+ return receiver._pc = _this6;
+ });
+ return receivers;
+ };
+ }
+ utils.wrapPeerConnectionEvent(window, 'track', function (e) {
+ e.receiver._pc = e.srcElement;
+ return e;
+ });
+ window.RTCRtpReceiver.prototype.getStats = function () {
+ var receiver = this;
+ return this._pc.getStats().then(function (result) {
+ return filterStats(result, receiver.track, false);
+ });
+ };
+ }
+
+ if (!('getStats' in window.RTCRtpSender.prototype && 'getStats' in window.RTCRtpReceiver.prototype)) {
+ return;
+ }
+
+ // shim RTCPeerConnection.getStats(track).
+ var origGetStats = window.RTCPeerConnection.prototype.getStats;
+ window.RTCPeerConnection.prototype.getStats = function () {
+ if (arguments.length > 0 && arguments[0] instanceof window.MediaStreamTrack) {
+ var track = arguments[0];
+ var sender = void 0;
+ var receiver = void 0;
+ var err = void 0;
+ this.getSenders().forEach(function (s) {
+ if (s.track === track) {
+ if (sender) {
+ err = true;
+ } else {
+ sender = s;
+ }
+ }
+ });
+ this.getReceivers().forEach(function (r) {
+ if (r.track === track) {
+ if (receiver) {
+ err = true;
+ } else {
+ receiver = r;
+ }
+ }
+ return r.track === track;
+ });
+ if (err || sender && receiver) {
+ return Promise.reject(new DOMException('There are more than one sender or receiver for the track.', 'InvalidAccessError'));
+ } else if (sender) {
+ return sender.getStats();
+ } else if (receiver) {
+ return receiver.getStats();
+ }
+ return Promise.reject(new DOMException('There is no sender or receiver for the track.', 'InvalidAccessError'));
+ }
+ return origGetStats.apply(this, arguments);
+ };
+}
+
+function shimAddTrackRemoveTrackWithNative(window) {
+ // shim addTrack/removeTrack with native variants in order to make
+ // the interactions with legacy getLocalStreams behave as in other browsers.
+ // Keeps a mapping stream.id => [stream, rtpsenders...]
+ window.RTCPeerConnection.prototype.getLocalStreams = function () {
+ var _this7 = this;
+
+ this._shimmedLocalStreams = this._shimmedLocalStreams || {};
+ return Object.keys(this._shimmedLocalStreams).map(function (streamId) {
+ return _this7._shimmedLocalStreams[streamId][0];
+ });
+ };
+
+ var origAddTrack = window.RTCPeerConnection.prototype.addTrack;
+ window.RTCPeerConnection.prototype.addTrack = function (track, stream) {
+ if (!stream) {
+ return origAddTrack.apply(this, arguments);
+ }
+ this._shimmedLocalStreams = this._shimmedLocalStreams || {};
+
+ var sender = origAddTrack.apply(this, arguments);
+ if (!this._shimmedLocalStreams[stream.id]) {
+ this._shimmedLocalStreams[stream.id] = [stream, sender];
+ } else if (this._shimmedLocalStreams[stream.id].indexOf(sender) === -1) {
+ this._shimmedLocalStreams[stream.id].push(sender);
+ }
+ return sender;
+ };
+
+ var origAddStream = window.RTCPeerConnection.prototype.addStream;
+ window.RTCPeerConnection.prototype.addStream = function (stream) {
+ var _this8 = this;
+
+ this._shimmedLocalStreams = this._shimmedLocalStreams || {};
+
+ stream.getTracks().forEach(function (track) {
+ var alreadyExists = _this8.getSenders().find(function (s) {
+ return s.track === track;
+ });
+ if (alreadyExists) {
+ throw new DOMException('Track already exists.', 'InvalidAccessError');
+ }
+ });
+ var existingSenders = this.getSenders();
+ origAddStream.apply(this, arguments);
+ var newSenders = this.getSenders().filter(function (newSender) {
+ return existingSenders.indexOf(newSender) === -1;
+ });
+ this._shimmedLocalStreams[stream.id] = [stream].concat(newSenders);
+ };
+
+ var origRemoveStream = window.RTCPeerConnection.prototype.removeStream;
+ window.RTCPeerConnection.prototype.removeStream = function (stream) {
+ this._shimmedLocalStreams = this._shimmedLocalStreams || {};
+ delete this._shimmedLocalStreams[stream.id];
+ return origRemoveStream.apply(this, arguments);
+ };
+
+ var origRemoveTrack = window.RTCPeerConnection.prototype.removeTrack;
+ window.RTCPeerConnection.prototype.removeTrack = function (sender) {
+ var _this9 = this;
+
+ this._shimmedLocalStreams = this._shimmedLocalStreams || {};
+ if (sender) {
+ Object.keys(this._shimmedLocalStreams).forEach(function (streamId) {
+ var idx = _this9._shimmedLocalStreams[streamId].indexOf(sender);
+ if (idx !== -1) {
+ _this9._shimmedLocalStreams[streamId].splice(idx, 1);
+ }
+ if (_this9._shimmedLocalStreams[streamId].length === 1) {
+ delete _this9._shimmedLocalStreams[streamId];
+ }
+ });
+ }
+ return origRemoveTrack.apply(this, arguments);
+ };
+}
+
+function shimAddTrackRemoveTrack(window) {
+ if (!window.RTCPeerConnection) {
+ return;
+ }
+ var browserDetails = utils.detectBrowser(window);
+ // shim addTrack and removeTrack.
+ if (window.RTCPeerConnection.prototype.addTrack && browserDetails.version >= 65) {
+ return shimAddTrackRemoveTrackWithNative(window);
+ }
+
+ // also shim pc.getLocalStreams when addTrack is shimmed
+ // to return the original streams.
+ var origGetLocalStreams = window.RTCPeerConnection.prototype.getLocalStreams;
+ window.RTCPeerConnection.prototype.getLocalStreams = function () {
+ var _this10 = this;
+
+ var nativeStreams = origGetLocalStreams.apply(this);
+ this._reverseStreams = this._reverseStreams || {};
+ return nativeStreams.map(function (stream) {
+ return _this10._reverseStreams[stream.id];
+ });
+ };
+
+ var origAddStream = window.RTCPeerConnection.prototype.addStream;
+ window.RTCPeerConnection.prototype.addStream = function (stream) {
+ var _this11 = this;
+
+ this._streams = this._streams || {};
+ this._reverseStreams = this._reverseStreams || {};
+
+ stream.getTracks().forEach(function (track) {
+ var alreadyExists = _this11.getSenders().find(function (s) {
+ return s.track === track;
+ });
+ if (alreadyExists) {
+ throw new DOMException('Track already exists.', 'InvalidAccessError');
+ }
+ });
+ // Add identity mapping for consistency with addTrack.
+ // Unless this is being used with a stream from addTrack.
+ if (!this._reverseStreams[stream.id]) {
+ var newStream = new window.MediaStream(stream.getTracks());
+ this._streams[stream.id] = newStream;
+ this._reverseStreams[newStream.id] = stream;
+ stream = newStream;
+ }
+ origAddStream.apply(this, [stream]);
+ };
+
+ var origRemoveStream = window.RTCPeerConnection.prototype.removeStream;
+ window.RTCPeerConnection.prototype.removeStream = function (stream) {
+ this._streams = this._streams || {};
+ this._reverseStreams = this._reverseStreams || {};
+
+ origRemoveStream.apply(this, [this._streams[stream.id] || stream]);
+ delete this._reverseStreams[this._streams[stream.id] ? this._streams[stream.id].id : stream.id];
+ delete this._streams[stream.id];
+ };
+
+ window.RTCPeerConnection.prototype.addTrack = function (track, stream) {
+ var _this12 = this;
+
+ if (this.signalingState === 'closed') {
+ throw new DOMException('The RTCPeerConnection\'s signalingState is \'closed\'.', 'InvalidStateError');
+ }
+ var streams = [].slice.call(arguments, 1);
+ if (streams.length !== 1 || !streams[0].getTracks().find(function (t) {
+ return t === track;
+ })) {
+ // this is not fully correct but all we can manage without
+ // [[associated MediaStreams]] internal slot.
+ throw new DOMException('The adapter.js addTrack polyfill only supports a single ' + ' stream which is associated with the specified track.', 'NotSupportedError');
+ }
+
+ var alreadyExists = this.getSenders().find(function (s) {
+ return s.track === track;
+ });
+ if (alreadyExists) {
+ throw new DOMException('Track already exists.', 'InvalidAccessError');
+ }
+
+ this._streams = this._streams || {};
+ this._reverseStreams = this._reverseStreams || {};
+ var oldStream = this._streams[stream.id];
+ if (oldStream) {
+ // this is using odd Chrome behaviour, use with caution:
+ // https://bugs.chromium.org/p/webrtc/issues/detail?id=7815
+ // Note: we rely on the high-level addTrack/dtmf shim to
+ // create the sender with a dtmf sender.
+ oldStream.addTrack(track);
+
+ // Trigger ONN async.
+ Promise.resolve().then(function () {
+ _this12.dispatchEvent(new Event('negotiationneeded'));
+ });
+ } else {
+ var newStream = new window.MediaStream([track]);
+ this._streams[stream.id] = newStream;
+ this._reverseStreams[newStream.id] = stream;
+ this.addStream(newStream);
+ }
+ return this.getSenders().find(function (s) {
+ return s.track === track;
+ });
+ };
+
+ // replace the internal stream id with the external one and
+ // vice versa.
+ function replaceInternalStreamId(pc, description) {
+ var sdp = description.sdp;
+ Object.keys(pc._reverseStreams || []).forEach(function (internalId) {
+ var externalStream = pc._reverseStreams[internalId];
+ var internalStream = pc._streams[externalStream.id];
+ sdp = sdp.replace(new RegExp(internalStream.id, 'g'), externalStream.id);
+ });
+ return new RTCSessionDescription({
+ type: description.type,
+ sdp: sdp
+ });
+ }
+ function replaceExternalStreamId(pc, description) {
+ var sdp = description.sdp;
+ Object.keys(pc._reverseStreams || []).forEach(function (internalId) {
+ var externalStream = pc._reverseStreams[internalId];
+ var internalStream = pc._streams[externalStream.id];
+ sdp = sdp.replace(new RegExp(externalStream.id, 'g'), internalStream.id);
+ });
+ return new RTCSessionDescription({
+ type: description.type,
+ sdp: sdp
+ });
+ }
+ ['createOffer', 'createAnswer'].forEach(function (method) {
+ var nativeMethod = window.RTCPeerConnection.prototype[method];
+ window.RTCPeerConnection.prototype[method] = function () {
+ var _this13 = this;
+
+ var args = arguments;
+ var isLegacyCall = arguments.length && typeof arguments[0] === 'function';
+ if (isLegacyCall) {
+ return nativeMethod.apply(this, [function (description) {
+ var desc = replaceInternalStreamId(_this13, description);
+ args[0].apply(null, [desc]);
+ }, function (err) {
+ if (args[1]) {
+ args[1].apply(null, err);
+ }
+ }, arguments[2]]);
+ }
+ return nativeMethod.apply(this, arguments).then(function (description) {
+ return replaceInternalStreamId(_this13, description);
+ });
+ };
+ });
+
+ var origSetLocalDescription = window.RTCPeerConnection.prototype.setLocalDescription;
+ window.RTCPeerConnection.prototype.setLocalDescription = function () {
+ if (!arguments.length || !arguments[0].type) {
+ return origSetLocalDescription.apply(this, arguments);
+ }
+ arguments[0] = replaceExternalStreamId(this, arguments[0]);
+ return origSetLocalDescription.apply(this, arguments);
+ };
+
+ // TODO: mangle getStats: https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamstats-streamidentifier
+
+ var origLocalDescription = Object.getOwnPropertyDescriptor(window.RTCPeerConnection.prototype, 'localDescription');
+ Object.defineProperty(window.RTCPeerConnection.prototype, 'localDescription', {
+ get: function get() {
+ var description = origLocalDescription.get.apply(this);
+ if (description.type === '') {
+ return description;
+ }
+ return replaceInternalStreamId(this, description);
+ }
+ });
+
+ window.RTCPeerConnection.prototype.removeTrack = function (sender) {
+ var _this14 = this;
+
+ if (this.signalingState === 'closed') {
+ throw new DOMException('The RTCPeerConnection\'s signalingState is \'closed\'.', 'InvalidStateError');
+ }
+ // We can not yet check for sender instanceof RTCRtpSender
+ // since we shim RTPSender. So we check if sender._pc is set.
+ if (!sender._pc) {
+ throw new DOMException('Argument 1 of RTCPeerConnection.removeTrack ' + 'does not implement interface RTCRtpSender.', 'TypeError');
+ }
+ var isLocal = sender._pc === this;
+ if (!isLocal) {
+ throw new DOMException('Sender was not created by this connection.', 'InvalidAccessError');
+ }
+
+ // Search for the native stream the senders track belongs to.
+ this._streams = this._streams || {};
+ var stream = void 0;
+ Object.keys(this._streams).forEach(function (streamid) {
+ var hasTrack = _this14._streams[streamid].getTracks().find(function (track) {
+ return sender.track === track;
+ });
+ if (hasTrack) {
+ stream = _this14._streams[streamid];
+ }
+ });
+
+ if (stream) {
+ if (stream.getTracks().length === 1) {
+ // if this is the last track of the stream, remove the stream. This
+ // takes care of any shimmed _senders.
+ this.removeStream(this._reverseStreams[stream.id]);
+ } else {
+ // relying on the same odd chrome behaviour as above.
+ stream.removeTrack(sender.track);
+ }
+ this.dispatchEvent(new Event('negotiationneeded'));
+ }
+ };
+}
+
+function shimPeerConnection(window) {
+ if (!window.RTCPeerConnection && window.webkitRTCPeerConnection) {
+ // very basic support for old versions.
+ window.RTCPeerConnection = window.webkitRTCPeerConnection;
+ }
+ if (!window.RTCPeerConnection) {
+ return;
+ }
+
+ var origGetStats = window.RTCPeerConnection.prototype.getStats;
+ window.RTCPeerConnection.prototype.getStats = function (selector, successCallback, errorCallback) {
+ var _this15 = 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.apply(this, arguments);
+ }
+
+ // When spec-style getStats is supported, return those when called with
+ // either no arguments or the selector argument is null.
+ if (origGetStats.length === 0 && (arguments.length === 0 || typeof arguments[0] !== 'function')) {
+ return origGetStats.apply(this, []);
+ }
+
+ var fixChromeStats_ = function fixChromeStats_(response) {
+ var standardReport = {};
+ var reports = response.result();
+ reports.forEach(function (report) {
+ var standardStats = {
+ id: report.id,
+ timestamp: report.timestamp,
+ type: {
+ localcandidate: 'local-candidate',
+ remotecandidate: 'remote-candidate'
+ }[report.type] || report.type
+ };
+ report.names().forEach(function (name) {
+ standardStats[name] = report.stat(name);
+ });
+ standardReport[standardStats.id] = standardStats;
+ });
+
+ return standardReport;
+ };
+
+ // shim getStats with maplike support
+ var makeMapStats = function makeMapStats(stats) {
+ return new Map(Object.keys(stats).map(function (key) {
+ return [key, stats[key]];
+ }));
+ };
+
+ if (arguments.length >= 2) {
+ var successCallbackWrapper_ = function successCallbackWrapper_(response) {
+ args[1](makeMapStats(fixChromeStats_(response)));
+ };
+
+ return origGetStats.apply(this, [successCallbackWrapper_, arguments[0]]);
+ }
+
+ // promise-support
+ return new Promise(function (resolve, reject) {
+ origGetStats.apply(_this15, [function (response) {
+ resolve(makeMapStats(fixChromeStats_(response)));
+ }, reject]);
+ }).then(successCallback, errorCallback);
+ };
+
+ // shim implicit creation of RTCSessionDescription/RTCIceCandidate
+ ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate'].forEach(function (method) {
+ var nativeMethod = window.RTCPeerConnection.prototype[method];
+ window.RTCPeerConnection.prototype[method] = function () {
+ arguments[0] = new (method === 'addIceCandidate' ? window.RTCIceCandidate : window.RTCSessionDescription)(arguments[0]);
+ return nativeMethod.apply(this, arguments);
+ };
+ });
+
+ // support for addIceCandidate(null or undefined)
+ var nativeAddIceCandidate = window.RTCPeerConnection.prototype.addIceCandidate;
+ window.RTCPeerConnection.prototype.addIceCandidate = function () {
+ if (!arguments[0]) {
+ if (arguments[1]) {
+ arguments[1].apply(null);
+ }
+ return Promise.resolve();
+ }
+ return nativeAddIceCandidate.apply(this, arguments);
+ };
+}
+
+function fixNegotiationNeeded(window) {
+ utils.wrapPeerConnectionEvent(window, 'negotiationneeded', function (e) {
+ var pc = e.target;
+ if (pc.signalingState !== 'stable') {
+ return;
+ }
+ return e;
+ });
+}
+
+},{"../utils.js":15,"./getdisplaymedia":4,"./getusermedia":5}],4:[function(require,module,exports){
+/*
+ * Copyright (c) 2018 The adapter.js 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.
+ */
+/* eslint-env node */
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.shimGetDisplayMedia = shimGetDisplayMedia;
+function shimGetDisplayMedia(window, getSourceId) {
+ if (window.navigator.mediaDevices && 'getDisplayMedia' in window.navigator.mediaDevices) {
+ return;
+ }
+ if (!window.navigator.mediaDevices) {
+ return;
+ }
+ // getSourceId is a function that returns a promise resolving with
+ // the sourceId of the screen/window/tab to be shared.
+ if (typeof getSourceId !== 'function') {
+ console.error('shimGetDisplayMedia: getSourceId argument is not ' + 'a function');
+ return;
+ }
+ window.navigator.mediaDevices.getDisplayMedia = function (constraints) {
+ return getSourceId(constraints).then(function (sourceId) {
+ var widthSpecified = constraints.video && constraints.video.width;
+ var heightSpecified = constraints.video && constraints.video.height;
+ var frameRateSpecified = constraints.video && constraints.video.frameRate;
+ constraints.video = {
+ mandatory: {
+ chromeMediaSource: 'desktop',
+ chromeMediaSourceId: sourceId,
+ maxFrameRate: frameRateSpecified || 3
+ }
+ };
+ if (widthSpecified) {
+ constraints.video.mandatory.maxWidth = widthSpecified;
+ }
+ if (heightSpecified) {
+ constraints.video.mandatory.maxHeight = heightSpecified;
+ }
+ return window.navigator.mediaDevices.getUserMedia(constraints);
+ });
+ };
+}
+
+},{}],5:[function(require,module,exports){
+/*
+ * Copyright (c) 2016 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.
+ */
+/* eslint-env node */
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
+
+exports.shimGetUserMedia = shimGetUserMedia;
+
+var _utils = require('../utils.js');
+
+var utils = _interopRequireWildcard(_utils);
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
+
+var logging = utils.log;
+
+function shimGetUserMedia(window) {
+ var navigator = window && window.navigator;
+
+ if (!navigator.mediaDevices) {
+ return;
+ }
+
+ var browserDetails = utils.detectBrowser(window);
+
+ var constraintsToChrome_ = function constraintsToChrome_(c) {
+ if ((typeof c === 'undefined' ? 'undefined' : _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 oldname_(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;
+ };
+
+ var shimConstraints_ = function shimConstraints_(constraints, func) {
+ if (browserDetails.version >= 61) {
+ return func(constraints);
+ }
+ constraints = JSON.parse(JSON.stringify(constraints));
+ if (constraints && _typeof(constraints.audio) === 'object') {
+ var remap = function remap(obj, a, b) {
+ if (a in obj && !(b in obj)) {
+ obj[b] = obj[a];
+ delete obj[a];
+ }
+ };
+ constraints = JSON.parse(JSON.stringify(constraints));
+ remap(constraints.audio, 'autoGainControl', 'googAutoGainControl');
+ remap(constraints.audio, 'noiseSuppression', 'googNoiseSuppression');
+ constraints.audio = constraintsToChrome_(constraints.audio);
+ }
+ if (constraints && _typeof(constraints.video) === 'object') {
+ // Shim facingMode for mobile & surface pro.
+ var face = constraints.video.facingMode;
+ face = face && ((typeof face === 'undefined' ? 'undefined' : _typeof(face)) === 'object' ? face : { ideal: face });
+ var getSupportedFacingModeLies = browserDetails.version < 66;
+
+ if (face && (face.exact === 'user' || face.exact === 'environment' || face.ideal === 'user' || face.ideal === 'environment') && !(navigator.mediaDevices.getSupportedConstraints && navigator.mediaDevices.getSupportedConstraints().facingMode && !getSupportedFacingModeLies)) {
+ delete constraints.video.facingMode;
+ var matches = void 0;
+ if (face.exact === 'environment' || face.ideal === 'environment') {
+ matches = ['back', 'rear'];
+ } else if (face.exact === 'user' || face.ideal === 'user') {
+ matches = ['front'];
+ }
+ if (matches) {
+ // Look for matches in label, or use last cam for back (typical).
+ return navigator.mediaDevices.enumerateDevices().then(function (devices) {
+ devices = devices.filter(function (d) {
+ return d.kind === 'videoinput';
+ });
+ var dev = devices.find(function (d) {
+ return matches.some(function (match) {
+ return d.label.toLowerCase().includes(match);
+ });
+ });
+ if (!dev && devices.length && matches.includes('back')) {
+ dev = devices[devices.length - 1]; // more likely the back cam
+ }
+ if (dev) {
+ constraints.video.deviceId = face.exact ? { exact: dev.deviceId } : { ideal: dev.deviceId };
+ }
+ constraints.video = constraintsToChrome_(constraints.video);
+ logging('chrome: ' + JSON.stringify(constraints));
+ return func(constraints);
+ });
+ }
+ }
+ constraints.video = constraintsToChrome_(constraints.video);
+ }
+ logging('chrome: ' + JSON.stringify(constraints));
+ return func(constraints);
+ };
+
+ var shimError_ = function shimError_(e) {
+ if (browserDetails.version >= 64) {
+ return e;
+ }
+ return {
+ name: {
+ PermissionDeniedError: 'NotAllowedError',
+ PermissionDismissedError: 'NotAllowedError',
+ InvalidStateError: 'NotAllowedError',
+ DevicesNotFoundError: 'NotFoundError',
+ ConstraintNotSatisfiedError: 'OverconstrainedError',
+ TrackStartError: 'NotReadableError',
+ MediaDeviceFailedDueToShutdown: 'NotAllowedError',
+ MediaDeviceKillSwitchOn: 'NotAllowedError',
+ TabCaptureError: 'AbortError',
+ ScreenCaptureError: 'AbortError',
+ DeviceCaptureError: 'AbortError'
+ }[e.name] || e.name,
+ message: e.message,
+ constraint: e.constraint || e.constraintName,
+ toString: function toString() {
+ return this.name + (this.message && ': ') + this.message;
+ }
+ };
+ };
+
+ var getUserMedia_ = function getUserMedia_(constraints, onSuccess, onError) {
+ shimConstraints_(constraints, function (c) {
+ navigator.webkitGetUserMedia(c, onSuccess, function (e) {
+ if (onError) {
+ onError(shimError_(e));
+ }
+ });
+ });
+ };
+ navigator.getUserMedia = getUserMedia_.bind(navigator);
+
+ // 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 (cs) {
+ return shimConstraints_(cs, function (c) {
+ return origGetUserMedia(c).then(function (stream) {
+ if (c.audio && !stream.getAudioTracks().length || c.video && !stream.getVideoTracks().length) {
+ stream.getTracks().forEach(function (track) {
+ track.stop();
+ });
+ throw new DOMException('', 'NotFoundError');
+ }
+ return stream;
+ }, function (e) {
+ return Promise.reject(shimError_(e));
+ });
+ });
+ };
+}
+
+},{"../utils.js":15}],6:[function(require,module,exports){
+/*
+ * Copyright (c) 2017 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.
+ */
+/* eslint-env node */
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
+
+exports.shimRTCIceCandidate = shimRTCIceCandidate;
+exports.shimMaxMessageSize = shimMaxMessageSize;
+exports.shimSendThrowTypeError = shimSendThrowTypeError;
+exports.shimConnectionState = shimConnectionState;
+exports.removeAllowExtmapMixed = removeAllowExtmapMixed;
+
+var _sdp = require('sdp');
+
+var _sdp2 = _interopRequireDefault(_sdp);
+
+var _utils = require('./utils');
+
+var utils = _interopRequireWildcard(_utils);
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function shimRTCIceCandidate(window) {
+ // foundation is arbitrarily chosen as an indicator for full support for
+ // https://w3c.github.io/webrtc-pc/#rtcicecandidate-interface
+ if (!window.RTCIceCandidate || window.RTCIceCandidate && 'foundation' in window.RTCIceCandidate.prototype) {
+ return;
+ }
+
+ var NativeRTCIceCandidate = window.RTCIceCandidate;
+ window.RTCIceCandidate = function (args) {
+ // Remove the a= which shouldn't be part of the candidate string.
+ if ((typeof args === 'undefined' ? 'undefined' : _typeof(args)) === 'object' && args.candidate && args.candidate.indexOf('a=') === 0) {
+ args = JSON.parse(JSON.stringify(args));
+ args.candidate = args.candidate.substr(2);
+ }
+
+ if (args.candidate && args.candidate.length) {
+ // Augment the native candidate with the parsed fields.
+ var nativeCandidate = new NativeRTCIceCandidate(args);
+ var parsedCandidate = _sdp2.default.parseCandidate(args.candidate);
+ var augmentedCandidate = Object.assign(nativeCandidate, parsedCandidate);
+
+ // Add a serializer that does not serialize the extra attributes.
+ augmentedCandidate.toJSON = function () {
+ return {
+ candidate: augmentedCandidate.candidate,
+ sdpMid: augmentedCandidate.sdpMid,
+ sdpMLineIndex: augmentedCandidate.sdpMLineIndex,
+ usernameFragment: augmentedCandidate.usernameFragment
+ };
+ };
+ return augmentedCandidate;
+ }
+ return new NativeRTCIceCandidate(args);
+ };
+ window.RTCIceCandidate.prototype = NativeRTCIceCandidate.prototype;
+
+ // Hook up the augmented candidate in onicecandidate and
+ // addEventListener('icecandidate', ...)
+ utils.wrapPeerConnectionEvent(window, 'icecandidate', function (e) {
+ if (e.candidate) {
+ Object.defineProperty(e, 'candidate', {
+ value: new window.RTCIceCandidate(e.candidate),
+ writable: 'false'
+ });
+ }
+ return e;
+ });
+}
+
+function shimMaxMessageSize(window) {
+ if (window.RTCSctpTransport || !window.RTCPeerConnection) {
+ return;
+ }
+ var browserDetails = utils.detectBrowser(window);
+
+ if (!('sctp' in window.RTCPeerConnection.prototype)) {
+ Object.defineProperty(window.RTCPeerConnection.prototype, 'sctp', {
+ get: function get() {
+ return typeof this._sctp === 'undefined' ? null : this._sctp;
+ }
+ });
+ }
+
+ var sctpInDescription = function sctpInDescription(description) {
+ var sections = _sdp2.default.splitSections(description.sdp);
+ sections.shift();
+ return sections.some(function (mediaSection) {
+ var mLine = _sdp2.default.parseMLine(mediaSection);
+ return mLine && mLine.kind === 'application' && mLine.protocol.indexOf('SCTP') !== -1;
+ });
+ };
+
+ var getRemoteFirefoxVersion = function getRemoteFirefoxVersion(description) {
+ // TODO: Is there a better solution for detecting Firefox?
+ var match = description.sdp.match(/mozilla...THIS_IS_SDPARTA-(\d+)/);
+ if (match === null || match.length < 2) {
+ return -1;
+ }
+ var version = parseInt(match[1], 10);
+ // Test for NaN (yes, this is ugly)
+ return version !== version ? -1 : version;
+ };
+
+ var getCanSendMaxMessageSize = function getCanSendMaxMessageSize(remoteIsFirefox) {
+ // Every implementation we know can send at least 64 KiB.
+ // Note: Although Chrome is technically able to send up to 256 KiB, the
+ // data does not reach the other peer reliably.
+ // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=8419
+ var canSendMaxMessageSize = 65536;
+ if (browserDetails.browser === 'firefox') {
+ if (browserDetails.version < 57) {
+ if (remoteIsFirefox === -1) {
+ // FF < 57 will send in 16 KiB chunks using the deprecated PPID
+ // fragmentation.
+ canSendMaxMessageSize = 16384;
+ } else {
+ // However, other FF (and RAWRTC) can reassemble PPID-fragmented
+ // messages. Thus, supporting ~2 GiB when sending.
+ canSendMaxMessageSize = 2147483637;
+ }
+ } else if (browserDetails.version < 60) {
+ // Currently, all FF >= 57 will reset the remote maximum message size
+ // to the default value when a data channel is created at a later
+ // stage. :(
+ // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1426831
+ canSendMaxMessageSize = browserDetails.version === 57 ? 65535 : 65536;
+ } else {
+ // FF >= 60 supports sending ~2 GiB
+ canSendMaxMessageSize = 2147483637;
+ }
+ }
+ return canSendMaxMessageSize;
+ };
+
+ var getMaxMessageSize = function getMaxMessageSize(description, remoteIsFirefox) {
+ // Note: 65536 bytes is the default value from the SDP spec. Also,
+ // every implementation we know supports receiving 65536 bytes.
+ var maxMessageSize = 65536;
+
+ // FF 57 has a slightly incorrect default remote max message size, so
+ // we need to adjust it here to avoid a failure when sending.
+ // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1425697
+ if (browserDetails.browser === 'firefox' && browserDetails.version === 57) {
+ maxMessageSize = 65535;
+ }
+
+ var match = _sdp2.default.matchPrefix(description.sdp, 'a=max-message-size:');
+ if (match.length > 0) {
+ maxMessageSize = parseInt(match[0].substr(19), 10);
+ } else if (browserDetails.browser === 'firefox' && remoteIsFirefox !== -1) {
+ // If the maximum message size is not present in the remote SDP and
+ // both local and remote are Firefox, the remote peer can receive
+ // ~2 GiB.
+ maxMessageSize = 2147483637;
+ }
+ return maxMessageSize;
+ };
+
+ var origSetRemoteDescription = window.RTCPeerConnection.prototype.setRemoteDescription;
+ window.RTCPeerConnection.prototype.setRemoteDescription = function () {
+ this._sctp = null;
+
+ if (sctpInDescription(arguments[0])) {
+ // Check if the remote is FF.
+ var isFirefox = getRemoteFirefoxVersion(arguments[0]);
+
+ // Get the maximum message size the local peer is capable of sending
+ var canSendMMS = getCanSendMaxMessageSize(isFirefox);
+
+ // Get the maximum message size of the remote peer.
+ var remoteMMS = getMaxMessageSize(arguments[0], isFirefox);
+
+ // Determine final maximum message size
+ var maxMessageSize = void 0;
+ if (canSendMMS === 0 && remoteMMS === 0) {
+ maxMessageSize = Number.POSITIVE_INFINITY;
+ } else if (canSendMMS === 0 || remoteMMS === 0) {
+ maxMessageSize = Math.max(canSendMMS, remoteMMS);
+ } else {
+ maxMessageSize = Math.min(canSendMMS, remoteMMS);
+ }
+
+ // Create a dummy RTCSctpTransport object and the 'maxMessageSize'
+ // attribute.
+ var sctp = {};
+ Object.defineProperty(sctp, 'maxMessageSize', {
+ get: function get() {
+ return maxMessageSize;
+ }
+ });
+ this._sctp = sctp;
+ }
+
+ return origSetRemoteDescription.apply(this, arguments);
+ };
+}
+
+function shimSendThrowTypeError(window) {
+ if (!(window.RTCPeerConnection && 'createDataChannel' in window.RTCPeerConnection.prototype)) {
+ return;
+ }
+
+ // Note: Although Firefox >= 57 has a native implementation, the maximum
+ // message size can be reset for all data channels at a later stage.
+ // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1426831
+
+ function wrapDcSend(dc, pc) {
+ var origDataChannelSend = dc.send;
+ dc.send = function () {
+ var data = arguments[0];
+ var length = data.length || data.size || data.byteLength;
+ if (dc.readyState === 'open' && pc.sctp && length > pc.sctp.maxMessageSize) {
+ throw new TypeError('Message too large (can send a maximum of ' + pc.sctp.maxMessageSize + ' bytes)');
+ }
+ return origDataChannelSend.apply(dc, arguments);
+ };
+ }
+ var origCreateDataChannel = window.RTCPeerConnection.prototype.createDataChannel;
+ window.RTCPeerConnection.prototype.createDataChannel = function () {
+ var dataChannel = origCreateDataChannel.apply(this, arguments);
+ wrapDcSend(dataChannel, this);
+ return dataChannel;
+ };
+ utils.wrapPeerConnectionEvent(window, 'datachannel', function (e) {
+ wrapDcSend(e.channel, e.target);
+ return e;
+ });
+}
+
+/* shims RTCConnectionState by pretending it is the same as iceConnectionState.
+ * See https://bugs.chromium.org/p/webrtc/issues/detail?id=6145#c12
+ * for why this is a valid hack in Chrome. In Firefox it is slightly incorrect
+ * since DTLS failures would be hidden. See
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=1265827
+ * for the Firefox tracking bug.
+ */
+function shimConnectionState(window) {
+ if (!window.RTCPeerConnection || 'connectionState' in window.RTCPeerConnection.prototype) {
+ return;
+ }
+ var proto = window.RTCPeerConnection.prototype;
+ Object.defineProperty(proto, 'connectionState', {
+ get: function get() {
+ return {
+ completed: 'connected',
+ checking: 'connecting'
+ }[this.iceConnectionState] || this.iceConnectionState;
+ },
+
+ enumerable: true,
+ configurable: true
+ });
+ Object.defineProperty(proto, 'onconnectionstatechange', {
+ get: function get() {
+ return this._onconnectionstatechange || null;
+ },
+ set: function set(cb) {
+ if (this._onconnectionstatechange) {
+ this.removeEventListener('connectionstatechange', this._onconnectionstatechange);
+ delete this._onconnectionstatechange;
+ }
+ if (cb) {
+ this.addEventListener('connectionstatechange', this._onconnectionstatechange = cb);
+ }
+ },
+
+ enumerable: true,
+ configurable: true
+ });
+
+ ['setLocalDescription', 'setRemoteDescription'].forEach(function (method) {
+ var origMethod = proto[method];
+ proto[method] = function () {
+ if (!this._connectionstatechangepoly) {
+ this._connectionstatechangepoly = function (e) {
+ var pc = e.target;
+ if (pc._lastConnectionState !== pc.connectionState) {
+ pc._lastConnectionState = pc.connectionState;
+ var newEvent = new Event('connectionstatechange', e);
+ pc.dispatchEvent(newEvent);
+ }
+ return e;
+ };
+ this.addEventListener('iceconnectionstatechange', this._connectionstatechangepoly);
+ }
+ return origMethod.apply(this, arguments);
+ };
+ });
+}
+
+function removeAllowExtmapMixed(window) {
+ /* remove a=extmap-allow-mixed for Chrome < M71 */
+ if (!window.RTCPeerConnection) {
+ return;
+ }
+ var browserDetails = utils.detectBrowser(window);
+ if (browserDetails.browser === 'chrome' && browserDetails.version >= 71) {
+ return;
+ }
+ var nativeSRD = window.RTCPeerConnection.prototype.setRemoteDescription;
+ window.RTCPeerConnection.prototype.setRemoteDescription = function (desc) {
+ if (desc && desc.sdp && desc.sdp.indexOf('\na=extmap-allow-mixed') !== -1) {
+ desc.sdp = desc.sdp.split('\n').filter(function (line) {
+ return line.trim() !== 'a=extmap-allow-mixed';
+ }).join('\n');
+ }
+ return nativeSRD.apply(this, arguments);
+ };
+}
+
+},{"./utils":15,"sdp":17}],7:[function(require,module,exports){
+/*
+ * Copyright (c) 2016 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.
+ */
+/* eslint-env node */
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.shimGetDisplayMedia = exports.shimGetUserMedia = undefined;
+
+var _getusermedia = require('./getusermedia');
+
+Object.defineProperty(exports, 'shimGetUserMedia', {
+ enumerable: true,
+ get: function get() {
+ return _getusermedia.shimGetUserMedia;
+ }
+});
+
+var _getdisplaymedia = require('./getdisplaymedia');
+
+Object.defineProperty(exports, 'shimGetDisplayMedia', {
+ enumerable: true,
+ get: function get() {
+ return _getdisplaymedia.shimGetDisplayMedia;
+ }
+});
+exports.shimPeerConnection = shimPeerConnection;
+exports.shimReplaceTrack = shimReplaceTrack;
+
+var _utils = require('../utils');
+
+var utils = _interopRequireWildcard(_utils);
+
+var _filtericeservers = require('./filtericeservers');
+
+var _rtcpeerconnectionShim = require('rtcpeerconnection-shim');
+
+var _rtcpeerconnectionShim2 = _interopRequireDefault(_rtcpeerconnectionShim);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
+
+function shimPeerConnection(window) {
+ var browserDetails = utils.detectBrowser(window);
+
+ if (window.RTCIceGatherer) {
+ if (!window.RTCIceCandidate) {
+ window.RTCIceCandidate = function (args) {
+ return args;
+ };
+ }
+ if (!window.RTCSessionDescription) {
+ window.RTCSessionDescription = function (args) {
+ return args;
+ };
+ }
+ // this adds an additional event listener to MediaStrackTrack that signals
+ // when a tracks enabled property was changed. Workaround for a bug in
+ // addStream, see below. No longer required in 15025+
+ if (browserDetails.version < 15025) {
+ var origMSTEnabled = Object.getOwnPropertyDescriptor(window.MediaStreamTrack.prototype, 'enabled');
+ Object.defineProperty(window.MediaStreamTrack.prototype, 'enabled', {
+ set: function set(value) {
+ origMSTEnabled.set.call(this, value);
+ var ev = new Event('enabled');
+ ev.enabled = value;
+ this.dispatchEvent(ev);
+ }
+ });
+ }
+ }
+
+ // ORTC defines the DTMF sender a bit different.
+ // https://github.com/w3c/ortc/issues/714
+ if (window.RTCRtpSender && !('dtmf' in window.RTCRtpSender.prototype)) {
+ Object.defineProperty(window.RTCRtpSender.prototype, 'dtmf', {
+ get: function get() {
+ if (this._dtmf === undefined) {
+ if (this.track.kind === 'audio') {
+ this._dtmf = new window.RTCDtmfSender(this);
+ } else if (this.track.kind === 'video') {
+ this._dtmf = null;
+ }
+ }
+ return this._dtmf;
+ }
+ });
+ }
+ // Edge currently only implements the RTCDtmfSender, not the
+ // RTCDTMFSender alias. See http://draft.ortc.org/#rtcdtmfsender2*
+ if (window.RTCDtmfSender && !window.RTCDTMFSender) {
+ window.RTCDTMFSender = window.RTCDtmfSender;
+ }
+
+ var RTCPeerConnectionShim = (0, _rtcpeerconnectionShim2.default)(window, browserDetails.version);
+ window.RTCPeerConnection = function (config) {
+ if (config && config.iceServers) {
+ config.iceServers = (0, _filtericeservers.filterIceServers)(config.iceServers, browserDetails.version);
+ utils.log('ICE servers after filtering:', config.iceServers);
+ }
+ return new RTCPeerConnectionShim(config);
+ };
+ window.RTCPeerConnection.prototype = RTCPeerConnectionShim.prototype;
+}
+
+function shimReplaceTrack(window) {
+ // ORTC has replaceTrack -- https://github.com/w3c/ortc/issues/614
+ if (window.RTCRtpSender && !('replaceTrack' in window.RTCRtpSender.prototype)) {
+ window.RTCRtpSender.prototype.replaceTrack = window.RTCRtpSender.prototype.setTrack;
+ }
+}
+
+},{"../utils":15,"./filtericeservers":8,"./getdisplaymedia":9,"./getusermedia":10,"rtcpeerconnection-shim":16}],8:[function(require,module,exports){
+/*
+ * Copyright (c) 2018 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.
+ */
+/* eslint-env node */
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.filterIceServers = filterIceServers;
+
+var _utils = require('../utils');
+
+var utils = _interopRequireWildcard(_utils);
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
+
+// Edge does not like
+// 1) stun: filtered after 14393 unless ?transport=udp is present
+// 2) turn: that does not have all of turn:host:port?transport=udp
+// 3) turn: with ipv6 addresses
+// 4) turn: occurring muliple times
+function filterIceServers(iceServers, edgeVersion) {
+ var hasTurn = false;
+ iceServers = JSON.parse(JSON.stringify(iceServers));
+ return iceServers.filter(function (server) {
+ if (server && (server.urls || server.url)) {
+ var urls = server.urls || server.url;
+ if (server.url && !server.urls) {
+ utils.deprecated('RTCIceServer.url', 'RTCIceServer.urls');
+ }
+ var isString = typeof urls === 'string';
+ if (isString) {
+ urls = [urls];
+ }
+ urls = urls.filter(function (url) {
+ // filter STUN unconditionally.
+ if (url.indexOf('stun:') === 0) {
+ return false;
+ }
+
+ var validTurn = url.startsWith('turn') && !url.startsWith('turn:[') && url.includes('transport=udp');
+ if (validTurn && !hasTurn) {
+ hasTurn = true;
+ return true;
+ }
+ return validTurn && !hasTurn;
+ });
+
+ delete server.url;
+ server.urls = isString ? urls[0] : urls;
+ return !!urls.length;
+ }
+ });
+}
+
+},{"../utils":15}],9:[function(require,module,exports){
+/*
+ * Copyright (c) 2018 The adapter.js 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.
+ */
+/* eslint-env node */
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.shimGetDisplayMedia = shimGetDisplayMedia;
+function shimGetDisplayMedia(window) {
+ if (!('getDisplayMedia' in window.navigator)) {
+ return;
+ }
+ if (!window.navigator.mediaDevices) {
+ return;
+ }
+ if (window.navigator.mediaDevices && 'getDisplayMedia' in window.navigator.mediaDevices) {
+ return;
+ }
+ window.navigator.mediaDevices.getDisplayMedia = window.navigator.getDisplayMedia.bind(window.navigator.mediaDevices);
+}
+
+},{}],10:[function(require,module,exports){
+/*
+ * Copyright (c) 2016 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.
+ */
+/* eslint-env node */
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.shimGetUserMedia = shimGetUserMedia;
+function shimGetUserMedia(window) {
+ var navigator = window && window.navigator;
+
+ var shimError_ = function shimError_(e) {
+ return {
+ name: { PermissionDeniedError: 'NotAllowedError' }[e.name] || e.name,
+ message: e.message,
+ constraint: e.constraint,
+ toString: function toString() {
+ return this.name;
+ }
+ };
+ };
+
+ // getUserMedia error shim.
+ var origGetUserMedia = navigator.mediaDevices.getUserMedia.bind(navigator.mediaDevices);
+ navigator.mediaDevices.getUserMedia = function (c) {
+ return origGetUserMedia(c).catch(function (e) {
+ return Promise.reject(shimError_(e));
+ });
+ };
+}
+
+},{}],11:[function(require,module,exports){
+/*
+ * Copyright (c) 2016 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.
+ */
+/* eslint-env node */
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.shimGetDisplayMedia = exports.shimGetUserMedia = undefined;
+
+var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
+
+var _getusermedia = require('./getusermedia');
+
+Object.defineProperty(exports, 'shimGetUserMedia', {
+ enumerable: true,
+ get: function get() {
+ return _getusermedia.shimGetUserMedia;
+ }
+});
+
+var _getdisplaymedia = require('./getdisplaymedia');
+
+Object.defineProperty(exports, 'shimGetDisplayMedia', {
+ enumerable: true,
+ get: function get() {
+ return _getdisplaymedia.shimGetDisplayMedia;
+ }
+});
+exports.shimOnTrack = shimOnTrack;
+exports.shimPeerConnection = shimPeerConnection;
+exports.shimSenderGetStats = shimSenderGetStats;
+exports.shimReceiverGetStats = shimReceiverGetStats;
+exports.shimRemoveStream = shimRemoveStream;
+exports.shimRTCDataChannel = shimRTCDataChannel;
+
+var _utils = require('../utils');
+
+var utils = _interopRequireWildcard(_utils);
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
+
+function shimOnTrack(window) {
+ if ((typeof window === 'undefined' ? 'undefined' : _typeof(window)) === 'object' && window.RTCTrackEvent && 'receiver' in window.RTCTrackEvent.prototype && !('transceiver' in window.RTCTrackEvent.prototype)) {
+ Object.defineProperty(window.RTCTrackEvent.prototype, 'transceiver', {
+ get: function get() {
+ return { receiver: this.receiver };
+ }
+ });
+ }
+}
+
+function shimPeerConnection(window) {
+ var browserDetails = utils.detectBrowser(window);
+
+ if ((typeof window === 'undefined' ? 'undefined' : _typeof(window)) !== 'object' || !(window.RTCPeerConnection || window.mozRTCPeerConnection)) {
+ return; // probably media.peerconnection.enabled=false in about:config
+ }
+ if (!window.RTCPeerConnection && window.mozRTCPeerConnection) {
+ // very basic support for old versions.
+ window.RTCPeerConnection = window.mozRTCPeerConnection;
+ }
+
+ // shim away need for obsolete RTCIceCandidate/RTCSessionDescription.
+ ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate'].forEach(function (method) {
+ var nativeMethod = window.RTCPeerConnection.prototype[method];
+ window.RTCPeerConnection.prototype[method] = function () {
+ arguments[0] = new (method === 'addIceCandidate' ? window.RTCIceCandidate : window.RTCSessionDescription)(arguments[0]);
+ return nativeMethod.apply(this, arguments);
+ };
+ });
+
+ // support for addIceCandidate(null or undefined)
+ var nativeAddIceCandidate = window.RTCPeerConnection.prototype.addIceCandidate;
+ window.RTCPeerConnection.prototype.addIceCandidate = function () {
+ if (!arguments[0]) {
+ if (arguments[1]) {
+ arguments[1].apply(null);
+ }
+ return Promise.resolve();
+ }
+ return nativeAddIceCandidate.apply(this, arguments);
+ };
+
+ var modernStatsTypes = {
+ inboundrtp: 'inbound-rtp',
+ outboundrtp: 'outbound-rtp',
+ candidatepair: 'candidate-pair',
+ localcandidate: 'local-candidate',
+ remotecandidate: 'remote-candidate'
+ };
+
+ var nativeGetStats = window.RTCPeerConnection.prototype.getStats;
+ window.RTCPeerConnection.prototype.getStats = function (selector, onSucc, onErr) {
+ return nativeGetStats.apply(this, [selector || null]).then(function (stats) {
+ if (browserDetails.version < 53 && !onSucc) {
+ // Shim only promise getStats with spec-hyphens in type names
+ // Leave callback version alone; misc old uses of forEach before Map
+ try {
+ stats.forEach(function (stat) {
+ stat.type = modernStatsTypes[stat.type] || stat.type;
+ });
+ } catch (e) {
+ if (e.name !== 'TypeError') {
+ throw e;
+ }
+ // Avoid TypeError: "type" is read-only, in old versions. 34-43ish
+ stats.forEach(function (stat, i) {
+ stats.set(i, Object.assign({}, stat, {
+ type: modernStatsTypes[stat.type] || stat.type
+ }));
+ });
+ }
+ }
+ return stats;
+ }).then(onSucc, onErr);
+ };
+}
+
+function shimSenderGetStats(window) {
+ if (!((typeof window === 'undefined' ? 'undefined' : _typeof(window)) === 'object' && window.RTCPeerConnection && window.RTCRtpSender)) {
+ return;
+ }
+ if (window.RTCRtpSender && 'getStats' in window.RTCRtpSender.prototype) {
+ return;
+ }
+ var origGetSenders = window.RTCPeerConnection.prototype.getSenders;
+ if (origGetSenders) {
+ window.RTCPeerConnection.prototype.getSenders = function () {
+ var _this = this;
+
+ var senders = origGetSenders.apply(this, []);
+ senders.forEach(function (sender) {
+ return sender._pc = _this;
+ });
+ return senders;
+ };
+ }
+
+ var origAddTrack = window.RTCPeerConnection.prototype.addTrack;
+ if (origAddTrack) {
+ window.RTCPeerConnection.prototype.addTrack = function () {
+ var sender = origAddTrack.apply(this, arguments);
+ sender._pc = this;
+ return sender;
+ };
+ }
+ window.RTCRtpSender.prototype.getStats = function () {
+ return this.track ? this._pc.getStats(this.track) : Promise.resolve(new Map());
+ };
+}
+
+function shimReceiverGetStats(window) {
+ if (!((typeof window === 'undefined' ? 'undefined' : _typeof(window)) === 'object' && window.RTCPeerConnection && window.RTCRtpSender)) {
+ return;
+ }
+ if (window.RTCRtpSender && 'getStats' in window.RTCRtpReceiver.prototype) {
+ return;
+ }
+ var origGetReceivers = window.RTCPeerConnection.prototype.getReceivers;
+ if (origGetReceivers) {
+ window.RTCPeerConnection.prototype.getReceivers = function () {
+ var _this2 = this;
+
+ var receivers = origGetReceivers.apply(this, []);
+ receivers.forEach(function (receiver) {
+ return receiver._pc = _this2;
+ });
+ return receivers;
+ };
+ }
+ utils.wrapPeerConnectionEvent(window, 'track', function (e) {
+ e.receiver._pc = e.srcElement;
+ return e;
+ });
+ window.RTCRtpReceiver.prototype.getStats = function () {
+ return this._pc.getStats(this.track);
+ };
+}
+
+function shimRemoveStream(window) {
+ if (!window.RTCPeerConnection || 'removeStream' in window.RTCPeerConnection.prototype) {
+ return;
+ }
+ window.RTCPeerConnection.prototype.removeStream = function (stream) {
+ var _this3 = this;
+
+ utils.deprecated('removeStream', 'removeTrack');
+ this.getSenders().forEach(function (sender) {
+ if (sender.track && stream.getTracks().includes(sender.track)) {
+ _this3.removeTrack(sender);
+ }
+ });
+ };
+}
+
+function shimRTCDataChannel(window) {
+ // rename DataChannel to RTCDataChannel (native fix in FF60):
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=1173851
+ if (window.DataChannel && !window.RTCDataChannel) {
+ window.RTCDataChannel = window.DataChannel;
+ }
+}
+
+},{"../utils":15,"./getdisplaymedia":12,"./getusermedia":13}],12:[function(require,module,exports){
+/*
+ * Copyright (c) 2018 The adapter.js 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.
+ */
+/* eslint-env node */
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.shimGetDisplayMedia = shimGetDisplayMedia;
+function shimGetDisplayMedia(window, preferredMediaSource) {
+ if (window.navigator.mediaDevices && 'getDisplayMedia' in window.navigator.mediaDevices) {
+ return;
+ }
+ if (!window.navigator.mediaDevices) {
+ return;
+ }
+ window.navigator.mediaDevices.getDisplayMedia = function (constraints) {
+ if (!(constraints && constraints.video)) {
+ var err = new DOMException('getDisplayMedia without video ' + 'constraints is undefined');
+ err.name = 'NotFoundError';
+ // from https://heycam.github.io/webidl/#idl-DOMException-error-names
+ err.code = 8;
+ return Promise.reject(err);
+ }
+ if (constraints.video === true) {
+ constraints.video = { mediaSource: preferredMediaSource };
+ } else {
+ constraints.video.mediaSource = preferredMediaSource;
+ }
+ return window.navigator.mediaDevices.getUserMedia(constraints);
+ };
+}
+
+},{}],13:[function(require,module,exports){
+/*
+ * Copyright (c) 2016 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.
+ */
+/* eslint-env node */
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
+
+exports.shimGetUserMedia = shimGetUserMedia;
+
+var _utils = require('../utils');
+
+var utils = _interopRequireWildcard(_utils);
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
+
+function shimGetUserMedia(window) {
+ var browserDetails = utils.detectBrowser(window);
+ var navigator = window && window.navigator;
+ var MediaStreamTrack = window && window.MediaStreamTrack;
+
+ navigator.getUserMedia = function (constraints, onSuccess, onError) {
+ // Replace Firefox 44+'s deprecation warning with unprefixed version.
+ utils.deprecated('navigator.getUserMedia', 'navigator.mediaDevices.getUserMedia');
+ navigator.mediaDevices.getUserMedia(constraints).then(onSuccess, onError);
+ };
+
+ if (!(browserDetails.version > 55 && 'autoGainControl' in navigator.mediaDevices.getSupportedConstraints())) {
+ var remap = function remap(obj, a, b) {
+ if (a in obj && !(b in obj)) {
+ obj[b] = obj[a];
+ delete obj[a];
+ }
+ };
+
+ var nativeGetUserMedia = navigator.mediaDevices.getUserMedia.bind(navigator.mediaDevices);
+ navigator.mediaDevices.getUserMedia = function (c) {
+ if ((typeof c === 'undefined' ? 'undefined' : _typeof(c)) === 'object' && _typeof(c.audio) === 'object') {
+ c = JSON.parse(JSON.stringify(c));
+ remap(c.audio, 'autoGainControl', 'mozAutoGainControl');
+ remap(c.audio, 'noiseSuppression', 'mozNoiseSuppression');
+ }
+ return nativeGetUserMedia(c);
+ };
+
+ if (MediaStreamTrack && MediaStreamTrack.prototype.getSettings) {
+ var nativeGetSettings = MediaStreamTrack.prototype.getSettings;
+ MediaStreamTrack.prototype.getSettings = function () {
+ var obj = nativeGetSettings.apply(this, arguments);
+ remap(obj, 'mozAutoGainControl', 'autoGainControl');
+ remap(obj, 'mozNoiseSuppression', 'noiseSuppression');
+ return obj;
+ };
+ }
+
+ if (MediaStreamTrack && MediaStreamTrack.prototype.applyConstraints) {
+ var nativeApplyConstraints = MediaStreamTrack.prototype.applyConstraints;
+ MediaStreamTrack.prototype.applyConstraints = function (c) {
+ if (this.kind === 'audio' && (typeof c === 'undefined' ? 'undefined' : _typeof(c)) === 'object') {
+ c = JSON.parse(JSON.stringify(c));
+ remap(c, 'autoGainControl', 'mozAutoGainControl');
+ remap(c, 'noiseSuppression', 'mozNoiseSuppression');
+ }
+ return nativeApplyConstraints.apply(this, [c]);
+ };
+ }
+ }
+}
+
+},{"../utils":15}],14:[function(require,module,exports){
+/*
+ * Copyright (c) 2016 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.
+ */
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
+
+exports.shimLocalStreamsAPI = shimLocalStreamsAPI;
+exports.shimRemoteStreamsAPI = shimRemoteStreamsAPI;
+exports.shimCallbacksAPI = shimCallbacksAPI;
+exports.shimGetUserMedia = shimGetUserMedia;
+exports.shimConstraints = shimConstraints;
+exports.shimRTCIceServerUrls = shimRTCIceServerUrls;
+exports.shimTrackEventTransceiver = shimTrackEventTransceiver;
+exports.shimCreateOfferLegacy = shimCreateOfferLegacy;
+
+var _utils = require('../utils');
+
+var utils = _interopRequireWildcard(_utils);
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
+
+function shimLocalStreamsAPI(window) {
+ if ((typeof window === 'undefined' ? 'undefined' : _typeof(window)) !== 'object' || !window.RTCPeerConnection) {
+ return;
+ }
+ if (!('getLocalStreams' in window.RTCPeerConnection.prototype)) {
+ window.RTCPeerConnection.prototype.getLocalStreams = function () {
+ if (!this._localStreams) {
+ this._localStreams = [];
+ }
+ return this._localStreams;
+ };
+ }
+ if (!('addStream' in window.RTCPeerConnection.prototype)) {
+ var _addTrack = window.RTCPeerConnection.prototype.addTrack;
+ window.RTCPeerConnection.prototype.addStream = function (stream) {
+ var _this = this;
+
+ if (!this._localStreams) {
+ this._localStreams = [];
+ }
+ if (!this._localStreams.includes(stream)) {
+ this._localStreams.push(stream);
+ }
+ stream.getTracks().forEach(function (track) {
+ return _addTrack.call(_this, track, stream);
+ });
+ };
+
+ window.RTCPeerConnection.prototype.addTrack = function (track, stream) {
+ if (stream) {
+ if (!this._localStreams) {
+ this._localStreams = [stream];
+ } else if (!this._localStreams.includes(stream)) {
+ this._localStreams.push(stream);
+ }
+ }
+ return _addTrack.call(this, track, stream);
+ };
+ }
+ if (!('removeStream' in window.RTCPeerConnection.prototype)) {
+ window.RTCPeerConnection.prototype.removeStream = function (stream) {
+ var _this2 = this;
+
+ if (!this._localStreams) {
+ this._localStreams = [];
+ }
+ var index = this._localStreams.indexOf(stream);
+ if (index === -1) {
+ return;
+ }
+ this._localStreams.splice(index, 1);
+ var tracks = stream.getTracks();
+ this.getSenders().forEach(function (sender) {
+ if (tracks.includes(sender.track)) {
+ _this2.removeTrack(sender);
+ }
+ });
+ };
+ }
+}
+
+function shimRemoteStreamsAPI(window) {
+ if ((typeof window === 'undefined' ? 'undefined' : _typeof(window)) !== 'object' || !window.RTCPeerConnection) {
+ return;
+ }
+ if (!('getRemoteStreams' in window.RTCPeerConnection.prototype)) {
+ window.RTCPeerConnection.prototype.getRemoteStreams = function () {
+ return this._remoteStreams ? this._remoteStreams : [];
+ };
+ }
+ if (!('onaddstream' in window.RTCPeerConnection.prototype)) {
+ Object.defineProperty(window.RTCPeerConnection.prototype, 'onaddstream', {
+ get: function get() {
+ return this._onaddstream;
+ },
+ set: function set(f) {
+ var _this3 = this;
+
+ if (this._onaddstream) {
+ this.removeEventListener('addstream', this._onaddstream);
+ this.removeEventListener('track', this._onaddstreampoly);
+ }
+ this.addEventListener('addstream', this._onaddstream = f);
+ this.addEventListener('track', this._onaddstreampoly = function (e) {
+ e.streams.forEach(function (stream) {
+ if (!_this3._remoteStreams) {
+ _this3._remoteStreams = [];
+ }
+ if (_this3._remoteStreams.includes(stream)) {
+ return;
+ }
+ _this3._remoteStreams.push(stream);
+ var event = new Event('addstream');
+ event.stream = stream;
+ _this3.dispatchEvent(event);
+ });
+ });
+ }
+ });
+ var origSetRemoteDescription = window.RTCPeerConnection.prototype.setRemoteDescription;
+ window.RTCPeerConnection.prototype.setRemoteDescription = function () {
+ var pc = this;
+ if (!this._onaddstreampoly) {
+ this.addEventListener('track', this._onaddstreampoly = function (e) {
+ e.streams.forEach(function (stream) {
+ if (!pc._remoteStreams) {
+ pc._remoteStreams = [];
+ }
+ if (pc._remoteStreams.indexOf(stream) >= 0) {
+ return;
+ }
+ pc._remoteStreams.push(stream);
+ var event = new Event('addstream');
+ event.stream = stream;
+ pc.dispatchEvent(event);
+ });
+ });
+ }
+ return origSetRemoteDescription.apply(pc, arguments);
+ };
+ }
+}
+
+function shimCallbacksAPI(window) {
+ if ((typeof window === 'undefined' ? 'undefined' : _typeof(window)) !== 'object' || !window.RTCPeerConnection) {
+ return;
+ }
+ var prototype = window.RTCPeerConnection.prototype;
+ var createOffer = prototype.createOffer;
+ var createAnswer = prototype.createAnswer;
+ var setLocalDescription = prototype.setLocalDescription;
+ var setRemoteDescription = prototype.setRemoteDescription;
+ var addIceCandidate = prototype.addIceCandidate;
+
+ prototype.createOffer = function (successCallback, failureCallback) {
+ var options = arguments.length >= 2 ? arguments[2] : arguments[0];
+ var promise = createOffer.apply(this, [options]);
+ if (!failureCallback) {
+ return promise;
+ }
+ promise.then(successCallback, failureCallback);
+ return Promise.resolve();
+ };
+
+ prototype.createAnswer = function (successCallback, failureCallback) {
+ var options = arguments.length >= 2 ? arguments[2] : arguments[0];
+ var promise = createAnswer.apply(this, [options]);
+ if (!failureCallback) {
+ return promise;
+ }
+ promise.then(successCallback, failureCallback);
+ return Promise.resolve();
+ };
+
+ var withCallback = function withCallback(description, successCallback, failureCallback) {
+ var promise = setLocalDescription.apply(this, [description]);
+ if (!failureCallback) {
+ return promise;
+ }
+ promise.then(successCallback, failureCallback);
+ return Promise.resolve();
+ };
+ prototype.setLocalDescription = withCallback;
+
+ withCallback = function withCallback(description, successCallback, failureCallback) {
+ var promise = setRemoteDescription.apply(this, [description]);
+ if (!failureCallback) {
+ return promise;
+ }
+ promise.then(successCallback, failureCallback);
+ return Promise.resolve();
+ };
+ prototype.setRemoteDescription = withCallback;
+
+ withCallback = function withCallback(candidate, successCallback, failureCallback) {
+ var promise = addIceCandidate.apply(this, [candidate]);
+ if (!failureCallback) {
+ return promise;
+ }
+ promise.then(successCallback, failureCallback);
+ return Promise.resolve();
+ };
+ prototype.addIceCandidate = withCallback;
+}
+
+function shimGetUserMedia(window) {
+ var navigator = window && window.navigator;
+
+ if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
+ // shim not needed in Safari 12.1
+ var mediaDevices = navigator.mediaDevices;
+ var _getUserMedia = mediaDevices.getUserMedia.bind(mediaDevices);
+ navigator.mediaDevices.getUserMedia = function (constraints) {
+ return _getUserMedia(shimConstraints(constraints));
+ };
+ }
+
+ if (!navigator.getUserMedia && navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
+ navigator.getUserMedia = function (constraints, cb, errcb) {
+ navigator.mediaDevices.getUserMedia(constraints).then(cb, errcb);
+ }.bind(navigator);
+ }
+}
+
+function shimConstraints(constraints) {
+ if (constraints && constraints.video !== undefined) {
+ return Object.assign({}, constraints, { video: utils.compactObject(constraints.video) });
+ }
+
+ return constraints;
+}
+
+function shimRTCIceServerUrls(window) {
+ // migrate from non-spec RTCIceServer.url to RTCIceServer.urls
+ var OrigPeerConnection = window.RTCPeerConnection;
+ window.RTCPeerConnection = function (pcConfig, pcConstraints) {
+ if (pcConfig && pcConfig.iceServers) {
+ var newIceServers = [];
+ for (var i = 0; i < pcConfig.iceServers.length; i++) {
+ var server = pcConfig.iceServers[i];
+ if (!server.hasOwnProperty('urls') && server.hasOwnProperty('url')) {
+ utils.deprecated('RTCIceServer.url', 'RTCIceServer.urls');
+ server = JSON.parse(JSON.stringify(server));
+ server.urls = server.url;
+ delete server.url;
+ newIceServers.push(server);
+ } else {
+ newIceServers.push(pcConfig.iceServers[i]);
+ }
+ }
+ pcConfig.iceServers = newIceServers;
+ }
+ return new OrigPeerConnection(pcConfig, pcConstraints);
+ };
+ window.RTCPeerConnection.prototype = OrigPeerConnection.prototype;
+ // wrap static methods. Currently just generateCertificate.
+ if ('generateCertificate' in window.RTCPeerConnection) {
+ Object.defineProperty(window.RTCPeerConnection, 'generateCertificate', {
+ get: function get() {
+ return OrigPeerConnection.generateCertificate;
+ }
+ });
+ }
+}
+
+function shimTrackEventTransceiver(window) {
+ // Add event.transceiver member over deprecated event.receiver
+ if ((typeof window === 'undefined' ? 'undefined' : _typeof(window)) === 'object' && window.RTCPeerConnection && 'receiver' in window.RTCTrackEvent.prototype &&
+ // can't check 'transceiver' in window.RTCTrackEvent.prototype, as it is
+ // defined for some reason even when window.RTCTransceiver is not.
+ !window.RTCTransceiver) {
+ Object.defineProperty(window.RTCTrackEvent.prototype, 'transceiver', {
+ get: function get() {
+ return { receiver: this.receiver };
+ }
+ });
+ }
+}
+
+function shimCreateOfferLegacy(window) {
+ var origCreateOffer = window.RTCPeerConnection.prototype.createOffer;
+ window.RTCPeerConnection.prototype.createOffer = function (offerOptions) {
+ if (offerOptions) {
+ if (typeof offerOptions.offerToReceiveAudio !== 'undefined') {
+ // support bit values
+ offerOptions.offerToReceiveAudio = !!offerOptions.offerToReceiveAudio;
+ }
+ var audioTransceiver = this.getTransceivers().find(function (transceiver) {
+ return transceiver.sender.track && transceiver.sender.track.kind === 'audio';
+ });
+ if (offerOptions.offerToReceiveAudio === false && audioTransceiver) {
+ if (audioTransceiver.direction === 'sendrecv') {
+ if (audioTransceiver.setDirection) {
+ audioTransceiver.setDirection('sendonly');
+ } else {
+ audioTransceiver.direction = 'sendonly';
+ }
+ } else if (audioTransceiver.direction === 'recvonly') {
+ if (audioTransceiver.setDirection) {
+ audioTransceiver.setDirection('inactive');
+ } else {
+ audioTransceiver.direction = 'inactive';
+ }
+ }
+ } else if (offerOptions.offerToReceiveAudio === true && !audioTransceiver) {
+ this.addTransceiver('audio');
+ }
+
+ if (typeof offerOptions.offerToReceiveVideo !== 'undefined') {
+ // support bit values
+ offerOptions.offerToReceiveVideo = !!offerOptions.offerToReceiveVideo;
+ }
+ var videoTransceiver = this.getTransceivers().find(function (transceiver) {
+ return transceiver.sender.track && transceiver.sender.track.kind === 'video';
+ });
+ if (offerOptions.offerToReceiveVideo === false && videoTransceiver) {
+ if (videoTransceiver.direction === 'sendrecv') {
+ if (videoTransceiver.setDirection) {
+ videoTransceiver.setDirection('sendonly');
+ } else {
+ videoTransceiver.direction = 'sendonly';
+ }
+ } else if (videoTransceiver.direction === 'recvonly') {
+ if (videoTransceiver.setDirection) {
+ videoTransceiver.setDirection('inactive');
+ } else {
+ videoTransceiver.direction = 'inactive';
+ }
+ }
+ } else if (offerOptions.offerToReceiveVideo === true && !videoTransceiver) {
+ this.addTransceiver('video');
+ }
+ }
+ return origCreateOffer.apply(this, arguments);
+ };
+}
+
+},{"../utils":15}],15:[function(require,module,exports){
+/*
+ * Copyright (c) 2016 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.
+ */
+/* eslint-env node */
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
+
+exports.extractVersion = extractVersion;
+exports.wrapPeerConnectionEvent = wrapPeerConnectionEvent;
+exports.disableLog = disableLog;
+exports.disableWarnings = disableWarnings;
+exports.log = log;
+exports.deprecated = deprecated;
+exports.detectBrowser = detectBrowser;
+exports.compactObject = compactObject;
+
+function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
+
+var logDisabled_ = true;
+var deprecationWarnings_ = true;
+
+/**
+ * Extract browser version out of the provided user agent string.
+ *
+ * @param {!string} uastring userAgent string.
+ * @param {!string} expr Regular expression used as match criteria.
+ * @param {!number} pos position in the version string to be returned.
+ * @return {!number} browser version.
+ */
+function extractVersion(uastring, expr, pos) {
+ var match = uastring.match(expr);
+ return match && match.length >= pos && parseInt(match[pos], 10);
+}
+
+// Wraps the peerconnection event eventNameToWrap in a function
+// which returns the modified event object (or false to prevent
+// the event).
+function wrapPeerConnectionEvent(window, eventNameToWrap, wrapper) {
+ if (!window.RTCPeerConnection) {
+ return;
+ }
+ var proto = window.RTCPeerConnection.prototype;
+ var nativeAddEventListener = proto.addEventListener;
+ proto.addEventListener = function (nativeEventName, cb) {
+ if (nativeEventName !== eventNameToWrap) {
+ return nativeAddEventListener.apply(this, arguments);
+ }
+ var wrappedCallback = function wrappedCallback(e) {
+ var modifiedEvent = wrapper(e);
+ if (modifiedEvent) {
+ cb(modifiedEvent);
+ }
+ };
+ this._eventMap = this._eventMap || {};
+ this._eventMap[cb] = wrappedCallback;
+ return nativeAddEventListener.apply(this, [nativeEventName, wrappedCallback]);
+ };
+
+ var nativeRemoveEventListener = proto.removeEventListener;
+ proto.removeEventListener = function (nativeEventName, cb) {
+ if (nativeEventName !== eventNameToWrap || !this._eventMap || !this._eventMap[cb]) {
+ return nativeRemoveEventListener.apply(this, arguments);
+ }
+ var unwrappedCb = this._eventMap[cb];
+ delete this._eventMap[cb];
+ return nativeRemoveEventListener.apply(this, [nativeEventName, unwrappedCb]);
+ };
+
+ Object.defineProperty(proto, 'on' + eventNameToWrap, {
+ get: function get() {
+ return this['_on' + eventNameToWrap];
+ },
+ set: function set(cb) {
+ if (this['_on' + eventNameToWrap]) {
+ this.removeEventListener(eventNameToWrap, this['_on' + eventNameToWrap]);
+ delete this['_on' + eventNameToWrap];
+ }
+ if (cb) {
+ this.addEventListener(eventNameToWrap, this['_on' + eventNameToWrap] = cb);
+ }
+ },
+
+ enumerable: true,
+ configurable: true
+ });
+}
+
+function disableLog(bool) {
+ if (typeof bool !== 'boolean') {
+ return new Error('Argument type: ' + (typeof bool === 'undefined' ? 'undefined' : _typeof(bool)) + '. Please use a boolean.');
+ }
+ logDisabled_ = bool;
+ return bool ? 'adapter.js logging disabled' : 'adapter.js logging enabled';
+}
+
+/**
+ * Disable or enable deprecation warnings
+ * @param {!boolean} bool set to true to disable warnings.
+ */
+function disableWarnings(bool) {
+ if (typeof bool !== 'boolean') {
+ return new Error('Argument type: ' + (typeof bool === 'undefined' ? 'undefined' : _typeof(bool)) + '. Please use a boolean.');
+ }
+ deprecationWarnings_ = !bool;
+ return 'adapter.js deprecation warnings ' + (bool ? 'disabled' : 'enabled');
+}
+
+function log() {
+ if ((typeof window === 'undefined' ? 'undefined' : _typeof(window)) === 'object') {
+ if (logDisabled_) {
+ return;
+ }
+ if (typeof console !== 'undefined' && typeof console.log === 'function') {
+ console.log.apply(console, arguments);
+ }
+ }
+}
+
+/**
+ * Shows a deprecation warning suggesting the modern and spec-compatible API.
+ */
+function deprecated(oldMethod, newMethod) {
+ if (!deprecationWarnings_) {
+ return;
+ }
+ console.warn(oldMethod + ' is deprecated, please use ' + newMethod + ' instead.');
+}
+
+/**
+ * Browser detector.
+ *
+ * @return {object} result containing browser and version
+ * properties.
+ */
+function detectBrowser(window) {
+ var navigator = window.navigator;
+
+ // Returned result object.
+
+ var result = { browser: null, version: null };
+
+ // Fail early if it's not a browser
+ if (typeof window === 'undefined' || !window.navigator) {
+ result.browser = 'Not a browser.';
+ return result;
+ }
+
+ if (navigator.mozGetUserMedia) {
+ // Firefox.
+ result.browser = 'firefox';
+ result.version = extractVersion(navigator.userAgent, /Firefox\/(\d+)\./, 1);
+ } else if (navigator.webkitGetUserMedia) {
+ // Chrome, Chromium, Webview, Opera.
+ // Version matches Chrome/WebRTC version.
+ result.browser = 'chrome';
+ result.version = extractVersion(navigator.userAgent, /Chrom(e|ium)\/(\d+)\./, 2);
+ } else if (navigator.mediaDevices && navigator.userAgent.match(/Edge\/(\d+).(\d+)$/)) {
+ // Edge.
+ result.browser = 'edge';
+ result.version = extractVersion(navigator.userAgent, /Edge\/(\d+).(\d+)$/, 2);
+ } else if (window.RTCPeerConnection && navigator.userAgent.match(/AppleWebKit\/(\d+)\./)) {
+ // Safari.
+ result.browser = 'safari';
+ result.version = extractVersion(navigator.userAgent, /AppleWebKit\/(\d+)\./, 1);
+ } else {
+ // Default fallthrough: not supported.
+ result.browser = 'Not a supported browser.';
+ return result;
+ }
+
+ return result;
+}
+
+/**
+ * Remove all empty objects and undefined values
+ * from a nested object -- an enhanced and vanilla version
+ * of Lodash's `compact`.
+ */
+function compactObject(data) {
+ if ((typeof data === 'undefined' ? 'undefined' : _typeof(data)) !== 'object') {
+ return data;
+ }
+
+ return Object.keys(data).reduce(function (accumulator, key) {
+ var isObject = _typeof(data[key]) === 'object';
+ var value = isObject ? compactObject(data[key]) : data[key];
+ var isEmptyObject = isObject && !Object.keys(value).length;
+ if (value === undefined || isEmptyObject) {
+ return accumulator;
+ }
+
+ return Object.assign(accumulator, _defineProperty({}, key, value));
+ }, {});
+}
+
+},{}],16:[function(require,module,exports){
/*
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
*
@@ -11,6 +2682,16 @@
var SDPUtils = require('sdp');
+function fixStatsType(stat) {
+ return {
+ inboundrtp: 'inbound-rtp',
+ outboundrtp: 'outbound-rtp',
+ candidatepair: 'candidate-pair',
+ localcandidate: 'local-candidate',
+ remotecandidate: 'remote-candidate'
+ }[stat.type] || stat.type;
+}
+
function writeMediaSection(transceiver, caps, type, stream, dtlsRole) {
var sdp = SDPUtils.writeRtpDescription(transceiver.kind, caps);
@@ -36,14 +2717,18 @@ function writeMediaSection(transceiver, caps, type, stream, dtlsRole) {
}
if (transceiver.rtpSender) {
+ var trackId = transceiver.rtpSender._initialTrackId ||
+ transceiver.rtpSender.track.id;
+ transceiver.rtpSender._initialTrackId = trackId;
// spec.
- var msid = 'msid:' + stream.id + ' ' +
- transceiver.rtpSender.track.id + '\r\n';
+ var msid = 'msid:' + (stream ? stream.id : '-') + ' ' +
+ trackId + '\r\n';
sdp += 'a=' + msid;
-
- // for Chrome.
+ // for Chrome. Legacy should no longer be required.
sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].ssrc +
' ' + msid;
+
+ // RTX
if (transceiver.sendEncodingParameters[0].rtx) {
sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].rtx.ssrc +
' ' + msid;
@@ -213,41 +2898,47 @@ function maybeAddCandidate(iceTransport, candidate) {
}
-// https://w3c.github.io/mediacapture-main/#mediastream
-// Helper function to add the track to the stream and
-// dispatch the event ourselves.
-function addTrackToStreamAndFireEvent(track, stream) {
- stream.addTrack(track);
- var e = new Event('addtrack'); // TODO: MediaStreamTrackEvent
- e.track = track;
- stream.dispatchEvent(e);
-}
-
-function removeTrackFromStreamAndFireEvent(track, stream) {
- stream.removeTrack(track);
- var e = new Event('removetrack'); // TODO: MediaStreamTrackEvent
- e.track = track;
- stream.dispatchEvent(e);
-}
-
-function fireAddTrack(pc, track, receiver, streams) {
- var trackEvent = new Event('track');
- trackEvent.track = track;
- trackEvent.receiver = receiver;
- trackEvent.transceiver = {receiver: receiver};
- trackEvent.streams = streams;
- window.setTimeout(function() {
- pc._dispatchEvent('track', trackEvent);
- });
-}
-
function makeError(name, description) {
var e = new Error(description);
e.name = name;
+ // legacy error codes from https://heycam.github.io/webidl/#idl-DOMException-error-names
+ e.code = {
+ NotSupportedError: 9,
+ InvalidStateError: 11,
+ InvalidAccessError: 15,
+ TypeError: undefined,
+ OperationError: undefined
+ }[name];
return e;
}
module.exports = function(window, edgeVersion) {
+ // https://w3c.github.io/mediacapture-main/#mediastream
+ // Helper function to add the track to the stream and
+ // dispatch the event ourselves.
+ function addTrackToStreamAndFireEvent(track, stream) {
+ stream.addTrack(track);
+ stream.dispatchEvent(new window.MediaStreamTrackEvent('addtrack',
+ {track: track}));
+ }
+
+ function removeTrackFromStreamAndFireEvent(track, stream) {
+ stream.removeTrack(track);
+ stream.dispatchEvent(new window.MediaStreamTrackEvent('removetrack',
+ {track: track}));
+ }
+
+ function fireAddTrack(pc, track, receiver, streams) {
+ var trackEvent = new Event('track');
+ trackEvent.track = track;
+ trackEvent.receiver = receiver;
+ trackEvent.transceiver = {receiver: receiver};
+ trackEvent.streams = streams;
+ window.setTimeout(function() {
+ pc._dispatchEvent('track', trackEvent);
+ });
+ }
+
var RTCPeerConnection = function(config) {
var pc = this;
@@ -264,11 +2955,12 @@ module.exports = function(window, edgeVersion) {
this.localStreams = [];
this.remoteStreams = [];
- this.localDescription = null;
- this.remoteDescription = null;
+ this._localDescription = null;
+ this._remoteDescription = null;
this.signalingState = 'stable';
this.iceConnectionState = 'new';
+ this.connectionState = 'new';
this.iceGatheringState = 'new';
config = JSON.parse(JSON.stringify(config || {}));
@@ -305,10 +2997,10 @@ module.exports = function(window, edgeVersion) {
this._iceGatherers = [];
if (config.iceCandidatePoolSize) {
for (var i = config.iceCandidatePoolSize; i > 0; i--) {
- this._iceGatherers = new window.RTCIceGatherer({
+ this._iceGatherers.push(new window.RTCIceGatherer({
iceServers: config.iceServers,
gatherPolicy: config.iceTransportPolicy
- });
+ }));
}
} else {
config.iceCandidatePoolSize = 0;
@@ -328,6 +3020,19 @@ module.exports = function(window, edgeVersion) {
this._isClosed = false;
};
+ Object.defineProperty(RTCPeerConnection.prototype, 'localDescription', {
+ configurable: true,
+ get: function() {
+ return this._localDescription;
+ }
+ });
+ Object.defineProperty(RTCPeerConnection.prototype, 'remoteDescription', {
+ configurable: true,
+ get: function() {
+ return this._remoteDescription;
+ }
+ });
+
// set up event handlers on prototype
RTCPeerConnection.prototype.onicecandidate = null;
RTCPeerConnection.prototype.onaddstream = null;
@@ -335,6 +3040,7 @@ module.exports = function(window, edgeVersion) {
RTCPeerConnection.prototype.onremovestream = null;
RTCPeerConnection.prototype.onsignalingstatechange = null;
RTCPeerConnection.prototype.oniceconnectionstatechange = null;
+ RTCPeerConnection.prototype.onconnectionstatechange = null;
RTCPeerConnection.prototype.onicegatheringstatechange = null;
RTCPeerConnection.prototype.onnegotiationneeded = null;
RTCPeerConnection.prototype.ondatachannel = null;
@@ -367,8 +3073,8 @@ module.exports = function(window, edgeVersion) {
};
// internal helper to create a transceiver object.
- // (whih is not yet the same as the WebRTC 1.0 transceiver)
- RTCPeerConnection.prototype._createTransceiver = function(kind) {
+ // (which is not yet the same as the WebRTC 1.0 transceiver)
+ RTCPeerConnection.prototype._createTransceiver = function(kind, doNotAdd) {
var hasBundleTransport = this.transceivers.length > 0;
var transceiver = {
track: null,
@@ -395,11 +3101,18 @@ module.exports = function(window, edgeVersion) {
transceiver.iceTransport = transports.iceTransport;
transceiver.dtlsTransport = transports.dtlsTransport;
}
- this.transceivers.push(transceiver);
+ if (!doNotAdd) {
+ this.transceivers.push(transceiver);
+ }
return transceiver;
};
RTCPeerConnection.prototype.addTrack = function(track, stream) {
+ if (this._isClosed) {
+ throw makeError('InvalidStateError',
+ 'Attempted to call addTrack on a closed peerconnection.');
+ }
+
var alreadyExists = this.transceivers.find(function(s) {
return s.track === track;
});
@@ -408,11 +3121,6 @@ module.exports = function(window, edgeVersion) {
throw makeError('InvalidAccessError', 'Track already exists.');
}
- if (this.signalingState === 'closed') {
- throw makeError('InvalidStateError',
- 'Attempted to call addTrack on a closed peerconnection.');
- }
-
var transceiver;
for (var i = 0; i < this.transceivers.length; i++) {
if (!this.transceivers[i].track &&
@@ -461,6 +3169,11 @@ module.exports = function(window, edgeVersion) {
};
RTCPeerConnection.prototype.removeTrack = function(sender) {
+ if (this._isClosed) {
+ throw makeError('InvalidStateError',
+ 'Attempted to call removeTrack on a closed peerconnection.');
+ }
+
if (!(sender instanceof window.RTCRtpSender)) {
throw new TypeError('Argument 1 of RTCPeerConnection.removeTrack ' +
'does not implement interface RTCRtpSender.');
@@ -540,14 +3253,14 @@ module.exports = function(window, edgeVersion) {
{value: 'new', writable: true}
);
- this.transceivers[sdpMLineIndex].candidates = [];
+ this.transceivers[sdpMLineIndex].bufferedCandidateEvents = [];
this.transceivers[sdpMLineIndex].bufferCandidates = function(event) {
var end = !event.candidate || Object.keys(event.candidate).length === 0;
// polyfill since RTCIceGatherer.state is not implemented in
// Edge 10547 yet.
iceGatherer.state = end ? 'completed' : 'gathering';
- if (pc.transceivers[sdpMLineIndex].candidates !== null) {
- pc.transceivers[sdpMLineIndex].candidates.push(event.candidate);
+ if (pc.transceivers[sdpMLineIndex].bufferedCandidateEvents !== null) {
+ pc.transceivers[sdpMLineIndex].bufferedCandidateEvents.push(event);
}
};
iceGatherer.addEventListener('localcandidate',
@@ -562,8 +3275,9 @@ module.exports = function(window, edgeVersion) {
if (iceGatherer.onlocalcandidate) {
return;
}
- var candidates = this.transceivers[sdpMLineIndex].candidates;
- this.transceivers[sdpMLineIndex].candidates = null;
+ var bufferedCandidateEvents =
+ this.transceivers[sdpMLineIndex].bufferedCandidateEvents;
+ this.transceivers[sdpMLineIndex].bufferedCandidateEvents = null;
iceGatherer.removeEventListener('localcandidate',
this.transceivers[sdpMLineIndex].bufferCandidates);
iceGatherer.onlocalcandidate = function(evt) {
@@ -591,19 +3305,36 @@ module.exports = function(window, edgeVersion) {
}
// RTCIceCandidate doesn't have a component, needs to be added
cand.component = 1;
- event.candidate.candidate = SDPUtils.writeCandidate(cand);
+ // also the usernameFragment. TODO: update SDP to take both variants.
+ cand.ufrag = iceGatherer.getLocalParameters().usernameFragment;
+
+ var serializedCandidate = SDPUtils.writeCandidate(cand);
+ event.candidate = Object.assign(event.candidate,
+ SDPUtils.parseCandidate(serializedCandidate));
+
+ event.candidate.candidate = serializedCandidate;
+ event.candidate.toJSON = function() {
+ return {
+ candidate: event.candidate.candidate,
+ sdpMid: event.candidate.sdpMid,
+ sdpMLineIndex: event.candidate.sdpMLineIndex,
+ usernameFragment: event.candidate.usernameFragment
+ };
+ };
}
// update local description.
- var sections = SDPUtils.splitSections(pc.localDescription.sdp);
+ var sections = SDPUtils.getMediaSections(pc._localDescription.sdp);
if (!end) {
- sections[event.candidate.sdpMLineIndex + 1] +=
+ sections[event.candidate.sdpMLineIndex] +=
'a=' + event.candidate.candidate + '\r\n';
} else {
- sections[event.candidate.sdpMLineIndex + 1] +=
+ sections[event.candidate.sdpMLineIndex] +=
'a=end-of-candidates\r\n';
}
- pc.localDescription.sdp = sections.join('');
+ pc._localDescription.sdp =
+ SDPUtils.getDescription(pc._localDescription.sdp) +
+ sections.join('');
var complete = pc.transceivers.every(function(transceiver) {
return transceiver.iceGatherer &&
transceiver.iceGatherer.state === 'completed';
@@ -628,9 +3359,7 @@ module.exports = function(window, edgeVersion) {
// emit already gathered candidates.
window.setTimeout(function() {
- candidates.forEach(function(candidate) {
- var e = new Event('RTCIceGatherEvent');
- e.candidate = candidate;
+ bufferedCandidateEvents.forEach(function(e) {
iceGatherer.onlocalcandidate(e);
});
}, 0);
@@ -641,6 +3370,7 @@ module.exports = function(window, edgeVersion) {
var pc = this;
var iceTransport = new window.RTCIceTransport(null);
iceTransport.onicestatechange = function() {
+ pc._updateIceConnectionState();
pc._updateConnectionState();
};
@@ -649,7 +3379,7 @@ module.exports = function(window, edgeVersion) {
pc._updateConnectionState();
};
dtlsTransport.onerror = function() {
- // onerror does not set state to failed by itpc.
+ // onerror does not set state to failed by itself.
Object.defineProperty(dtlsTransport, 'state',
{value: 'failed', writable: true});
pc._updateConnectionState();
@@ -710,6 +3440,8 @@ module.exports = function(window, edgeVersion) {
}
if (transceiver.recvEncodingParameters.length) {
params.encodings = transceiver.recvEncodingParameters;
+ } else {
+ params.encodings = [{}];
}
params.rtcp = {
compound: transceiver.rtcpParameters.compound
@@ -727,8 +3459,14 @@ module.exports = function(window, edgeVersion) {
RTCPeerConnection.prototype.setLocalDescription = function(description) {
var pc = this;
+ // Note: pranswer is not supported.
+ if (['offer', 'answer'].indexOf(description.type) === -1) {
+ return Promise.reject(makeError('TypeError',
+ 'Unsupported type "' + description.type + '"'));
+ }
+
if (!isActionAllowedInSignalingState('setLocalDescription',
- description.type, this.signalingState) || this._isClosed) {
+ description.type, pc.signalingState) || pc._isClosed) {
return Promise.reject(makeError('InvalidStateError',
'Can not set local ' + description.type +
' in state ' + pc.signalingState));
@@ -746,11 +3484,11 @@ module.exports = function(window, edgeVersion) {
pc.transceivers[sdpMLineIndex].localCapabilities = caps;
});
- this.transceivers.forEach(function(transceiver, sdpMLineIndex) {
+ pc.transceivers.forEach(function(transceiver, sdpMLineIndex) {
pc._gather(transceiver.mid, sdpMLineIndex);
});
} else if (description.type === 'answer') {
- sections = SDPUtils.splitSections(pc.remoteDescription.sdp);
+ sections = SDPUtils.splitSections(pc._remoteDescription.sdp);
sessionpart = sections.shift();
var isIceLite = SDPUtils.matchPrefix(sessionpart,
'a=ice-lite').length > 0;
@@ -766,7 +3504,7 @@ module.exports = function(window, edgeVersion) {
var rejected = SDPUtils.isRejected(mediaSection) &&
SDPUtils.matchPrefix(mediaSection, 'a=bundle-only').length === 0;
- if (!rejected && !transceiver.isDatachannel) {
+ if (!rejected && !transceiver.rejected) {
var remoteIceParameters = SDPUtils.getIceParameters(
mediaSection, sessionpart);
var remoteDtlsParameters = SDPUtils.getDtlsParameters(
@@ -799,20 +3537,14 @@ module.exports = function(window, edgeVersion) {
});
}
- this.localDescription = {
+ pc._localDescription = {
type: description.type,
sdp: description.sdp
};
- switch (description.type) {
- case 'offer':
- this._updateSignalingState('have-local-offer');
- break;
- case 'answer':
- this._updateSignalingState('stable');
- break;
- default:
- throw new TypeError('unsupported type "' + description.type +
- '"');
+ if (description.type === 'offer') {
+ pc._updateSignalingState('have-local-offer');
+ } else {
+ pc._updateSignalingState('stable');
}
return Promise.resolve();
@@ -821,15 +3553,21 @@ module.exports = function(window, edgeVersion) {
RTCPeerConnection.prototype.setRemoteDescription = function(description) {
var pc = this;
+ // Note: pranswer is not supported.
+ if (['offer', 'answer'].indexOf(description.type) === -1) {
+ return Promise.reject(makeError('TypeError',
+ 'Unsupported type "' + description.type + '"'));
+ }
+
if (!isActionAllowedInSignalingState('setRemoteDescription',
- description.type, this.signalingState) || this._isClosed) {
+ description.type, pc.signalingState) || pc._isClosed) {
return Promise.reject(makeError('InvalidStateError',
'Can not set remote ' + description.type +
' in state ' + pc.signalingState));
}
var streams = {};
- this.remoteStreams.forEach(function(stream) {
+ pc.remoteStreams.forEach(function(stream) {
streams[stream.id] = stream;
});
var receiverList = [];
@@ -839,14 +3577,14 @@ module.exports = function(window, edgeVersion) {
'a=ice-lite').length > 0;
var usingBundle = SDPUtils.matchPrefix(sessionpart,
'a=group:BUNDLE ').length > 0;
- this.usingBundle = usingBundle;
+ pc.usingBundle = usingBundle;
var iceOptions = SDPUtils.matchPrefix(sessionpart,
'a=ice-options:')[0];
if (iceOptions) {
- this.canTrickleIceCandidates = iceOptions.substr(14).split(' ')
+ pc.canTrickleIceCandidates = iceOptions.substr(14).split(' ')
.indexOf('trickle') >= 0;
} else {
- this.canTrickleIceCandidates = false;
+ pc.canTrickleIceCandidates = false;
}
sections.forEach(function(mediaSection, sdpMLineIndex) {
@@ -863,14 +3601,25 @@ module.exports = function(window, edgeVersion) {
var mid = SDPUtils.getMid(mediaSection) || SDPUtils.generateIdentifier();
// Reject datachannels which are not implemented yet.
- if (kind === 'application' && protocol === 'DTLS/SCTP') {
+ if (rejected || (kind === 'application' && (protocol === 'DTLS/SCTP' ||
+ protocol === 'UDP/DTLS/SCTP'))) {
+ // TODO: this is dangerous in the case where a non-rejected m-line
+ // becomes rejected.
pc.transceivers[sdpMLineIndex] = {
mid: mid,
- isDatachannel: true
+ kind: kind,
+ protocol: protocol,
+ rejected: true
};
return;
}
+ if (!rejected && pc.transceivers[sdpMLineIndex] &&
+ pc.transceivers[sdpMLineIndex].rejected) {
+ // recycle a rejected transceiver.
+ pc.transceivers[sdpMLineIndex] = pc._createTransceiver(kind, true);
+ }
+
var transceiver;
var iceGatherer;
var iceTransport;
@@ -1062,6 +3811,19 @@ module.exports = function(window, edgeVersion) {
}
}
+ // If the offer contained RTX but the answer did not,
+ // remove RTX from sendEncodingParameters.
+ var commonCapabilities = getCommonCapabilities(
+ transceiver.localCapabilities,
+ transceiver.remoteCapabilities);
+
+ var hasRtx = commonCapabilities.codecs.filter(function(c) {
+ return c.name.toLowerCase() === 'rtx';
+ }).length;
+ if (!hasRtx && transceiver.sendEncodingParameters[0].rtx) {
+ delete transceiver.sendEncodingParameters[0].rtx;
+ }
+
pc._transceive(transceiver,
direction === 'sendrecv' || direction === 'recvonly',
direction === 'sendrecv' || direction === 'sendonly');
@@ -1090,24 +3852,18 @@ module.exports = function(window, edgeVersion) {
}
});
- if (this._dtlsRole === undefined) {
- this._dtlsRole = description.type === 'offer' ? 'active' : 'passive';
+ if (pc._dtlsRole === undefined) {
+ pc._dtlsRole = description.type === 'offer' ? 'active' : 'passive';
}
- this.remoteDescription = {
+ pc._remoteDescription = {
type: description.type,
sdp: description.sdp
};
- switch (description.type) {
- case 'offer':
- this._updateSignalingState('have-remote-offer');
- break;
- case 'answer':
- this._updateSignalingState('stable');
- break;
- default:
- throw new TypeError('unsupported type "' + description.type +
- '"');
+ if (description.type === 'offer') {
+ pc._updateSignalingState('have-remote-offer');
+ } else {
+ pc._updateSignalingState('stable');
}
Object.keys(streams).forEach(function(sid) {
var stream = streams[sid];
@@ -1198,22 +3954,20 @@ module.exports = function(window, edgeVersion) {
}
this.needNegotiation = true;
window.setTimeout(function() {
- if (pc.needNegotiation === false) {
- return;
+ if (pc.needNegotiation) {
+ pc.needNegotiation = false;
+ var event = new Event('negotiationneeded');
+ pc._dispatchEvent('negotiationneeded', event);
}
- pc.needNegotiation = false;
- var event = new Event('negotiationneeded');
- pc._dispatchEvent('negotiationneeded', event);
}, 0);
};
- // Update the connection state.
- RTCPeerConnection.prototype._updateConnectionState = function() {
+ // Update the ice connection state.
+ RTCPeerConnection.prototype._updateIceConnectionState = function() {
var newState;
var states = {
'new': 0,
closed: 0,
- connecting: 0,
checking: 0,
connected: 0,
completed: 0,
@@ -1221,23 +3975,24 @@ module.exports = function(window, edgeVersion) {
failed: 0
};
this.transceivers.forEach(function(transceiver) {
- states[transceiver.iceTransport.state]++;
- states[transceiver.dtlsTransport.state]++;
+ if (transceiver.iceTransport && !transceiver.rejected) {
+ states[transceiver.iceTransport.state]++;
+ }
});
- // ICETransport.completed and connected are the same for this purpose.
- states.connected += states.completed;
newState = 'new';
if (states.failed > 0) {
newState = 'failed';
- } else if (states.connecting > 0 || states.checking > 0) {
- newState = 'connecting';
+ } else if (states.checking > 0) {
+ newState = 'checking';
} else if (states.disconnected > 0) {
newState = 'disconnected';
} else if (states.new > 0) {
newState = 'new';
- } else if (states.connected > 0 || states.completed > 0) {
+ } else if (states.connected > 0) {
newState = 'connected';
+ } else if (states.completed > 0) {
+ newState = 'completed';
}
if (newState !== this.iceConnectionState) {
@@ -1247,18 +4002,60 @@ module.exports = function(window, edgeVersion) {
}
};
+ // Update the connection state.
+ RTCPeerConnection.prototype._updateConnectionState = function() {
+ var newState;
+ var states = {
+ 'new': 0,
+ closed: 0,
+ connecting: 0,
+ connected: 0,
+ completed: 0,
+ disconnected: 0,
+ failed: 0
+ };
+ this.transceivers.forEach(function(transceiver) {
+ if (transceiver.iceTransport && transceiver.dtlsTransport &&
+ !transceiver.rejected) {
+ states[transceiver.iceTransport.state]++;
+ states[transceiver.dtlsTransport.state]++;
+ }
+ });
+ // ICETransport.completed and connected are the same for this purpose.
+ states.connected += states.completed;
+
+ newState = 'new';
+ if (states.failed > 0) {
+ newState = 'failed';
+ } else if (states.connecting > 0) {
+ newState = 'connecting';
+ } else if (states.disconnected > 0) {
+ newState = 'disconnected';
+ } else if (states.new > 0) {
+ newState = 'new';
+ } else if (states.connected > 0) {
+ newState = 'connected';
+ }
+
+ if (newState !== this.connectionState) {
+ this.connectionState = newState;
+ var event = new Event('connectionstatechange');
+ this._dispatchEvent('connectionstatechange', event);
+ }
+ };
+
RTCPeerConnection.prototype.createOffer = function() {
var pc = this;
- if (this._isClosed) {
+ if (pc._isClosed) {
return Promise.reject(makeError('InvalidStateError',
'Can not call createOffer after close'));
}
- var numAudioTracks = this.transceivers.filter(function(t) {
+ var numAudioTracks = pc.transceivers.filter(function(t) {
return t.kind === 'audio';
}).length;
- var numVideoTracks = this.transceivers.filter(function(t) {
+ var numVideoTracks = pc.transceivers.filter(function(t) {
return t.kind === 'video';
}).length;
@@ -1290,7 +4087,7 @@ module.exports = function(window, edgeVersion) {
}
}
- this.transceivers.forEach(function(transceiver) {
+ pc.transceivers.forEach(function(transceiver) {
if (transceiver.kind === 'audio') {
numAudioTracks--;
if (numAudioTracks < 0) {
@@ -1307,23 +4104,23 @@ module.exports = function(window, edgeVersion) {
// Create M-lines for recvonly streams.
while (numAudioTracks > 0 || numVideoTracks > 0) {
if (numAudioTracks > 0) {
- this._createTransceiver('audio');
+ pc._createTransceiver('audio');
numAudioTracks--;
}
if (numVideoTracks > 0) {
- this._createTransceiver('video');
+ pc._createTransceiver('video');
numVideoTracks--;
}
}
- var sdp = SDPUtils.writeSessionBoilerplate(this._sdpSessionId,
- this._sdpSessionVersion++);
- this.transceivers.forEach(function(transceiver, sdpMLineIndex) {
+ var sdp = SDPUtils.writeSessionBoilerplate(pc._sdpSessionId,
+ pc._sdpSessionVersion++);
+ pc.transceivers.forEach(function(transceiver, sdpMLineIndex) {
// For each track, create an ice gatherer, ice transport,
// dtls transport, potentially rtpsender and rtpreceiver.
var track = transceiver.track;
var kind = transceiver.kind;
- var mid = SDPUtils.generateIdentifier();
+ var mid = transceiver.mid || SDPUtils.generateIdentifier();
transceiver.mid = mid;
if (!transceiver.iceGatherer) {
@@ -1347,6 +4144,27 @@ module.exports = function(window, edgeVersion) {
codec.parameters['level-asymmetry-allowed'] === undefined) {
codec.parameters['level-asymmetry-allowed'] = '1';
}
+
+ // for subsequent offers, we might have to re-use the payload
+ // type of the last offer.
+ if (transceiver.remoteCapabilities &&
+ transceiver.remoteCapabilities.codecs) {
+ transceiver.remoteCapabilities.codecs.forEach(function(remoteCodec) {
+ if (codec.name.toLowerCase() === remoteCodec.name.toLowerCase() &&
+ codec.clockRate === remoteCodec.clockRate) {
+ codec.preferredPayloadType = remoteCodec.payloadType;
+ }
+ });
+ }
+ });
+ localCapabilities.headerExtensions.forEach(function(hdrExt) {
+ var remoteExtensions = transceiver.remoteCapabilities &&
+ transceiver.remoteCapabilities.headerExtensions || [];
+ remoteExtensions.forEach(function(rHdrExt) {
+ if (hdrExt.uri === rHdrExt.uri) {
+ hdrExt.id = rHdrExt.id;
+ }
+ });
});
// generate an ssrc now, to be used later in rtpSender.send
@@ -1373,14 +4191,14 @@ module.exports = function(window, edgeVersion) {
});
// always offer BUNDLE and dispose on return if not supported.
- if (this._config.bundlePolicy !== 'max-compat') {
- sdp += 'a=group:BUNDLE ' + this.transceivers.map(function(t) {
+ if (pc._config.bundlePolicy !== 'max-compat') {
+ sdp += 'a=group:BUNDLE ' + pc.transceivers.map(function(t) {
return t.mid;
}).join(' ') + '\r\n';
}
sdp += 'a=ice-options:trickle\r\n';
- this.transceivers.forEach(function(transceiver, sdpMLineIndex) {
+ pc.transceivers.forEach(function(transceiver, sdpMLineIndex) {
sdp += writeMediaSection(transceiver, transceiver.localCapabilities,
'offer', transceiver.stream, pc._dtlsRole);
sdp += 'a=rtcp-rsize\r\n';
@@ -1408,27 +4226,49 @@ module.exports = function(window, edgeVersion) {
RTCPeerConnection.prototype.createAnswer = function() {
var pc = this;
- if (this._isClosed) {
+ if (pc._isClosed) {
return Promise.reject(makeError('InvalidStateError',
'Can not call createAnswer after close'));
}
- var sdp = SDPUtils.writeSessionBoilerplate(this._sdpSessionId,
- this._sdpSessionVersion++);
- if (this.usingBundle) {
- sdp += 'a=group:BUNDLE ' + this.transceivers.map(function(t) {
+ if (!(pc.signalingState === 'have-remote-offer' ||
+ pc.signalingState === 'have-local-pranswer')) {
+ return Promise.reject(makeError('InvalidStateError',
+ 'Can not call createAnswer in signalingState ' + pc.signalingState));
+ }
+
+ var sdp = SDPUtils.writeSessionBoilerplate(pc._sdpSessionId,
+ pc._sdpSessionVersion++);
+ if (pc.usingBundle) {
+ sdp += 'a=group:BUNDLE ' + pc.transceivers.map(function(t) {
return t.mid;
}).join(' ') + '\r\n';
}
- var mediaSectionsInOffer = SDPUtils.splitSections(
- this.remoteDescription.sdp).length - 1;
- this.transceivers.forEach(function(transceiver, sdpMLineIndex) {
+ sdp += 'a=ice-options:trickle\r\n';
+
+ var mediaSectionsInOffer = SDPUtils.getMediaSections(
+ pc._remoteDescription.sdp).length;
+ pc.transceivers.forEach(function(transceiver, sdpMLineIndex) {
if (sdpMLineIndex + 1 > mediaSectionsInOffer) {
return;
}
- if (transceiver.isDatachannel) {
- sdp += 'm=application 0 DTLS/SCTP 5000\r\n' +
- 'c=IN IP4 0.0.0.0\r\n' +
+ if (transceiver.rejected) {
+ if (transceiver.kind === 'application') {
+ if (transceiver.protocol === 'DTLS/SCTP') { // legacy fmt
+ sdp += 'm=application 0 DTLS/SCTP 5000\r\n';
+ } else {
+ sdp += 'm=application 0 ' + transceiver.protocol +
+ ' webrtc-datachannel\r\n';
+ }
+ } else if (transceiver.kind === 'audio') {
+ sdp += 'm=audio 0 UDP/TLS/RTP/SAVPF 0\r\n' +
+ 'a=rtpmap:0 PCMU/8000\r\n';
+ } else if (transceiver.kind === 'video') {
+ sdp += 'm=video 0 UDP/TLS/RTP/SAVPF 120\r\n' +
+ 'a=rtpmap:120 VP8/90000\r\n';
+ }
+ sdp += 'c=IN IP4 0.0.0.0\r\n' +
+ 'a=inactive\r\n' +
'a=mid:' + transceiver.mid + '\r\n';
return;
}
@@ -1480,79 +4320,107 @@ module.exports = function(window, edgeVersion) {
};
RTCPeerConnection.prototype.addIceCandidate = function(candidate) {
+ var pc = this;
var sections;
- if (!candidate || candidate.candidate === '') {
- for (var j = 0; j < this.transceivers.length; j++) {
- if (this.transceivers[j].isDatachannel) {
- continue;
- }
- this.transceivers[j].iceTransport.addRemoteCandidate({});
- sections = SDPUtils.splitSections(this.remoteDescription.sdp);
- sections[j + 1] += 'a=end-of-candidates\r\n';
- this.remoteDescription.sdp = sections.join('');
- if (this.usingBundle) {
- break;
- }
- }
- } else if (!(candidate.sdpMLineIndex !== undefined || candidate.sdpMid)) {
- throw new TypeError('sdpMLineIndex or sdpMid required');
- } else if (!this.remoteDescription) {
- return Promise.reject(makeError('InvalidStateError',
- 'Can not add ICE candidate without a remote description'));
- } else {
- var sdpMLineIndex = candidate.sdpMLineIndex;
- if (candidate.sdpMid) {
- for (var i = 0; i < this.transceivers.length; i++) {
- if (this.transceivers[i].mid === candidate.sdpMid) {
- sdpMLineIndex = i;
+ if (candidate && !(candidate.sdpMLineIndex !== undefined ||
+ candidate.sdpMid)) {
+ return Promise.reject(new TypeError('sdpMLineIndex or sdpMid required'));
+ }
+
+ // TODO: needs to go into ops queue.
+ return new Promise(function(resolve, reject) {
+ if (!pc._remoteDescription) {
+ return reject(makeError('InvalidStateError',
+ 'Can not add ICE candidate without a remote description'));
+ } else if (!candidate || candidate.candidate === '') {
+ for (var j = 0; j < pc.transceivers.length; j++) {
+ if (pc.transceivers[j].rejected) {
+ continue;
+ }
+ pc.transceivers[j].iceTransport.addRemoteCandidate({});
+ sections = SDPUtils.getMediaSections(pc._remoteDescription.sdp);
+ sections[j] += 'a=end-of-candidates\r\n';
+ pc._remoteDescription.sdp =
+ SDPUtils.getDescription(pc._remoteDescription.sdp) +
+ sections.join('');
+ if (pc.usingBundle) {
break;
}
}
- }
- var transceiver = this.transceivers[sdpMLineIndex];
- if (transceiver) {
- if (transceiver.isDatachannel) {
- return Promise.resolve();
- }
- var cand = Object.keys(candidate.candidate).length > 0 ?
- SDPUtils.parseCandidate(candidate.candidate) : {};
- // Ignore Chrome's invalid candidates since Edge does not like them.
- if (cand.protocol === 'tcp' && (cand.port === 0 || cand.port === 9)) {
- return Promise.resolve();
- }
- // Ignore RTCP candidates, we assume RTCP-MUX.
- if (cand.component && cand.component !== 1) {
- return Promise.resolve();
- }
- // when using bundle, avoid adding candidates to the wrong
- // ice transport. And avoid adding candidates added in the SDP.
- if (sdpMLineIndex === 0 || (sdpMLineIndex > 0 &&
- transceiver.iceTransport !== this.transceivers[0].iceTransport)) {
- if (!maybeAddCandidate(transceiver.iceTransport, cand)) {
- return Promise.reject(makeError('OperationError',
- 'Can not add ICE candidate'));
+ } else {
+ var sdpMLineIndex = candidate.sdpMLineIndex;
+ if (candidate.sdpMid) {
+ for (var i = 0; i < pc.transceivers.length; i++) {
+ if (pc.transceivers[i].mid === candidate.sdpMid) {
+ sdpMLineIndex = i;
+ break;
+ }
}
}
+ var transceiver = pc.transceivers[sdpMLineIndex];
+ if (transceiver) {
+ if (transceiver.rejected) {
+ return resolve();
+ }
+ var cand = Object.keys(candidate.candidate).length > 0 ?
+ SDPUtils.parseCandidate(candidate.candidate) : {};
+ // Ignore Chrome's invalid candidates since Edge does not like them.
+ if (cand.protocol === 'tcp' && (cand.port === 0 || cand.port === 9)) {
+ return resolve();
+ }
+ // Ignore RTCP candidates, we assume RTCP-MUX.
+ if (cand.component && cand.component !== 1) {
+ return resolve();
+ }
+ // when using bundle, avoid adding candidates to the wrong
+ // ice transport. And avoid adding candidates added in the SDP.
+ if (sdpMLineIndex === 0 || (sdpMLineIndex > 0 &&
+ transceiver.iceTransport !== pc.transceivers[0].iceTransport)) {
+ if (!maybeAddCandidate(transceiver.iceTransport, cand)) {
+ return reject(makeError('OperationError',
+ 'Can not add ICE candidate'));
+ }
+ }
- // update the remoteDescription.
- var candidateString = candidate.candidate.trim();
- if (candidateString.indexOf('a=') === 0) {
- candidateString = candidateString.substr(2);
+ // update the remoteDescription.
+ var candidateString = candidate.candidate.trim();
+ if (candidateString.indexOf('a=') === 0) {
+ candidateString = candidateString.substr(2);
+ }
+ sections = SDPUtils.getMediaSections(pc._remoteDescription.sdp);
+ sections[sdpMLineIndex] += 'a=' +
+ (cand.type ? candidateString : 'end-of-candidates')
+ + '\r\n';
+ pc._remoteDescription.sdp =
+ SDPUtils.getDescription(pc._remoteDescription.sdp) +
+ sections.join('');
+ } else {
+ return reject(makeError('OperationError',
+ 'Can not add ICE candidate'));
}
- sections = SDPUtils.splitSections(this.remoteDescription.sdp);
- sections[sdpMLineIndex + 1] += 'a=' +
- (cand.type ? candidateString : 'end-of-candidates')
- + '\r\n';
- this.remoteDescription.sdp = sections.join('');
- } else {
- return Promise.reject(makeError('OperationError',
- 'Can not add ICE candidate'));
}
- }
- return Promise.resolve();
+ resolve();
+ });
};
- RTCPeerConnection.prototype.getStats = function() {
+ RTCPeerConnection.prototype.getStats = function(selector) {
+ if (selector && selector instanceof window.MediaStreamTrack) {
+ var senderOrReceiver = null;
+ this.transceivers.forEach(function(transceiver) {
+ if (transceiver.rtpSender &&
+ transceiver.rtpSender.track === selector) {
+ senderOrReceiver = transceiver.rtpSender;
+ } else if (transceiver.rtpReceiver &&
+ transceiver.rtpReceiver.track === selector) {
+ senderOrReceiver = transceiver.rtpReceiver;
+ }
+ });
+ if (!senderOrReceiver) {
+ throw makeError('InvalidAccessError', 'Invalid selector.');
+ }
+ return senderOrReceiver.getStats();
+ }
+
var promises = [];
this.transceivers.forEach(function(transceiver) {
['rtpSender', 'rtpReceiver', 'iceGatherer', 'iceTransport',
@@ -1562,30 +4430,38 @@ module.exports = function(window, edgeVersion) {
}
});
});
- var fixStatsType = function(stat) {
- return {
- inboundrtp: 'inbound-rtp',
- outboundrtp: 'outbound-rtp',
- candidatepair: 'candidate-pair',
- localcandidate: 'local-candidate',
- remotecandidate: 'remote-candidate'
- }[stat.type] || stat.type;
- };
- return new Promise(function(resolve) {
- // shim getStats with maplike support
+ return Promise.all(promises).then(function(allStats) {
var results = new Map();
- Promise.all(promises).then(function(res) {
- res.forEach(function(result) {
- Object.keys(result).forEach(function(id) {
- result[id].type = fixStatsType(result[id]);
- results.set(id, result[id]);
- });
+ allStats.forEach(function(stats) {
+ stats.forEach(function(stat) {
+ results.set(stat.id, stat);
});
- resolve(results);
});
+ return results;
});
};
+ // fix low-level stat names and return Map instead of object.
+ var ortcObjects = ['RTCRtpSender', 'RTCRtpReceiver', 'RTCIceGatherer',
+ 'RTCIceTransport', 'RTCDtlsTransport'];
+ ortcObjects.forEach(function(ortcObjectName) {
+ var obj = window[ortcObjectName];
+ if (obj && obj.prototype && obj.prototype.getStats) {
+ var nativeGetstats = obj.prototype.getStats;
+ obj.prototype.getStats = function() {
+ return nativeGetstats.apply(this)
+ .then(function(nativeStats) {
+ var mapStats = new Map();
+ Object.keys(nativeStats).forEach(function(id) {
+ nativeStats[id].type = fixStatsType(nativeStats[id]);
+ mapStats.set(id, nativeStats[id]);
+ });
+ return mapStats;
+ });
+ };
+ }
+ });
+
// legacy callback shims. Should be moved to adapter.js some days.
var methods = ['createOffer', 'createAnswer'];
methods.forEach(function(method) {
@@ -1652,7 +4528,7 @@ module.exports = function(window, edgeVersion) {
return RTCPeerConnection;
};
-},{"sdp":2}],2:[function(require,module,exports){
+},{"sdp":17}],17:[function(require,module,exports){
/* eslint-env node */
'use strict';
@@ -1682,6 +4558,19 @@ SDPUtils.splitSections = function(blob) {
});
};
+// returns the session description.
+SDPUtils.getDescription = function(blob) {
+ var sections = SDPUtils.splitSections(blob);
+ return sections && sections[0];
+};
+
+// returns the individual media sections.
+SDPUtils.getMediaSections = function(blob) {
+ var sections = SDPUtils.splitSections(blob);
+ sections.shift();
+ return sections;
+};
+
// Returns lines that start with a certain prefix.
SDPUtils.matchPrefix = function(blob, prefix) {
return SDPUtils.splitLines(blob).filter(function(line) {
@@ -1707,6 +4596,7 @@ SDPUtils.parseCandidate = function(line) {
protocol: parts[2].toLowerCase(),
priority: parseInt(parts[3], 10),
ip: parts[4],
+ address: parts[4], // address is an alias for ip.
port: parseInt(parts[5], 10),
// skip parts[6] == 'typ'
type: parts[7]
@@ -1742,7 +4632,7 @@ SDPUtils.writeCandidate = function(candidate) {
sdp.push(candidate.component);
sdp.push(candidate.protocol.toUpperCase());
sdp.push(candidate.priority);
- sdp.push(candidate.ip);
+ sdp.push(candidate.address || candidate.ip);
sdp.push(candidate.port);
var type = candidate.type;
@@ -1751,17 +4641,17 @@ SDPUtils.writeCandidate = function(candidate) {
if (type !== 'host' && candidate.relatedAddress &&
candidate.relatedPort) {
sdp.push('raddr');
- sdp.push(candidate.relatedAddress); // was: relAddr
+ sdp.push(candidate.relatedAddress);
sdp.push('rport');
- sdp.push(candidate.relatedPort); // was: relPort
+ sdp.push(candidate.relatedPort);
}
if (candidate.tcpType && candidate.protocol.toLowerCase() === 'tcp') {
sdp.push('tcptype');
sdp.push(candidate.tcpType);
}
- if (candidate.ufrag) {
+ if (candidate.usernameFragment || candidate.ufrag) {
sdp.push('ufrag');
- sdp.push(candidate.ufrag);
+ sdp.push(candidate.usernameFragment || candidate.ufrag);
}
return 'candidate:' + sdp.join(' ');
};
@@ -1770,7 +4660,7 @@ SDPUtils.writeCandidate = function(candidate) {
// a=ice-options:foo bar
SDPUtils.parseIceOptions = function(line) {
return line.substr(14).split(' ');
-}
+};
// Parses an rtpmap line, returns RTCRtpCoddecParameters. Sample input:
// a=rtpmap:111 opus/48000/2
@@ -1784,8 +4674,9 @@ SDPUtils.parseRtpMap = function(line) {
parsed.name = parts[0];
parsed.clockRate = parseInt(parts[1], 10); // was: clockrate
- // was: channels
- parsed.numChannels = parts.length === 3 ? parseInt(parts[2], 10) : 1;
+ parsed.channels = parts.length === 3 ? parseInt(parts[2], 10) : 1;
+ // legacy alias, got renamed back to channels in ORTC.
+ parsed.numChannels = parsed.channels;
return parsed;
};
@@ -1796,8 +4687,9 @@ SDPUtils.writeRtpMap = function(codec) {
if (codec.preferredPayloadType !== undefined) {
pt = codec.preferredPayloadType;
}
+ var channels = codec.channels || codec.numChannels || 1;
return 'a=rtpmap:' + pt + ' ' + codec.name + '/' + codec.clockRate +
- (codec.numChannels !== 1 ? '/' + codec.numChannels : '') + '\r\n';
+ (channels !== 1 ? '/' + channels : '') + '\r\n';
};
// Parses an a=extmap line (headerextension from RFC 5285). Sample input:
@@ -1846,7 +4738,11 @@ SDPUtils.writeFmtp = function(codec) {
if (codec.parameters && Object.keys(codec.parameters).length) {
var params = [];
Object.keys(codec.parameters).forEach(function(param) {
- params.push(param + '=' + codec.parameters[param]);
+ if (codec.parameters[param]) {
+ params.push(param + '=' + codec.parameters[param]);
+ } else {
+ params.push(param);
+ }
});
line += 'a=fmtp:' + pt + ' ' + params.join(';') + '\r\n';
}
@@ -1897,6 +4793,16 @@ SDPUtils.parseSsrcMedia = function(line) {
return parts;
};
+SDPUtils.parseSsrcGroup = function(line) {
+ var parts = line.substr(13).split(' ');
+ return {
+ semantics: parts.shift(),
+ ssrcs: parts.map(function(ssrc) {
+ return parseInt(ssrc, 10);
+ })
+ };
+};
+
// Extracts the MID (RFC 5888) from a media section.
// returns the MID or undefined if no mid line was found.
SDPUtils.getMid = function(mediaSection) {
@@ -1904,7 +4810,7 @@ SDPUtils.getMid = function(mediaSection) {
if (mid) {
return mid.substr(6);
}
-}
+};
SDPUtils.parseFingerprint = function(line) {
var parts = line.substr(14).split(' ');
@@ -2038,9 +4944,11 @@ SDPUtils.writeRtpDescription = function(kind, caps) {
}
sdp += 'a=rtcp-mux\r\n';
- caps.headerExtensions.forEach(function(extension) {
- sdp += SDPUtils.writeExtmap(extension);
- });
+ if (caps.headerExtensions) {
+ caps.headerExtensions.forEach(function(extension) {
+ sdp += SDPUtils.writeExtmap(extension);
+ });
+ }
// FIXME: write fecMechanisms.
return sdp;
};
@@ -2066,8 +4974,7 @@ SDPUtils.parseRtpEncodingParameters = function(mediaSection) {
var flows = SDPUtils.matchPrefix(mediaSection, 'a=ssrc-group:FID')
.map(function(line) {
- var parts = line.split(' ');
- parts.shift();
+ var parts = line.substr(17).split(' ');
return parts.map(function(part) {
return parseInt(part, 10);
});
@@ -2080,16 +4987,16 @@ SDPUtils.parseRtpEncodingParameters = function(mediaSection) {
if (codec.name.toUpperCase() === 'RTX' && codec.parameters.apt) {
var encParam = {
ssrc: primarySsrc,
- codecPayloadType: parseInt(codec.parameters.apt, 10),
- rtx: {
- ssrc: secondarySsrc
- }
+ codecPayloadType: parseInt(codec.parameters.apt, 10)
};
+ if (primarySsrc && secondarySsrc) {
+ encParam.rtx = {ssrc: secondarySsrc};
+ }
encodingParameters.push(encParam);
if (hasRed) {
encParam = JSON.parse(JSON.stringify(encParam));
encParam.fec = {
- ssrc: secondarySsrc,
+ ssrc: primarySsrc,
mechanism: hasUlpfec ? 'red+ulpfec' : 'red'
};
encodingParameters.push(encParam);
@@ -2125,8 +5032,7 @@ SDPUtils.parseRtpEncodingParameters = function(mediaSection) {
SDPUtils.parseRtcpParameters = function(mediaSection) {
var rtcpParameters = {};
- var cname;
- // Gets the first SSRC. Note that with RTX there might be multiple
+ // Gets the first SSRC. Note tha with RTX there might be multiple
// SSRCs.
var remoteSsrc = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:')
.map(function(line) {
@@ -2167,8 +5073,8 @@ SDPUtils.parseMsid = function(mediaSection) {
.map(function(line) {
return SDPUtils.parseSsrcMedia(line);
})
- .filter(function(parts) {
- return parts.attribute === 'msid';
+ .filter(function(msidParts) {
+ return msidParts.attribute === 'msid';
});
if (planB.length > 0) {
parts = planB[0].value.split(' ');
@@ -2188,7 +5094,8 @@ SDPUtils.generateSessionId = function() {
// sessId argument is optional - if not supplied it will
// be generated randomly
// sessVersion is optional and defaults to 2
-SDPUtils.writeSessionBoilerplate = function(sessId, sessVer) {
+// sessUser is optional and defaults to 'thisisadapterortc'
+SDPUtils.writeSessionBoilerplate = function(sessId, sessVer, sessUser) {
var sessionId;
var version = sessVer !== undefined ? sessVer : 2;
if (sessId) {
@@ -2196,9 +5103,11 @@ SDPUtils.writeSessionBoilerplate = function(sessId, sessVer) {
} else {
sessionId = SDPUtils.generateSessionId();
}
+ var user = sessUser || 'thisisadapterortc';
// FIXME: sess-id should be an NTP timestamp.
return 'v=0\r\n' +
- 'o=thisisadapterortc ' + sessionId + ' ' + version + ' IN IP4 127.0.0.1\r\n' +
+ 'o=' + user + ' ' + sessionId + ' ' + version +
+ ' IN IP4 127.0.0.1\r\n' +
's=-\r\n' +
't=0 0\r\n';
};
@@ -2290,2477 +5199,47 @@ SDPUtils.isRejected = function(mediaSection) {
SDPUtils.parseMLine = function(mediaSection) {
var lines = SDPUtils.splitLines(mediaSection);
- var mline = lines[0].split(' ');
+ var parts = lines[0].substr(2).split(' ');
return {
- kind: mline[0].substr(2),
- port: parseInt(mline[1], 10),
- protocol: mline[2],
- fmt: mline.slice(3).join(' ')
+ kind: parts[0],
+ port: parseInt(parts[1], 10),
+ protocol: parts[2],
+ fmt: parts.slice(3).join(' ')
};
};
+SDPUtils.parseOLine = function(mediaSection) {
+ var line = SDPUtils.matchPrefix(mediaSection, 'o=')[0];
+ var parts = line.substr(2).split(' ');
+ return {
+ username: parts[0],
+ sessionId: parts[1],
+ sessionVersion: parseInt(parts[2], 10),
+ netType: parts[3],
+ addressType: parts[4],
+ address: parts[5]
+ };
+};
+
+// a very naive interpretation of a valid SDP.
+SDPUtils.isValidSDP = function(blob) {
+ if (typeof blob !== 'string' || blob.length === 0) {
+ return false;
+ }
+ var lines = SDPUtils.splitLines(blob);
+ for (var i = 0; i < lines.length; i++) {
+ if (lines[i].length < 2 || lines[i].charAt(1) !== '=') {
+ return false;
+ }
+ // TODO: check the modifier a bit more.
+ }
+ return true;
+};
+
// Expose public methods.
if (typeof module === 'object') {
module.exports = SDPUtils;
}
-},{}],3:[function(require,module,exports){
-(function (global){
-/*
- * Copyright (c) 2016 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.
- */
- /* eslint-env node */
-
-'use strict';
-
-var adapterFactory = require('./adapter_factory.js');
-module.exports = adapterFactory({window: global.window});
-
-}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-},{"./adapter_factory.js":4}],4:[function(require,module,exports){
-/*
- * Copyright (c) 2016 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.
- */
- /* eslint-env node */
-
-'use strict';
-
-var utils = require('./utils');
-// Shimming starts here.
-module.exports = function(dependencies, opts) {
- var window = dependencies && dependencies.window;
-
- var options = {
- shimChrome: true,
- shimFirefox: true,
- shimEdge: true,
- shimSafari: true,
- };
-
- for (var key in opts) {
- if (hasOwnProperty.call(opts, key)) {
- options[key] = opts[key];
- }
- }
-
- // Utils.
- var logging = utils.log;
- var browserDetails = utils.detectBrowser(window);
-
- // Uncomment the line below if you want logging to occur, including logging
- // for the switch statement below. Can also be turned on in the browser via
- // adapter.disableLog(false), but then logging from the switch statement below
- // will not appear.
- // require('./utils').disableLog(false);
-
- // Browser shims.
- var chromeShim = require('./chrome/chrome_shim') || null;
- var edgeShim = require('./edge/edge_shim') || null;
- var firefoxShim = require('./firefox/firefox_shim') || null;
- var safariShim = require('./safari/safari_shim') || null;
- var commonShim = require('./common_shim') || null;
-
- // Export to the adapter global object visible in the browser.
- var adapter = {
- browserDetails: browserDetails,
- commonShim: commonShim,
- extractVersion: utils.extractVersion,
- disableLog: utils.disableLog,
- disableWarnings: utils.disableWarnings
- };
-
- // Shim browser if found.
- switch (browserDetails.browser) {
- case 'chrome':
- if (!chromeShim || !chromeShim.shimPeerConnection ||
- !options.shimChrome) {
- logging('Chrome shim is not included in this adapter release.');
- return adapter;
- }
- logging('adapter.js shimming chrome.');
- // Export to the adapter global object visible in the browser.
- adapter.browserShim = chromeShim;
- commonShim.shimCreateObjectURL(window);
-
- chromeShim.shimGetUserMedia(window);
- chromeShim.shimMediaStream(window);
- chromeShim.shimSourceObject(window);
- chromeShim.shimPeerConnection(window);
- chromeShim.shimOnTrack(window);
- chromeShim.shimAddTrackRemoveTrack(window);
- chromeShim.shimGetSendersWithDtmf(window);
-
- commonShim.shimRTCIceCandidate(window);
- commonShim.shimMaxMessageSize(window);
- commonShim.shimSendThrowTypeError(window);
- break;
- case 'firefox':
- if (!firefoxShim || !firefoxShim.shimPeerConnection ||
- !options.shimFirefox) {
- logging('Firefox shim is not included in this adapter release.');
- return adapter;
- }
- logging('adapter.js shimming firefox.');
- // Export to the adapter global object visible in the browser.
- adapter.browserShim = firefoxShim;
- commonShim.shimCreateObjectURL(window);
-
- firefoxShim.shimGetUserMedia(window);
- firefoxShim.shimSourceObject(window);
- firefoxShim.shimPeerConnection(window);
- firefoxShim.shimOnTrack(window);
- firefoxShim.shimRemoveStream(window);
-
- commonShim.shimRTCIceCandidate(window);
- commonShim.shimMaxMessageSize(window);
- commonShim.shimSendThrowTypeError(window);
- break;
- case 'edge':
- if (!edgeShim || !edgeShim.shimPeerConnection || !options.shimEdge) {
- logging('MS edge shim is not included in this adapter release.');
- return adapter;
- }
- logging('adapter.js shimming edge.');
- // Export to the adapter global object visible in the browser.
- adapter.browserShim = edgeShim;
- commonShim.shimCreateObjectURL(window);
-
- edgeShim.shimGetUserMedia(window);
- edgeShim.shimPeerConnection(window);
- edgeShim.shimReplaceTrack(window);
-
- // the edge shim implements the full RTCIceCandidate object.
-
- commonShim.shimMaxMessageSize(window);
- commonShim.shimSendThrowTypeError(window);
- break;
- case 'safari':
- if (!safariShim || !options.shimSafari) {
- logging('Safari shim is not included in this adapter release.');
- return adapter;
- }
- logging('adapter.js shimming safari.');
- // Export to the adapter global object visible in the browser.
- adapter.browserShim = safariShim;
- commonShim.shimCreateObjectURL(window);
-
- safariShim.shimRTCIceServerUrls(window);
- safariShim.shimCallbacksAPI(window);
- safariShim.shimLocalStreamsAPI(window);
- safariShim.shimRemoteStreamsAPI(window);
- safariShim.shimTrackEventTransceiver(window);
- safariShim.shimGetUserMedia(window);
- safariShim.shimCreateOfferLegacy(window);
-
- commonShim.shimRTCIceCandidate(window);
- commonShim.shimMaxMessageSize(window);
- commonShim.shimSendThrowTypeError(window);
- break;
- default:
- logging('Unsupported browser!');
- break;
- }
-
- return adapter;
-};
-
-},{"./chrome/chrome_shim":5,"./common_shim":7,"./edge/edge_shim":8,"./firefox/firefox_shim":10,"./safari/safari_shim":12,"./utils":13}],5:[function(require,module,exports){
-
-/*
- * Copyright (c) 2016 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.
- */
- /* eslint-env node */
-'use strict';
-var utils = require('../utils.js');
-var logging = utils.log;
-
-module.exports = {
- shimGetUserMedia: require('./getusermedia'),
- shimMediaStream: function(window) {
- window.MediaStream = window.MediaStream || window.webkitMediaStream;
- },
-
- shimOnTrack: function(window) {
- if (typeof window === 'object' && window.RTCPeerConnection && !('ontrack' in
- window.RTCPeerConnection.prototype)) {
- Object.defineProperty(window.RTCPeerConnection.prototype, 'ontrack', {
- get: function() {
- return this._ontrack;
- },
- set: function(f) {
- if (this._ontrack) {
- this.removeEventListener('track', this._ontrack);
- }
- this.addEventListener('track', this._ontrack = f);
- }
- });
- var origSetRemoteDescription =
- window.RTCPeerConnection.prototype.setRemoteDescription;
- window.RTCPeerConnection.prototype.setRemoteDescription = function() {
- var pc = this;
- if (!pc._ontrackpoly) {
- pc._ontrackpoly = function(e) {
- // onaddstream does not fire when a track is added to an existing
- // stream. But stream.onaddtrack is implemented so we use that.
- e.stream.addEventListener('addtrack', function(te) {
- var receiver;
- if (window.RTCPeerConnection.prototype.getReceivers) {
- receiver = pc.getReceivers().find(function(r) {
- return r.track && r.track.id === te.track.id;
- });
- } else {
- receiver = {track: te.track};
- }
-
- var event = new Event('track');
- event.track = te.track;
- event.receiver = receiver;
- event.transceiver = {receiver: receiver};
- event.streams = [e.stream];
- pc.dispatchEvent(event);
- });
- e.stream.getTracks().forEach(function(track) {
- var receiver;
- if (window.RTCPeerConnection.prototype.getReceivers) {
- receiver = pc.getReceivers().find(function(r) {
- return r.track && r.track.id === track.id;
- });
- } else {
- receiver = {track: track};
- }
- var event = new Event('track');
- event.track = track;
- event.receiver = receiver;
- event.transceiver = {receiver: receiver};
- event.streams = [e.stream];
- pc.dispatchEvent(event);
- });
- };
- pc.addEventListener('addstream', pc._ontrackpoly);
- }
- return origSetRemoteDescription.apply(pc, arguments);
- };
- } else if (!('RTCRtpTransceiver' in window)) {
- utils.wrapPeerConnectionEvent(window, 'track', function(e) {
- if (!e.transceiver) {
- e.transceiver = {receiver: e.receiver};
- }
- return e;
- });
- }
- },
-
- shimGetSendersWithDtmf: function(window) {
- // Overrides addTrack/removeTrack, depends on shimAddTrackRemoveTrack.
- if (typeof window === 'object' && window.RTCPeerConnection &&
- !('getSenders' in window.RTCPeerConnection.prototype) &&
- 'createDTMFSender' in window.RTCPeerConnection.prototype) {
- var shimSenderWithDtmf = function(pc, track) {
- return {
- track: track,
- get dtmf() {
- if (this._dtmf === undefined) {
- if (track.kind === 'audio') {
- this._dtmf = pc.createDTMFSender(track);
- } else {
- this._dtmf = null;
- }
- }
- return this._dtmf;
- },
- _pc: pc
- };
- };
-
- // augment addTrack when getSenders is not available.
- if (!window.RTCPeerConnection.prototype.getSenders) {
- window.RTCPeerConnection.prototype.getSenders = function() {
- this._senders = this._senders || [];
- return this._senders.slice(); // return a copy of the internal state.
- };
- var origAddTrack = window.RTCPeerConnection.prototype.addTrack;
- window.RTCPeerConnection.prototype.addTrack = function(track, stream) {
- var pc = this;
- var sender = origAddTrack.apply(pc, arguments);
- if (!sender) {
- sender = shimSenderWithDtmf(pc, track);
- pc._senders.push(sender);
- }
- return sender;
- };
-
- var origRemoveTrack = window.RTCPeerConnection.prototype.removeTrack;
- window.RTCPeerConnection.prototype.removeTrack = function(sender) {
- var pc = this;
- origRemoveTrack.apply(pc, arguments);
- var idx = pc._senders.indexOf(sender);
- if (idx !== -1) {
- pc._senders.splice(idx, 1);
- }
- };
- }
- var origAddStream = window.RTCPeerConnection.prototype.addStream;
- window.RTCPeerConnection.prototype.addStream = function(stream) {
- var pc = this;
- pc._senders = pc._senders || [];
- origAddStream.apply(pc, [stream]);
- stream.getTracks().forEach(function(track) {
- pc._senders.push(shimSenderWithDtmf(pc, track));
- });
- };
-
- var origRemoveStream = window.RTCPeerConnection.prototype.removeStream;
- window.RTCPeerConnection.prototype.removeStream = function(stream) {
- var pc = this;
- pc._senders = pc._senders || [];
- origRemoveStream.apply(pc, [stream]);
-
- stream.getTracks().forEach(function(track) {
- var sender = pc._senders.find(function(s) {
- return s.track === track;
- });
- if (sender) {
- pc._senders.splice(pc._senders.indexOf(sender), 1); // remove sender
- }
- });
- };
- } else if (typeof window === 'object' && window.RTCPeerConnection &&
- 'getSenders' in window.RTCPeerConnection.prototype &&
- 'createDTMFSender' in window.RTCPeerConnection.prototype &&
- window.RTCRtpSender &&
- !('dtmf' in window.RTCRtpSender.prototype)) {
- var origGetSenders = window.RTCPeerConnection.prototype.getSenders;
- window.RTCPeerConnection.prototype.getSenders = function() {
- var pc = this;
- var senders = origGetSenders.apply(pc, []);
- senders.forEach(function(sender) {
- sender._pc = pc;
- });
- return senders;
- };
-
- Object.defineProperty(window.RTCRtpSender.prototype, 'dtmf', {
- get: function() {
- if (this._dtmf === undefined) {
- if (this.track.kind === 'audio') {
- this._dtmf = this._pc.createDTMFSender(this.track);
- } else {
- this._dtmf = null;
- }
- }
- return this._dtmf;
- }
- });
- }
- },
-
- shimSourceObject: function(window) {
- var URL = window && window.URL;
-
- 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() {
- return this._srcObject;
- },
- set: function(stream) {
- var self = this;
- // Use _srcObject as a private property for this shim
- this._srcObject = stream;
- if (this.src) {
- URL.revokeObjectURL(this.src);
- }
-
- if (!stream) {
- this.src = '';
- return undefined;
- }
- this.src = URL.createObjectURL(stream);
- // We need to recreate the blob url when a track is added or
- // removed. Doing it manually since we want to avoid a recursion.
- stream.addEventListener('addtrack', function() {
- if (self.src) {
- URL.revokeObjectURL(self.src);
- }
- self.src = URL.createObjectURL(stream);
- });
- stream.addEventListener('removetrack', function() {
- if (self.src) {
- URL.revokeObjectURL(self.src);
- }
- self.src = URL.createObjectURL(stream);
- });
- }
- });
- }
- }
- },
-
- shimAddTrackRemoveTrackWithNative: function(window) {
- // shim addTrack/removeTrack with native variants in order to make
- // the interactions with legacy getLocalStreams behave as in other browsers.
- // Keeps a mapping stream.id => [stream, rtpsenders...]
- window.RTCPeerConnection.prototype.getLocalStreams = function() {
- var pc = this;
- this._shimmedLocalStreams = this._shimmedLocalStreams || {};
- return Object.keys(this._shimmedLocalStreams).map(function(streamId) {
- return pc._shimmedLocalStreams[streamId][0];
- });
- };
-
- var origAddTrack = window.RTCPeerConnection.prototype.addTrack;
- window.RTCPeerConnection.prototype.addTrack = function(track, stream) {
- if (!stream) {
- return origAddTrack.apply(this, arguments);
- }
- this._shimmedLocalStreams = this._shimmedLocalStreams || {};
-
- var sender = origAddTrack.apply(this, arguments);
- if (!this._shimmedLocalStreams[stream.id]) {
- this._shimmedLocalStreams[stream.id] = [stream, sender];
- } else if (this._shimmedLocalStreams[stream.id].indexOf(sender) === -1) {
- this._shimmedLocalStreams[stream.id].push(sender);
- }
- return sender;
- };
-
- var origAddStream = window.RTCPeerConnection.prototype.addStream;
- window.RTCPeerConnection.prototype.addStream = function(stream) {
- var pc = this;
- this._shimmedLocalStreams = this._shimmedLocalStreams || {};
-
- stream.getTracks().forEach(function(track) {
- var alreadyExists = pc.getSenders().find(function(s) {
- return s.track === track;
- });
- if (alreadyExists) {
- throw new DOMException('Track already exists.',
- 'InvalidAccessError');
- }
- });
- var existingSenders = pc.getSenders();
- origAddStream.apply(this, arguments);
- var newSenders = pc.getSenders().filter(function(newSender) {
- return existingSenders.indexOf(newSender) === -1;
- });
- this._shimmedLocalStreams[stream.id] = [stream].concat(newSenders);
- };
-
- var origRemoveStream = window.RTCPeerConnection.prototype.removeStream;
- window.RTCPeerConnection.prototype.removeStream = function(stream) {
- this._shimmedLocalStreams = this._shimmedLocalStreams || {};
- delete this._shimmedLocalStreams[stream.id];
- return origRemoveStream.apply(this, arguments);
- };
-
- var origRemoveTrack = window.RTCPeerConnection.prototype.removeTrack;
- window.RTCPeerConnection.prototype.removeTrack = function(sender) {
- var pc = this;
- this._shimmedLocalStreams = this._shimmedLocalStreams || {};
- if (sender) {
- Object.keys(this._shimmedLocalStreams).forEach(function(streamId) {
- var idx = pc._shimmedLocalStreams[streamId].indexOf(sender);
- if (idx !== -1) {
- pc._shimmedLocalStreams[streamId].splice(idx, 1);
- }
- if (pc._shimmedLocalStreams[streamId].length === 1) {
- delete pc._shimmedLocalStreams[streamId];
- }
- });
- }
- return origRemoveTrack.apply(this, arguments);
- };
- },
-
- shimAddTrackRemoveTrack: function(window) {
- var browserDetails = utils.detectBrowser(window);
- // shim addTrack and removeTrack.
- if (window.RTCPeerConnection.prototype.addTrack &&
- browserDetails.version >= 65) {
- return this.shimAddTrackRemoveTrackWithNative(window);
- }
-
- // also shim pc.getLocalStreams when addTrack is shimmed
- // to return the original streams.
- var origGetLocalStreams = window.RTCPeerConnection.prototype
- .getLocalStreams;
- window.RTCPeerConnection.prototype.getLocalStreams = function() {
- var pc = this;
- var nativeStreams = origGetLocalStreams.apply(this);
- pc._reverseStreams = pc._reverseStreams || {};
- return nativeStreams.map(function(stream) {
- return pc._reverseStreams[stream.id];
- });
- };
-
- var origAddStream = window.RTCPeerConnection.prototype.addStream;
- window.RTCPeerConnection.prototype.addStream = function(stream) {
- var pc = this;
- pc._streams = pc._streams || {};
- pc._reverseStreams = pc._reverseStreams || {};
-
- stream.getTracks().forEach(function(track) {
- var alreadyExists = pc.getSenders().find(function(s) {
- return s.track === track;
- });
- if (alreadyExists) {
- throw new DOMException('Track already exists.',
- 'InvalidAccessError');
- }
- });
- // Add identity mapping for consistency with addTrack.
- // Unless this is being used with a stream from addTrack.
- if (!pc._reverseStreams[stream.id]) {
- var newStream = new window.MediaStream(stream.getTracks());
- pc._streams[stream.id] = newStream;
- pc._reverseStreams[newStream.id] = stream;
- stream = newStream;
- }
- origAddStream.apply(pc, [stream]);
- };
-
- var origRemoveStream = window.RTCPeerConnection.prototype.removeStream;
- window.RTCPeerConnection.prototype.removeStream = function(stream) {
- var pc = this;
- pc._streams = pc._streams || {};
- pc._reverseStreams = pc._reverseStreams || {};
-
- origRemoveStream.apply(pc, [(pc._streams[stream.id] || stream)]);
- delete pc._reverseStreams[(pc._streams[stream.id] ?
- pc._streams[stream.id].id : stream.id)];
- delete pc._streams[stream.id];
- };
-
- window.RTCPeerConnection.prototype.addTrack = function(track, stream) {
- var pc = this;
- if (pc.signalingState === 'closed') {
- throw new DOMException(
- 'The RTCPeerConnection\'s signalingState is \'closed\'.',
- 'InvalidStateError');
- }
- var streams = [].slice.call(arguments, 1);
- if (streams.length !== 1 ||
- !streams[0].getTracks().find(function(t) {
- return t === track;
- })) {
- // this is not fully correct but all we can manage without
- // [[associated MediaStreams]] internal slot.
- throw new DOMException(
- 'The adapter.js addTrack polyfill only supports a single ' +
- ' stream which is associated with the specified track.',
- 'NotSupportedError');
- }
-
- var alreadyExists = pc.getSenders().find(function(s) {
- return s.track === track;
- });
- if (alreadyExists) {
- throw new DOMException('Track already exists.',
- 'InvalidAccessError');
- }
-
- pc._streams = pc._streams || {};
- pc._reverseStreams = pc._reverseStreams || {};
- var oldStream = pc._streams[stream.id];
- if (oldStream) {
- // this is using odd Chrome behaviour, use with caution:
- // https://bugs.chromium.org/p/webrtc/issues/detail?id=7815
- // Note: we rely on the high-level addTrack/dtmf shim to
- // create the sender with a dtmf sender.
- oldStream.addTrack(track);
-
- // Trigger ONN async.
- Promise.resolve().then(function() {
- pc.dispatchEvent(new Event('negotiationneeded'));
- });
- } else {
- var newStream = new window.MediaStream([track]);
- pc._streams[stream.id] = newStream;
- pc._reverseStreams[newStream.id] = stream;
- pc.addStream(newStream);
- }
- return pc.getSenders().find(function(s) {
- return s.track === track;
- });
- };
-
- // replace the internal stream id with the external one and
- // vice versa.
- function replaceInternalStreamId(pc, description) {
- var sdp = description.sdp;
- Object.keys(pc._reverseStreams || []).forEach(function(internalId) {
- var externalStream = pc._reverseStreams[internalId];
- var internalStream = pc._streams[externalStream.id];
- sdp = sdp.replace(new RegExp(internalStream.id, 'g'),
- externalStream.id);
- });
- return new RTCSessionDescription({
- type: description.type,
- sdp: sdp
- });
- }
- function replaceExternalStreamId(pc, description) {
- var sdp = description.sdp;
- Object.keys(pc._reverseStreams || []).forEach(function(internalId) {
- var externalStream = pc._reverseStreams[internalId];
- var internalStream = pc._streams[externalStream.id];
- sdp = sdp.replace(new RegExp(externalStream.id, 'g'),
- internalStream.id);
- });
- return new RTCSessionDescription({
- type: description.type,
- sdp: sdp
- });
- }
- ['createOffer', 'createAnswer'].forEach(function(method) {
- var nativeMethod = window.RTCPeerConnection.prototype[method];
- window.RTCPeerConnection.prototype[method] = function() {
- var pc = this;
- var args = arguments;
- var isLegacyCall = arguments.length &&
- typeof arguments[0] === 'function';
- if (isLegacyCall) {
- return nativeMethod.apply(pc, [
- function(description) {
- var desc = replaceInternalStreamId(pc, description);
- args[0].apply(null, [desc]);
- },
- function(err) {
- if (args[1]) {
- args[1].apply(null, err);
- }
- }, arguments[2]
- ]);
- }
- return nativeMethod.apply(pc, arguments)
- .then(function(description) {
- return replaceInternalStreamId(pc, description);
- });
- };
- });
-
- var origSetLocalDescription =
- window.RTCPeerConnection.prototype.setLocalDescription;
- window.RTCPeerConnection.prototype.setLocalDescription = function() {
- var pc = this;
- if (!arguments.length || !arguments[0].type) {
- return origSetLocalDescription.apply(pc, arguments);
- }
- arguments[0] = replaceExternalStreamId(pc, arguments[0]);
- return origSetLocalDescription.apply(pc, arguments);
- };
-
- // TODO: mangle getStats: https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamstats-streamidentifier
-
- var origLocalDescription = Object.getOwnPropertyDescriptor(
- window.RTCPeerConnection.prototype, 'localDescription');
- Object.defineProperty(window.RTCPeerConnection.prototype,
- 'localDescription', {
- get: function() {
- var pc = this;
- var description = origLocalDescription.get.apply(this);
- if (description.type === '') {
- return description;
- }
- return replaceInternalStreamId(pc, description);
- }
- });
-
- window.RTCPeerConnection.prototype.removeTrack = function(sender) {
- var pc = this;
- if (pc.signalingState === 'closed') {
- throw new DOMException(
- 'The RTCPeerConnection\'s signalingState is \'closed\'.',
- 'InvalidStateError');
- }
- // We can not yet check for sender instanceof RTCRtpSender
- // since we shim RTPSender. So we check if sender._pc is set.
- if (!sender._pc) {
- throw new DOMException('Argument 1 of RTCPeerConnection.removeTrack ' +
- 'does not implement interface RTCRtpSender.', 'TypeError');
- }
- var isLocal = sender._pc === pc;
- if (!isLocal) {
- throw new DOMException('Sender was not created by this connection.',
- 'InvalidAccessError');
- }
-
- // Search for the native stream the senders track belongs to.
- pc._streams = pc._streams || {};
- var stream;
- Object.keys(pc._streams).forEach(function(streamid) {
- var hasTrack = pc._streams[streamid].getTracks().find(function(track) {
- return sender.track === track;
- });
- if (hasTrack) {
- stream = pc._streams[streamid];
- }
- });
-
- if (stream) {
- if (stream.getTracks().length === 1) {
- // if this is the last track of the stream, remove the stream. This
- // takes care of any shimmed _senders.
- pc.removeStream(pc._reverseStreams[stream.id]);
- } else {
- // relying on the same odd chrome behaviour as above.
- stream.removeTrack(sender.track);
- }
- pc.dispatchEvent(new Event('negotiationneeded'));
- }
- };
- },
-
- shimPeerConnection: function(window) {
- var browserDetails = utils.detectBrowser(window);
-
- // The RTCPeerConnection object.
- if (!window.RTCPeerConnection && window.webkitRTCPeerConnection) {
- window.RTCPeerConnection = function(pcConfig, pcConstraints) {
- // Translate iceTransportPolicy to iceTransports,
- // see https://code.google.com/p/webrtc/issues/detail?id=4869
- // this was fixed in M56 along with unprefixing RTCPeerConnection.
- logging('PeerConnection');
- if (pcConfig && pcConfig.iceTransportPolicy) {
- pcConfig.iceTransports = pcConfig.iceTransportPolicy;
- }
-
- return new window.webkitRTCPeerConnection(pcConfig, pcConstraints);
- };
- window.RTCPeerConnection.prototype =
- window.webkitRTCPeerConnection.prototype;
- // wrap static methods. Currently just generateCertificate.
- if (window.webkitRTCPeerConnection.generateCertificate) {
- Object.defineProperty(window.RTCPeerConnection, 'generateCertificate', {
- get: function() {
- return window.webkitRTCPeerConnection.generateCertificate;
- }
- });
- }
- } else {
- // migrate from non-spec RTCIceServer.url to RTCIceServer.urls
- var OrigPeerConnection = window.RTCPeerConnection;
- window.RTCPeerConnection = function(pcConfig, pcConstraints) {
- if (pcConfig && pcConfig.iceServers) {
- var newIceServers = [];
- for (var i = 0; i < pcConfig.iceServers.length; i++) {
- var server = pcConfig.iceServers[i];
- if (!server.hasOwnProperty('urls') &&
- server.hasOwnProperty('url')) {
- utils.deprecated('RTCIceServer.url', 'RTCIceServer.urls');
- server = JSON.parse(JSON.stringify(server));
- server.urls = server.url;
- newIceServers.push(server);
- } else {
- newIceServers.push(pcConfig.iceServers[i]);
- }
- }
- pcConfig.iceServers = newIceServers;
- }
- return new OrigPeerConnection(pcConfig, pcConstraints);
- };
- window.RTCPeerConnection.prototype = OrigPeerConnection.prototype;
- // wrap static methods. Currently just generateCertificate.
- Object.defineProperty(window.RTCPeerConnection, 'generateCertificate', {
- get: function() {
- return OrigPeerConnection.generateCertificate;
- }
- });
- }
-
- var origGetStats = window.RTCPeerConnection.prototype.getStats;
- window.RTCPeerConnection.prototype.getStats = function(selector,
- successCallback, errorCallback) {
- var pc = 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.apply(this, arguments);
- }
-
- // When spec-style getStats is supported, return those when called with
- // either no arguments or the selector argument is null.
- if (origGetStats.length === 0 && (arguments.length === 0 ||
- typeof arguments[0] !== 'function')) {
- return origGetStats.apply(this, []);
- }
-
- var fixChromeStats_ = function(response) {
- var standardReport = {};
- var reports = response.result();
- reports.forEach(function(report) {
- var standardStats = {
- id: report.id,
- timestamp: report.timestamp,
- type: {
- localcandidate: 'local-candidate',
- remotecandidate: 'remote-candidate'
- }[report.type] || report.type
- };
- report.names().forEach(function(name) {
- standardStats[name] = report.stat(name);
- });
- standardReport[standardStats.id] = standardStats;
- });
-
- return standardReport;
- };
-
- // shim getStats with maplike support
- var makeMapStats = function(stats) {
- return new Map(Object.keys(stats).map(function(key) {
- return [key, stats[key]];
- }));
- };
-
- if (arguments.length >= 2) {
- var successCallbackWrapper_ = function(response) {
- args[1](makeMapStats(fixChromeStats_(response)));
- };
-
- return origGetStats.apply(this, [successCallbackWrapper_,
- arguments[0]]);
- }
-
- // promise-support
- return new Promise(function(resolve, reject) {
- origGetStats.apply(pc, [
- function(response) {
- resolve(makeMapStats(fixChromeStats_(response)));
- }, reject]);
- }).then(successCallback, errorCallback);
- };
-
- // add promise support -- natively available in Chrome 51
- if (browserDetails.version < 51) {
- ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate']
- .forEach(function(method) {
- var nativeMethod = window.RTCPeerConnection.prototype[method];
- window.RTCPeerConnection.prototype[method] = function() {
- var args = arguments;
- var pc = this;
- var promise = new Promise(function(resolve, reject) {
- nativeMethod.apply(pc, [args[0], resolve, reject]);
- });
- if (args.length < 2) {
- return promise;
- }
- return promise.then(function() {
- args[1].apply(null, []);
- },
- function(err) {
- if (args.length >= 3) {
- args[2].apply(null, [err]);
- }
- });
- };
- });
- }
-
- // promise support for createOffer and createAnswer. Available (without
- // bugs) since M52: crbug/619289
- if (browserDetails.version < 52) {
- ['createOffer', 'createAnswer'].forEach(function(method) {
- var nativeMethod = window.RTCPeerConnection.prototype[method];
- window.RTCPeerConnection.prototype[method] = function() {
- var pc = 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(pc, [resolve, reject, opts]);
- });
- }
- return nativeMethod.apply(this, arguments);
- };
- });
- }
-
- // shim implicit creation of RTCSessionDescription/RTCIceCandidate
- ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate']
- .forEach(function(method) {
- var nativeMethod = window.RTCPeerConnection.prototype[method];
- window.RTCPeerConnection.prototype[method] = function() {
- arguments[0] = new ((method === 'addIceCandidate') ?
- window.RTCIceCandidate :
- window.RTCSessionDescription)(arguments[0]);
- return nativeMethod.apply(this, arguments);
- };
- });
-
- // support for addIceCandidate(null or undefined)
- var nativeAddIceCandidate =
- window.RTCPeerConnection.prototype.addIceCandidate;
- window.RTCPeerConnection.prototype.addIceCandidate = function() {
- if (!arguments[0]) {
- if (arguments[1]) {
- arguments[1].apply(null);
- }
- return Promise.resolve();
- }
- return nativeAddIceCandidate.apply(this, arguments);
- };
- }
-};
-
-},{"../utils.js":13,"./getusermedia":6}],6:[function(require,module,exports){
-/*
- * Copyright (c) 2016 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.
- */
- /* eslint-env node */
-'use strict';
-var utils = require('../utils.js');
-var logging = utils.log;
-
-// Expose public methods.
-module.exports = function(window) {
- var browserDetails = utils.detectBrowser(window);
- var navigator = window && window.navigator;
-
- 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;
- };
-
- var shimConstraints_ = function(constraints, func) {
- if (browserDetails.version >= 61) {
- return func(constraints);
- }
- constraints = JSON.parse(JSON.stringify(constraints));
- if (constraints && typeof constraints.audio === 'object') {
- var remap = function(obj, a, b) {
- if (a in obj && !(b in obj)) {
- obj[b] = obj[a];
- delete obj[a];
- }
- };
- constraints = JSON.parse(JSON.stringify(constraints));
- remap(constraints.audio, 'autoGainControl', 'googAutoGainControl');
- remap(constraints.audio, 'noiseSuppression', 'googNoiseSuppression');
- constraints.audio = constraintsToChrome_(constraints.audio);
- }
- if (constraints && typeof constraints.video === 'object') {
- // Shim facingMode for mobile & surface pro.
- var face = constraints.video.facingMode;
- face = face && ((typeof face === 'object') ? face : {ideal: face});
- var getSupportedFacingModeLies = browserDetails.version < 66;
-
- if ((face && (face.exact === 'user' || face.exact === 'environment' ||
- face.ideal === 'user' || face.ideal === 'environment')) &&
- !(navigator.mediaDevices.getSupportedConstraints &&
- navigator.mediaDevices.getSupportedConstraints().facingMode &&
- !getSupportedFacingModeLies)) {
- delete constraints.video.facingMode;
- var matches;
- if (face.exact === 'environment' || face.ideal === 'environment') {
- matches = ['back', 'rear'];
- } else if (face.exact === 'user' || face.ideal === 'user') {
- matches = ['front'];
- }
- if (matches) {
- // Look for matches in label, or use last cam for back (typical).
- return navigator.mediaDevices.enumerateDevices()
- .then(function(devices) {
- devices = devices.filter(function(d) {
- return d.kind === 'videoinput';
- });
- var dev = devices.find(function(d) {
- return matches.some(function(match) {
- return d.label.toLowerCase().indexOf(match) !== -1;
- });
- });
- if (!dev && devices.length && matches.indexOf('back') !== -1) {
- dev = devices[devices.length - 1]; // more likely the back cam
- }
- if (dev) {
- constraints.video.deviceId = face.exact ? {exact: dev.deviceId} :
- {ideal: dev.deviceId};
- }
- constraints.video = constraintsToChrome_(constraints.video);
- logging('chrome: ' + JSON.stringify(constraints));
- return func(constraints);
- });
- }
- }
- constraints.video = constraintsToChrome_(constraints.video);
- }
- logging('chrome: ' + JSON.stringify(constraints));
- return func(constraints);
- };
-
- var shimError_ = function(e) {
- return {
- name: {
- PermissionDeniedError: 'NotAllowedError',
- InvalidStateError: 'NotReadableError',
- DevicesNotFoundError: 'NotFoundError',
- ConstraintNotSatisfiedError: 'OverconstrainedError',
- TrackStartError: 'NotReadableError',
- MediaDeviceFailedDueToShutdown: 'NotReadableError',
- MediaDeviceKillSwitchOn: 'NotReadableError'
- }[e.name] || e.name,
- message: e.message,
- constraint: e.constraintName,
- toString: function() {
- return this.name + (this.message && ': ') + this.message;
- }
- };
- };
-
- var getUserMedia_ = function(constraints, onSuccess, onError) {
- shimConstraints_(constraints, function(c) {
- navigator.webkitGetUserMedia(c, onSuccess, function(e) {
- if (onError) {
- onError(shimError_(e));
- }
- });
- });
- };
-
- navigator.getUserMedia = getUserMedia_;
-
- // Returns the result of getUserMedia as a Promise.
- var getUserMediaPromise_ = function(constraints) {
- return new Promise(function(resolve, reject) {
- navigator.getUserMedia(constraints, resolve, reject);
- });
- };
-
- if (!navigator.mediaDevices) {
- navigator.mediaDevices = {
- getUserMedia: getUserMediaPromise_,
- enumerateDevices: function() {
- return new Promise(function(resolve) {
- var kinds = {audio: 'audioinput', video: 'videoinput'};
- return window.MediaStreamTrack.getSources(function(devices) {
- resolve(devices.map(function(device) {
- return {label: device.label,
- kind: kinds[device.kind],
- deviceId: device.id,
- groupId: ''};
- }));
- });
- });
- },
- getSupportedConstraints: function() {
- return {
- deviceId: true, echoCancellation: true, facingMode: true,
- frameRate: true, height: true, width: true
- };
- }
- };
- }
-
- // 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 getUserMediaPromise_(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(cs) {
- return shimConstraints_(cs, function(c) {
- return origGetUserMedia(c).then(function(stream) {
- if (c.audio && !stream.getAudioTracks().length ||
- c.video && !stream.getVideoTracks().length) {
- stream.getTracks().forEach(function(track) {
- track.stop();
- });
- throw new DOMException('', 'NotFoundError');
- }
- return stream;
- }, function(e) {
- return Promise.reject(shimError_(e));
- });
- });
- };
- }
-
- // Dummy devicechange event methods.
- // TODO(KaptenJansson) remove once implemented in Chrome stable.
- if (typeof navigator.mediaDevices.addEventListener === 'undefined') {
- navigator.mediaDevices.addEventListener = function() {
- logging('Dummy mediaDevices.addEventListener called.');
- };
- }
- if (typeof navigator.mediaDevices.removeEventListener === 'undefined') {
- navigator.mediaDevices.removeEventListener = function() {
- logging('Dummy mediaDevices.removeEventListener called.');
- };
- }
-};
-
-},{"../utils.js":13}],7:[function(require,module,exports){
-/*
- * Copyright (c) 2017 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.
- */
- /* eslint-env node */
-'use strict';
-
-var SDPUtils = require('sdp');
-var utils = require('./utils');
-
-module.exports = {
- shimRTCIceCandidate: function(window) {
- // foundation is arbitrarily chosen as an indicator for full support for
- // https://w3c.github.io/webrtc-pc/#rtcicecandidate-interface
- if (window.RTCIceCandidate && 'foundation' in
- window.RTCIceCandidate.prototype) {
- return;
- }
-
- var NativeRTCIceCandidate = window.RTCIceCandidate;
- window.RTCIceCandidate = function(args) {
- // Remove the a= which shouldn't be part of the candidate string.
- if (typeof args === 'object' && args.candidate &&
- args.candidate.indexOf('a=') === 0) {
- args = JSON.parse(JSON.stringify(args));
- args.candidate = args.candidate.substr(2);
- }
-
- // Augment the native candidate with the parsed fields.
- var nativeCandidate = new NativeRTCIceCandidate(args);
- var parsedCandidate = SDPUtils.parseCandidate(args.candidate);
- var augmentedCandidate = Object.assign(nativeCandidate,
- parsedCandidate);
-
- // Add a serializer that does not serialize the extra attributes.
- augmentedCandidate.toJSON = function() {
- return {
- candidate: augmentedCandidate.candidate,
- sdpMid: augmentedCandidate.sdpMid,
- sdpMLineIndex: augmentedCandidate.sdpMLineIndex,
- usernameFragment: augmentedCandidate.usernameFragment,
- };
- };
- return augmentedCandidate;
- };
-
- // Hook up the augmented candidate in onicecandidate and
- // addEventListener('icecandidate', ...)
- utils.wrapPeerConnectionEvent(window, 'icecandidate', function(e) {
- if (e.candidate) {
- Object.defineProperty(e, 'candidate', {
- value: new window.RTCIceCandidate(e.candidate),
- writable: 'false'
- });
- }
- return e;
- });
- },
-
- // shimCreateObjectURL must be called before shimSourceObject to avoid loop.
-
- shimCreateObjectURL: function(window) {
- var URL = window && window.URL;
-
- if (!(typeof window === 'object' && window.HTMLMediaElement &&
- 'srcObject' in window.HTMLMediaElement.prototype &&
- URL.createObjectURL && URL.revokeObjectURL)) {
- // Only shim CreateObjectURL using srcObject if srcObject exists.
- return undefined;
- }
-
- var nativeCreateObjectURL = URL.createObjectURL.bind(URL);
- var nativeRevokeObjectURL = URL.revokeObjectURL.bind(URL);
- var streams = new Map(), newId = 0;
-
- URL.createObjectURL = function(stream) {
- if ('getTracks' in stream) {
- var url = 'polyblob:' + (++newId);
- streams.set(url, stream);
- utils.deprecated('URL.createObjectURL(stream)',
- 'elem.srcObject = stream');
- return url;
- }
- return nativeCreateObjectURL(stream);
- };
- URL.revokeObjectURL = function(url) {
- nativeRevokeObjectURL(url);
- streams.delete(url);
- };
-
- var dsc = Object.getOwnPropertyDescriptor(window.HTMLMediaElement.prototype,
- 'src');
- Object.defineProperty(window.HTMLMediaElement.prototype, 'src', {
- get: function() {
- return dsc.get.apply(this);
- },
- set: function(url) {
- this.srcObject = streams.get(url) || null;
- return dsc.set.apply(this, [url]);
- }
- });
-
- var nativeSetAttribute = window.HTMLMediaElement.prototype.setAttribute;
- window.HTMLMediaElement.prototype.setAttribute = function() {
- if (arguments.length === 2 &&
- ('' + arguments[0]).toLowerCase() === 'src') {
- this.srcObject = streams.get(arguments[1]) || null;
- }
- return nativeSetAttribute.apply(this, arguments);
- };
- },
-
- shimMaxMessageSize: function(window) {
- if (window.RTCSctpTransport || !window.RTCPeerConnection) {
- return;
- }
- var browserDetails = utils.detectBrowser(window);
-
- if (!('sctp' in window.RTCPeerConnection.prototype)) {
- Object.defineProperty(window.RTCPeerConnection.prototype, 'sctp', {
- get: function() {
- return typeof this._sctp === 'undefined' ? null : this._sctp;
- }
- });
- }
-
- var sctpInDescription = function(description) {
- var sections = SDPUtils.splitSections(description.sdp);
- sections.shift();
- return sections.some(function(mediaSection) {
- var mLine = SDPUtils.parseMLine(mediaSection);
- return mLine && mLine.kind === 'application'
- && mLine.protocol.indexOf('SCTP') !== -1;
- });
- };
-
- var getRemoteFirefoxVersion = function(description) {
- // TODO: Is there a better solution for detecting Firefox?
- var match = description.sdp.match(/mozilla...THIS_IS_SDPARTA-(\d+)/);
- if (match === null || match.length < 2) {
- return -1;
- }
- var version = parseInt(match[1], 10);
- // Test for NaN (yes, this is ugly)
- return version !== version ? -1 : version;
- };
-
- var getCanSendMaxMessageSize = function(remoteIsFirefox) {
- // Every implementation we know can send at least 64 KiB.
- // Note: Although Chrome is technically able to send up to 256 KiB, the
- // data does not reach the other peer reliably.
- // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=8419
- var canSendMaxMessageSize = 65536;
- if (browserDetails.browser === 'firefox') {
- if (browserDetails.version < 57) {
- if (remoteIsFirefox === -1) {
- // FF < 57 will send in 16 KiB chunks using the deprecated PPID
- // fragmentation.
- canSendMaxMessageSize = 16384;
- } else {
- // However, other FF (and RAWRTC) can reassemble PPID-fragmented
- // messages. Thus, supporting ~2 GiB when sending.
- canSendMaxMessageSize = 2147483637;
- }
- } else {
- // Currently, all FF >= 57 will reset the remote maximum message size
- // to the default value when a data channel is created at a later
- // stage. :(
- // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1426831
- canSendMaxMessageSize =
- browserDetails.version === 57 ? 65535 : 65536;
- }
- }
- return canSendMaxMessageSize;
- };
-
- var getMaxMessageSize = function(description, remoteIsFirefox) {
- // Note: 65536 bytes is the default value from the SDP spec. Also,
- // every implementation we know supports receiving 65536 bytes.
- var maxMessageSize = 65536;
-
- // FF 57 has a slightly incorrect default remote max message size, so
- // we need to adjust it here to avoid a failure when sending.
- // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1425697
- if (browserDetails.browser === 'firefox'
- && browserDetails.version === 57) {
- maxMessageSize = 65535;
- }
-
- var match = SDPUtils.matchPrefix(description.sdp, 'a=max-message-size:');
- if (match.length > 0) {
- maxMessageSize = parseInt(match[0].substr(19), 10);
- } else if (browserDetails.browser === 'firefox' &&
- remoteIsFirefox !== -1) {
- // If the maximum message size is not present in the remote SDP and
- // both local and remote are Firefox, the remote peer can receive
- // ~2 GiB.
- maxMessageSize = 2147483637;
- }
- return maxMessageSize;
- };
-
- var origSetRemoteDescription =
- window.RTCPeerConnection.prototype.setRemoteDescription;
- window.RTCPeerConnection.prototype.setRemoteDescription = function() {
- var pc = this;
- pc._sctp = null;
-
- if (sctpInDescription(arguments[0])) {
- // Check if the remote is FF.
- var isFirefox = getRemoteFirefoxVersion(arguments[0]);
-
- // Get the maximum message size the local peer is capable of sending
- var canSendMMS = getCanSendMaxMessageSize(isFirefox);
-
- // Get the maximum message size of the remote peer.
- var remoteMMS = getMaxMessageSize(arguments[0], isFirefox);
-
- // Determine final maximum message size
- var maxMessageSize;
- if (canSendMMS === 0 && remoteMMS === 0) {
- maxMessageSize = Number.POSITIVE_INFINITY;
- } else if (canSendMMS === 0 || remoteMMS === 0) {
- maxMessageSize = Math.max(canSendMMS, remoteMMS);
- } else {
- maxMessageSize = Math.min(canSendMMS, remoteMMS);
- }
-
- // Create a dummy RTCSctpTransport object and the 'maxMessageSize'
- // attribute.
- var sctp = {};
- Object.defineProperty(sctp, 'maxMessageSize', {
- get: function() {
- return maxMessageSize;
- }
- });
- pc._sctp = sctp;
- }
-
- return origSetRemoteDescription.apply(pc, arguments);
- };
- },
-
- shimSendThrowTypeError: function(window) {
- // Note: Although Firefox >= 57 has a native implementation, the maximum
- // message size can be reset for all data channels at a later stage.
- // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1426831
-
- var origCreateDataChannel =
- window.RTCPeerConnection.prototype.createDataChannel;
- window.RTCPeerConnection.prototype.createDataChannel = function() {
- var pc = this;
- var dataChannel = origCreateDataChannel.apply(pc, arguments);
- var origDataChannelSend = dataChannel.send;
-
- // Patch 'send' method
- dataChannel.send = function() {
- var dc = this;
- var data = arguments[0];
- var length = data.length || data.size || data.byteLength;
- if (length > pc.sctp.maxMessageSize) {
- throw new DOMException('Message too large (can send a maximum of ' +
- pc.sctp.maxMessageSize + ' bytes)', 'TypeError');
- }
- return origDataChannelSend.apply(dc, arguments);
- };
-
- return dataChannel;
- };
- }
-};
-
-},{"./utils":13,"sdp":2}],8:[function(require,module,exports){
-/*
- * Copyright (c) 2016 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.
- */
- /* eslint-env node */
-'use strict';
-
-var utils = require('../utils');
-var shimRTCPeerConnection = require('rtcpeerconnection-shim');
-
-module.exports = {
- shimGetUserMedia: require('./getusermedia'),
- shimPeerConnection: function(window) {
- var browserDetails = utils.detectBrowser(window);
-
- if (window.RTCIceGatherer) {
- // ORTC defines an RTCIceCandidate object but no constructor.
- // Not implemented in Edge.
- if (!window.RTCIceCandidate) {
- window.RTCIceCandidate = function(args) {
- return args;
- };
- }
- // ORTC does not have a session description object but
- // other browsers (i.e. Chrome) that will support both PC and ORTC
- // in the future might have this defined already.
- if (!window.RTCSessionDescription) {
- window.RTCSessionDescription = function(args) {
- return args;
- };
- }
- // this adds an additional event listener to MediaStrackTrack that signals
- // when a tracks enabled property was changed. Workaround for a bug in
- // addStream, see below. No longer required in 15025+
- if (browserDetails.version < 15025) {
- var origMSTEnabled = Object.getOwnPropertyDescriptor(
- window.MediaStreamTrack.prototype, 'enabled');
- Object.defineProperty(window.MediaStreamTrack.prototype, 'enabled', {
- set: function(value) {
- origMSTEnabled.set.call(this, value);
- var ev = new Event('enabled');
- ev.enabled = value;
- this.dispatchEvent(ev);
- }
- });
- }
- }
-
- // ORTC defines the DTMF sender a bit different.
- // https://github.com/w3c/ortc/issues/714
- if (window.RTCRtpSender && !('dtmf' in window.RTCRtpSender.prototype)) {
- Object.defineProperty(window.RTCRtpSender.prototype, 'dtmf', {
- get: function() {
- if (this._dtmf === undefined) {
- if (this.track.kind === 'audio') {
- this._dtmf = new window.RTCDtmfSender(this);
- } else if (this.track.kind === 'video') {
- this._dtmf = null;
- }
- }
- return this._dtmf;
- }
- });
- }
-
- window.RTCPeerConnection =
- shimRTCPeerConnection(window, browserDetails.version);
- },
- shimReplaceTrack: function(window) {
- // ORTC has replaceTrack -- https://github.com/w3c/ortc/issues/614
- if (window.RTCRtpSender &&
- !('replaceTrack' in window.RTCRtpSender.prototype)) {
- window.RTCRtpSender.prototype.replaceTrack =
- window.RTCRtpSender.prototype.setTrack;
- }
- }
-};
-
-},{"../utils":13,"./getusermedia":9,"rtcpeerconnection-shim":1}],9:[function(require,module,exports){
-/*
- * Copyright (c) 2016 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.
- */
- /* eslint-env node */
-'use strict';
-
-// Expose public methods.
-module.exports = function(window) {
- var navigator = window && window.navigator;
-
- var shimError_ = function(e) {
- return {
- name: {PermissionDeniedError: 'NotAllowedError'}[e.name] || e.name,
- message: e.message,
- constraint: e.constraint,
- toString: function() {
- return this.name;
- }
- };
- };
-
- // getUserMedia error shim.
- var origGetUserMedia = navigator.mediaDevices.getUserMedia.
- bind(navigator.mediaDevices);
- navigator.mediaDevices.getUserMedia = function(c) {
- return origGetUserMedia(c).catch(function(e) {
- return Promise.reject(shimError_(e));
- });
- };
-};
-
-},{}],10:[function(require,module,exports){
-/*
- * Copyright (c) 2016 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.
- */
- /* eslint-env node */
-'use strict';
-
-var utils = require('../utils');
-
-module.exports = {
- shimGetUserMedia: require('./getusermedia'),
- shimOnTrack: function(window) {
- if (typeof window === 'object' && window.RTCPeerConnection && !('ontrack' in
- window.RTCPeerConnection.prototype)) {
- Object.defineProperty(window.RTCPeerConnection.prototype, 'ontrack', {
- get: function() {
- return this._ontrack;
- },
- set: function(f) {
- if (this._ontrack) {
- this.removeEventListener('track', this._ontrack);
- this.removeEventListener('addstream', this._ontrackpoly);
- }
- this.addEventListener('track', this._ontrack = f);
- this.addEventListener('addstream', this._ontrackpoly = function(e) {
- e.stream.getTracks().forEach(function(track) {
- var event = new Event('track');
- event.track = track;
- event.receiver = {track: track};
- event.transceiver = {receiver: event.receiver};
- event.streams = [e.stream];
- this.dispatchEvent(event);
- }.bind(this));
- }.bind(this));
- }
- });
- }
- if (typeof window === 'object' && window.RTCTrackEvent &&
- ('receiver' in window.RTCTrackEvent.prototype) &&
- !('transceiver' in window.RTCTrackEvent.prototype)) {
- Object.defineProperty(window.RTCTrackEvent.prototype, 'transceiver', {
- get: function() {
- return {receiver: this.receiver};
- }
- });
- }
- },
-
- shimSourceObject: function(window) {
- // Firefox has supported mozSrcObject since FF22, unprefixed in 42.
- 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() {
- return this.mozSrcObject;
- },
- set: function(stream) {
- this.mozSrcObject = stream;
- }
- });
- }
- }
- },
-
- shimPeerConnection: function(window) {
- var browserDetails = utils.detectBrowser(window);
-
- if (typeof window !== 'object' || !(window.RTCPeerConnection ||
- window.mozRTCPeerConnection)) {
- return; // probably media.peerconnection.enabled=false in about:config
- }
- // The RTCPeerConnection object.
- if (!window.RTCPeerConnection) {
- window.RTCPeerConnection = function(pcConfig, pcConstraints) {
- if (browserDetails.version < 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 window.mozRTCPeerConnection(pcConfig, pcConstraints);
- };
- window.RTCPeerConnection.prototype =
- window.mozRTCPeerConnection.prototype;
-
- // wrap static methods. Currently just generateCertificate.
- if (window.mozRTCPeerConnection.generateCertificate) {
- Object.defineProperty(window.RTCPeerConnection, 'generateCertificate', {
- get: function() {
- return window.mozRTCPeerConnection.generateCertificate;
- }
- });
- }
-
- window.RTCSessionDescription = window.mozRTCSessionDescription;
- window.RTCIceCandidate = window.mozRTCIceCandidate;
- }
-
- // shim away need for obsolete RTCIceCandidate/RTCSessionDescription.
- ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate']
- .forEach(function(method) {
- var nativeMethod = window.RTCPeerConnection.prototype[method];
- window.RTCPeerConnection.prototype[method] = function() {
- arguments[0] = new ((method === 'addIceCandidate') ?
- window.RTCIceCandidate :
- window.RTCSessionDescription)(arguments[0]);
- return nativeMethod.apply(this, arguments);
- };
- });
-
- // support for addIceCandidate(null or undefined)
- var nativeAddIceCandidate =
- window.RTCPeerConnection.prototype.addIceCandidate;
- window.RTCPeerConnection.prototype.addIceCandidate = function() {
- if (!arguments[0]) {
- if (arguments[1]) {
- arguments[1].apply(null);
- }
- return Promise.resolve();
- }
- return nativeAddIceCandidate.apply(this, arguments);
- };
-
- // shim getStats with maplike support
- var makeMapStats = function(stats) {
- var map = new Map();
- Object.keys(stats).forEach(function(key) {
- map.set(key, stats[key]);
- map[key] = stats[key];
- });
- return map;
- };
-
- var modernStatsTypes = {
- inboundrtp: 'inbound-rtp',
- outboundrtp: 'outbound-rtp',
- candidatepair: 'candidate-pair',
- localcandidate: 'local-candidate',
- remotecandidate: 'remote-candidate'
- };
-
- var nativeGetStats = window.RTCPeerConnection.prototype.getStats;
- window.RTCPeerConnection.prototype.getStats = function(
- selector,
- onSucc,
- onErr
- ) {
- return nativeGetStats.apply(this, [selector || null])
- .then(function(stats) {
- if (browserDetails.version < 48) {
- stats = makeMapStats(stats);
- }
- if (browserDetails.version < 53 && !onSucc) {
- // Shim only promise getStats with spec-hyphens in type names
- // Leave callback version alone; misc old uses of forEach before Map
- try {
- stats.forEach(function(stat) {
- stat.type = modernStatsTypes[stat.type] || stat.type;
- });
- } catch (e) {
- if (e.name !== 'TypeError') {
- throw e;
- }
- // Avoid TypeError: "type" is read-only, in old versions. 34-43ish
- stats.forEach(function(stat, i) {
- stats.set(i, Object.assign({}, stat, {
- type: modernStatsTypes[stat.type] || stat.type
- }));
- });
- }
- }
- return stats;
- })
- .then(onSucc, onErr);
- };
- },
-
- shimRemoveStream: function(window) {
- if (!window.RTCPeerConnection ||
- 'removeStream' in window.RTCPeerConnection.prototype) {
- return;
- }
- window.RTCPeerConnection.prototype.removeStream = function(stream) {
- var pc = this;
- utils.deprecated('removeStream', 'removeTrack');
- this.getSenders().forEach(function(sender) {
- if (sender.track && stream.getTracks().indexOf(sender.track) !== -1) {
- pc.removeTrack(sender);
- }
- });
- };
- }
-};
-
-},{"../utils":13,"./getusermedia":11}],11:[function(require,module,exports){
-/*
- * Copyright (c) 2016 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.
- */
- /* eslint-env node */
-'use strict';
-
-var utils = require('../utils');
-var logging = utils.log;
-
-// Expose public methods.
-module.exports = function(window) {
- var browserDetails = utils.detectBrowser(window);
- var navigator = window && window.navigator;
- var MediaStreamTrack = window && window.MediaStreamTrack;
-
- var shimError_ = function(e) {
- return {
- name: {
- InternalError: 'NotReadableError',
- NotSupportedError: 'TypeError',
- PermissionDeniedError: 'NotAllowedError',
- SecurityError: 'NotAllowedError'
- }[e.name] || e.name,
- message: {
- 'The operation is insecure.': 'The request is not allowed by the ' +
- 'user agent or the platform in the current context.'
- }[e.message] || e.message,
- constraint: e.constraint,
- toString: function() {
- return this.name + (this.message && ': ') + this.message;
- }
- };
- };
-
- // getUserMedia constraints shim.
- var 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;
- };
- constraints = JSON.parse(JSON.stringify(constraints));
- if (browserDetails.version < 38) {
- logging('spec: ' + JSON.stringify(constraints));
- if (constraints.audio) {
- constraints.audio = constraintsToFF37_(constraints.audio);
- }
- if (constraints.video) {
- constraints.video = constraintsToFF37_(constraints.video);
- }
- logging('ff37: ' + JSON.stringify(constraints));
- }
- return navigator.mozGetUserMedia(constraints, onSuccess, function(e) {
- onError(shimError_(e));
- });
- };
-
- // Returns the result of getUserMedia as a Promise.
- var getUserMediaPromise_ = function(constraints) {
- return new Promise(function(resolve, reject) {
- getUserMedia_(constraints, resolve, reject);
- });
- };
-
- // Shim for mediaDevices on older versions.
- if (!navigator.mediaDevices) {
- navigator.mediaDevices = {getUserMedia: getUserMediaPromise_,
- 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 (browserDetails.version < 41) {
- // Work around http://bugzil.la/1169665
- var orgEnumerateDevices =
- navigator.mediaDevices.enumerateDevices.bind(navigator.mediaDevices);
- navigator.mediaDevices.enumerateDevices = function() {
- return orgEnumerateDevices().then(undefined, function(e) {
- if (e.name === 'NotFoundError') {
- return [];
- }
- throw e;
- });
- };
- }
- if (browserDetails.version < 49) {
- var origGetUserMedia = navigator.mediaDevices.getUserMedia.
- bind(navigator.mediaDevices);
- navigator.mediaDevices.getUserMedia = function(c) {
- return origGetUserMedia(c).then(function(stream) {
- // Work around https://bugzil.la/802326
- if (c.audio && !stream.getAudioTracks().length ||
- c.video && !stream.getVideoTracks().length) {
- stream.getTracks().forEach(function(track) {
- track.stop();
- });
- throw new DOMException('The object can not be found here.',
- 'NotFoundError');
- }
- return stream;
- }, function(e) {
- return Promise.reject(shimError_(e));
- });
- };
- }
- if (!(browserDetails.version > 55 &&
- 'autoGainControl' in navigator.mediaDevices.getSupportedConstraints())) {
- var remap = function(obj, a, b) {
- if (a in obj && !(b in obj)) {
- obj[b] = obj[a];
- delete obj[a];
- }
- };
-
- var nativeGetUserMedia = navigator.mediaDevices.getUserMedia.
- bind(navigator.mediaDevices);
- navigator.mediaDevices.getUserMedia = function(c) {
- if (typeof c === 'object' && typeof c.audio === 'object') {
- c = JSON.parse(JSON.stringify(c));
- remap(c.audio, 'autoGainControl', 'mozAutoGainControl');
- remap(c.audio, 'noiseSuppression', 'mozNoiseSuppression');
- }
- return nativeGetUserMedia(c);
- };
-
- if (MediaStreamTrack && MediaStreamTrack.prototype.getSettings) {
- var nativeGetSettings = MediaStreamTrack.prototype.getSettings;
- MediaStreamTrack.prototype.getSettings = function() {
- var obj = nativeGetSettings.apply(this, arguments);
- remap(obj, 'mozAutoGainControl', 'autoGainControl');
- remap(obj, 'mozNoiseSuppression', 'noiseSuppression');
- return obj;
- };
- }
-
- if (MediaStreamTrack && MediaStreamTrack.prototype.applyConstraints) {
- var nativeApplyConstraints = MediaStreamTrack.prototype.applyConstraints;
- MediaStreamTrack.prototype.applyConstraints = function(c) {
- if (this.kind === 'audio' && typeof c === 'object') {
- c = JSON.parse(JSON.stringify(c));
- remap(c, 'autoGainControl', 'mozAutoGainControl');
- remap(c, 'noiseSuppression', 'mozNoiseSuppression');
- }
- return nativeApplyConstraints.apply(this, [c]);
- };
- }
- }
- navigator.getUserMedia = function(constraints, onSuccess, onError) {
- if (browserDetails.version < 44) {
- return getUserMedia_(constraints, onSuccess, onError);
- }
- // Replace Firefox 44+'s deprecation warning with unprefixed version.
- utils.deprecated('navigator.getUserMedia',
- 'navigator.mediaDevices.getUserMedia');
- navigator.mediaDevices.getUserMedia(constraints).then(onSuccess, onError);
- };
-};
-
-},{"../utils":13}],12:[function(require,module,exports){
-/*
- * Copyright (c) 2016 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.
- */
-'use strict';
-var utils = require('../utils');
-
-module.exports = {
- shimLocalStreamsAPI: function(window) {
- if (typeof window !== 'object' || !window.RTCPeerConnection) {
- return;
- }
- if (!('getLocalStreams' in window.RTCPeerConnection.prototype)) {
- window.RTCPeerConnection.prototype.getLocalStreams = function() {
- if (!this._localStreams) {
- this._localStreams = [];
- }
- return this._localStreams;
- };
- }
- if (!('getStreamById' in window.RTCPeerConnection.prototype)) {
- window.RTCPeerConnection.prototype.getStreamById = function(id) {
- var result = null;
- if (this._localStreams) {
- this._localStreams.forEach(function(stream) {
- if (stream.id === id) {
- result = stream;
- }
- });
- }
- if (this._remoteStreams) {
- this._remoteStreams.forEach(function(stream) {
- if (stream.id === id) {
- result = stream;
- }
- });
- }
- return result;
- };
- }
- if (!('addStream' in window.RTCPeerConnection.prototype)) {
- var _addTrack = window.RTCPeerConnection.prototype.addTrack;
- window.RTCPeerConnection.prototype.addStream = function(stream) {
- if (!this._localStreams) {
- this._localStreams = [];
- }
- if (this._localStreams.indexOf(stream) === -1) {
- this._localStreams.push(stream);
- }
- var pc = this;
- stream.getTracks().forEach(function(track) {
- _addTrack.call(pc, track, stream);
- });
- };
-
- window.RTCPeerConnection.prototype.addTrack = function(track, stream) {
- if (stream) {
- if (!this._localStreams) {
- this._localStreams = [stream];
- } else if (this._localStreams.indexOf(stream) === -1) {
- this._localStreams.push(stream);
- }
- }
- return _addTrack.call(this, track, stream);
- };
- }
- if (!('removeStream' in window.RTCPeerConnection.prototype)) {
- window.RTCPeerConnection.prototype.removeStream = function(stream) {
- if (!this._localStreams) {
- this._localStreams = [];
- }
- var index = this._localStreams.indexOf(stream);
- if (index === -1) {
- return;
- }
- this._localStreams.splice(index, 1);
- var pc = this;
- var tracks = stream.getTracks();
- this.getSenders().forEach(function(sender) {
- if (tracks.indexOf(sender.track) !== -1) {
- pc.removeTrack(sender);
- }
- });
- };
- }
- },
- shimRemoteStreamsAPI: function(window) {
- if (typeof window !== 'object' || !window.RTCPeerConnection) {
- return;
- }
- if (!('getRemoteStreams' in window.RTCPeerConnection.prototype)) {
- window.RTCPeerConnection.prototype.getRemoteStreams = function() {
- return this._remoteStreams ? this._remoteStreams : [];
- };
- }
- if (!('onaddstream' in window.RTCPeerConnection.prototype)) {
- Object.defineProperty(window.RTCPeerConnection.prototype, 'onaddstream', {
- get: function() {
- return this._onaddstream;
- },
- set: function(f) {
- var pc = this;
- if (this._onaddstream) {
- this.removeEventListener('addstream', this._onaddstream);
- this.removeEventListener('track', this._onaddstreampoly);
- }
- this.addEventListener('addstream', this._onaddstream = f);
- this.addEventListener('track', this._onaddstreampoly = function(e) {
- e.streams.forEach(function(stream) {
- if (!pc._remoteStreams) {
- pc._remoteStreams = [];
- }
- if (pc._remoteStreams.indexOf(stream) >= 0) {
- return;
- }
- pc._remoteStreams.push(stream);
- var event = new Event('addstream');
- event.stream = stream;
- pc.dispatchEvent(event);
- });
- });
- }
- });
- }
- },
- shimCallbacksAPI: function(window) {
- if (typeof window !== 'object' || !window.RTCPeerConnection) {
- return;
- }
- var prototype = window.RTCPeerConnection.prototype;
- var createOffer = prototype.createOffer;
- var createAnswer = prototype.createAnswer;
- var setLocalDescription = prototype.setLocalDescription;
- var setRemoteDescription = prototype.setRemoteDescription;
- var addIceCandidate = prototype.addIceCandidate;
-
- prototype.createOffer = function(successCallback, failureCallback) {
- var options = (arguments.length >= 2) ? arguments[2] : arguments[0];
- var promise = createOffer.apply(this, [options]);
- if (!failureCallback) {
- return promise;
- }
- promise.then(successCallback, failureCallback);
- return Promise.resolve();
- };
-
- prototype.createAnswer = function(successCallback, failureCallback) {
- var options = (arguments.length >= 2) ? arguments[2] : arguments[0];
- var promise = createAnswer.apply(this, [options]);
- if (!failureCallback) {
- return promise;
- }
- promise.then(successCallback, failureCallback);
- return Promise.resolve();
- };
-
- var withCallback = function(description, successCallback, failureCallback) {
- var promise = setLocalDescription.apply(this, [description]);
- if (!failureCallback) {
- return promise;
- }
- promise.then(successCallback, failureCallback);
- return Promise.resolve();
- };
- prototype.setLocalDescription = withCallback;
-
- withCallback = function(description, successCallback, failureCallback) {
- var promise = setRemoteDescription.apply(this, [description]);
- if (!failureCallback) {
- return promise;
- }
- promise.then(successCallback, failureCallback);
- return Promise.resolve();
- };
- prototype.setRemoteDescription = withCallback;
-
- withCallback = function(candidate, successCallback, failureCallback) {
- var promise = addIceCandidate.apply(this, [candidate]);
- if (!failureCallback) {
- return promise;
- }
- promise.then(successCallback, failureCallback);
- return Promise.resolve();
- };
- prototype.addIceCandidate = withCallback;
- },
- shimGetUserMedia: function(window) {
- var navigator = window && window.navigator;
-
- if (!navigator.getUserMedia) {
- if (navigator.webkitGetUserMedia) {
- navigator.getUserMedia = navigator.webkitGetUserMedia.bind(navigator);
- } else if (navigator.mediaDevices &&
- navigator.mediaDevices.getUserMedia) {
- navigator.getUserMedia = function(constraints, cb, errcb) {
- navigator.mediaDevices.getUserMedia(constraints)
- .then(cb, errcb);
- }.bind(navigator);
- }
- }
- },
- shimRTCIceServerUrls: function(window) {
- // migrate from non-spec RTCIceServer.url to RTCIceServer.urls
- var OrigPeerConnection = window.RTCPeerConnection;
- window.RTCPeerConnection = function(pcConfig, pcConstraints) {
- if (pcConfig && pcConfig.iceServers) {
- var newIceServers = [];
- for (var i = 0; i < pcConfig.iceServers.length; i++) {
- var server = pcConfig.iceServers[i];
- if (!server.hasOwnProperty('urls') &&
- server.hasOwnProperty('url')) {
- utils.deprecated('RTCIceServer.url', 'RTCIceServer.urls');
- server = JSON.parse(JSON.stringify(server));
- server.urls = server.url;
- delete server.url;
- newIceServers.push(server);
- } else {
- newIceServers.push(pcConfig.iceServers[i]);
- }
- }
- pcConfig.iceServers = newIceServers;
- }
- return new OrigPeerConnection(pcConfig, pcConstraints);
- };
- window.RTCPeerConnection.prototype = OrigPeerConnection.prototype;
- // wrap static methods. Currently just generateCertificate.
- if ('generateCertificate' in window.RTCPeerConnection) {
- Object.defineProperty(window.RTCPeerConnection, 'generateCertificate', {
- get: function() {
- return OrigPeerConnection.generateCertificate;
- }
- });
- }
- },
- shimTrackEventTransceiver: function(window) {
- // Add event.transceiver member over deprecated event.receiver
- if (typeof window === 'object' && window.RTCPeerConnection &&
- ('receiver' in window.RTCTrackEvent.prototype) &&
- // can't check 'transceiver' in window.RTCTrackEvent.prototype, as it is
- // defined for some reason even when window.RTCTransceiver is not.
- !window.RTCTransceiver) {
- Object.defineProperty(window.RTCTrackEvent.prototype, 'transceiver', {
- get: function() {
- return {receiver: this.receiver};
- }
- });
- }
- },
-
- shimCreateOfferLegacy: function(window) {
- var origCreateOffer = window.RTCPeerConnection.prototype.createOffer;
- window.RTCPeerConnection.prototype.createOffer = function(offerOptions) {
- var pc = this;
- if (offerOptions) {
- var audioTransceiver = pc.getTransceivers().find(function(transceiver) {
- return transceiver.sender.track &&
- transceiver.sender.track.kind === 'audio';
- });
- if (offerOptions.offerToReceiveAudio === false && audioTransceiver) {
- if (audioTransceiver.direction === 'sendrecv') {
- if (audioTransceiver.setDirection) {
- audioTransceiver.setDirection('sendonly');
- } else {
- audioTransceiver.direction = 'sendonly';
- }
- } else if (audioTransceiver.direction === 'recvonly') {
- if (audioTransceiver.setDirection) {
- audioTransceiver.setDirection('inactive');
- } else {
- audioTransceiver.direction = 'inactive';
- }
- }
- } else if (offerOptions.offerToReceiveAudio === true &&
- !audioTransceiver) {
- pc.addTransceiver('audio');
- }
-
- var videoTransceiver = pc.getTransceivers().find(function(transceiver) {
- return transceiver.sender.track &&
- transceiver.sender.track.kind === 'video';
- });
- if (offerOptions.offerToReceiveVideo === false && videoTransceiver) {
- if (videoTransceiver.direction === 'sendrecv') {
- videoTransceiver.setDirection('sendonly');
- } else if (videoTransceiver.direction === 'recvonly') {
- videoTransceiver.setDirection('inactive');
- }
- } else if (offerOptions.offerToReceiveVideo === true &&
- !videoTransceiver) {
- pc.addTransceiver('video');
- }
- }
- return origCreateOffer.apply(pc, arguments);
- };
- }
-};
-
-},{"../utils":13}],13:[function(require,module,exports){
-/*
- * Copyright (c) 2016 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.
- */
- /* eslint-env node */
-'use strict';
-
-var logDisabled_ = true;
-var deprecationWarnings_ = true;
-
-/**
- * Extract browser version out of the provided user agent string.
- *
- * @param {!string} uastring userAgent string.
- * @param {!string} expr Regular expression used as match criteria.
- * @param {!number} pos position in the version string to be returned.
- * @return {!number} browser version.
- */
-function extractVersion(uastring, expr, pos) {
- var match = uastring.match(expr);
- return match && match.length >= pos && parseInt(match[pos], 10);
-}
-
-// Wraps the peerconnection event eventNameToWrap in a function
-// which returns the modified event object.
-function wrapPeerConnectionEvent(window, eventNameToWrap, wrapper) {
- if (!window.RTCPeerConnection) {
- return;
- }
- var proto = window.RTCPeerConnection.prototype;
- var nativeAddEventListener = proto.addEventListener;
- proto.addEventListener = function(nativeEventName, cb) {
- if (nativeEventName !== eventNameToWrap) {
- return nativeAddEventListener.apply(this, arguments);
- }
- var wrappedCallback = function(e) {
- cb(wrapper(e));
- };
- this._eventMap = this._eventMap || {};
- this._eventMap[cb] = wrappedCallback;
- return nativeAddEventListener.apply(this, [nativeEventName,
- wrappedCallback]);
- };
-
- var nativeRemoveEventListener = proto.removeEventListener;
- proto.removeEventListener = function(nativeEventName, cb) {
- if (nativeEventName !== eventNameToWrap || !this._eventMap
- || !this._eventMap[cb]) {
- return nativeRemoveEventListener.apply(this, arguments);
- }
- var unwrappedCb = this._eventMap[cb];
- delete this._eventMap[cb];
- return nativeRemoveEventListener.apply(this, [nativeEventName,
- unwrappedCb]);
- };
-
- Object.defineProperty(proto, 'on' + eventNameToWrap, {
- get: function() {
- return this['_on' + eventNameToWrap];
- },
- set: function(cb) {
- if (this['_on' + eventNameToWrap]) {
- this.removeEventListener(eventNameToWrap,
- this['_on' + eventNameToWrap]);
- delete this['_on' + eventNameToWrap];
- }
- if (cb) {
- this.addEventListener(eventNameToWrap,
- this['_on' + eventNameToWrap] = cb);
- }
- }
- });
-}
-
-// Utility methods.
-module.exports = {
- extractVersion: extractVersion,
- wrapPeerConnectionEvent: wrapPeerConnectionEvent,
- disableLog: function(bool) {
- if (typeof bool !== 'boolean') {
- return new Error('Argument type: ' + typeof bool +
- '. Please use a boolean.');
- }
- logDisabled_ = bool;
- return (bool) ? 'adapter.js logging disabled' :
- 'adapter.js logging enabled';
- },
-
- /**
- * Disable or enable deprecation warnings
- * @param {!boolean} bool set to true to disable warnings.
- */
- disableWarnings: function(bool) {
- if (typeof bool !== 'boolean') {
- return new Error('Argument type: ' + typeof bool +
- '. Please use a boolean.');
- }
- deprecationWarnings_ = !bool;
- return 'adapter.js deprecation warnings ' + (bool ? 'disabled' : 'enabled');
- },
-
- log: function() {
- if (typeof window === 'object') {
- if (logDisabled_) {
- return;
- }
- if (typeof console !== 'undefined' && typeof console.log === 'function') {
- console.log.apply(console, arguments);
- }
- }
- },
-
- /**
- * Shows a deprecation warning suggesting the modern and spec-compatible API.
- */
- deprecated: function(oldMethod, newMethod) {
- if (!deprecationWarnings_) {
- return;
- }
- console.warn(oldMethod + ' is deprecated, please use ' + newMethod +
- ' instead.');
- },
-
- /**
- * Browser detector.
- *
- * @return {object} result containing browser and version
- * properties.
- */
- detectBrowser: function(window) {
- var navigator = window && window.navigator;
-
- // Returned result object.
- var result = {};
- result.browser = null;
- result.version = null;
-
- // Fail early if it's not a browser
- if (typeof window === 'undefined' || !window.navigator) {
- result.browser = 'Not a browser.';
- return result;
- }
-
- if (navigator.mozGetUserMedia) { // Firefox.
- result.browser = 'firefox';
- result.version = extractVersion(navigator.userAgent,
- /Firefox\/(\d+)\./, 1);
- } else if (navigator.webkitGetUserMedia) {
- // Chrome, Chromium, Webview, Opera.
- // Version matches Chrome/WebRTC version.
- result.browser = 'chrome';
- result.version = extractVersion(navigator.userAgent,
- /Chrom(e|ium)\/(\d+)\./, 2);
- } else if (navigator.mediaDevices &&
- navigator.userAgent.match(/Edge\/(\d+).(\d+)$/)) { // Edge.
- result.browser = 'edge';
- result.version = extractVersion(navigator.userAgent,
- /Edge\/(\d+).(\d+)$/, 2);
- } else if (navigator.mediaDevices &&
- navigator.userAgent.match(/AppleWebKit\/(\d+)\./)) { // Safari.
- result.browser = 'safari';
- result.version = extractVersion(navigator.userAgent,
- /AppleWebKit\/(\d+)\./, 1);
- } else { // Default fallthrough: not supported.
- result.browser = 'Not a supported browser.';
- return result;
- }
-
- return result;
- }
-};
-
-},{}]},{},[3])(3)
-});
\ No newline at end of file
+},{}]},{},[1])(1)
+});
diff --git a/html5/verto/js/src/vendor/media-device-id.min.js b/html5/verto/js/src/vendor/media-device-id.min.js
new file mode 100644
index 0000000000..16df327236
--- /dev/null
+++ b/html5/verto/js/src/vendor/media-device-id.min.js
@@ -0,0 +1 @@
+/* Under MIT License by Mazuh. Original source code at: https://github.com/Mazuh/media-device-id */ !function(t){var r={};function e(n){if(r[n])return r[n].exports;var o=r[n]={i:n,l:!1,exports:{}};return t[n].call(o.exports,o,o.exports,e),o.l=!0,o.exports}e.m=t,e.c=r,e.d=function(t,r,n){e.o(t,r)||Object.defineProperty(t,r,{enumerable:!0,get:n})},e.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},e.t=function(t,r){if(1&r&&(t=e(t)),8&r)return t;if(4&r&&"object"==typeof t&&t&&t.__esModule)return t;var n=Object.create(null);if(e.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:t}),2&r&&"string"!=typeof t)for(var o in t)e.d(n,o,function(r){return t[r]}.bind(null,o));return n},e.n=function(t){var r=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(r,"a",r),r},e.o=function(t,r){return Object.prototype.hasOwnProperty.call(t,r)},e.p="",e(e.s=2)}([function(t,r,e){t.exports=e(3)},function(t,r){function e(t,r,e,n,o,i,a){try{var u=t[i](a),c=u.value}catch(t){return void e(t)}u.done?r(c):Promise.resolve(c).then(n,o)}t.exports=function(t){return function(){var r=this,n=arguments;return new Promise(function(o,i){var a=t.apply(r,n);function u(t){e(a,o,i,u,c,"next",t)}function c(t){e(a,o,i,u,c,"throw",t)}u(void 0)})}}},function(t,r,e){"use strict";e.r(r),e.d(r,"assureMediaInputId",function(){return u});var n=e(0),o=e.n(n),i=e(1),a=e.n(i);function u(t,r,e){return c.apply(this,arguments)}function c(){return(c=a()(o.a.mark(function t(r,e,n){var i,a,u,c,f,s,l,h,p,v,d;return o.a.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:return i=function(t){return t.kind.indexOf("input")>-1},t.next=3,navigator.mediaDevices.enumerateDevices().then(function(t){return{ok:t.filter(i)}}).catch(function(t){return{err:t}});case 3:if(!(a=t.sent).err){t.next=6;break}throw String(a.err);case 6:if(u=a.ok,c=function(t){return t&&t.label},f=u.every(c),s=function(t){return t.label&&t.label==r},l=function(t){return t.deviceId==e},h=function(t){return l(t)},p=u.find(h),v=function(t){return l(t)||s(t)},d=u.find(v),p||f){t.next=19;break}if(void 0===n){t.next=18;break}return t.abrupt("return",n);case 18:throw"Could not assure device, id is wrong and labels are unavailable";case 19:if(p||d){t.next=23;break}if(void 0===n){t.next=22;break}return t.abrupt("return",n);case 22:throw"Could not assure device, not found by label nor id";case 23:return t.abrupt("return",p?p.deviceId:d.deviceId);case 24:case"end":return t.stop()}},t,this)}))).apply(this,arguments)}void 0!==window&&(window.assureMediaInputId=u)},function(t,r,e){var n=function(){return this||"object"==typeof self&&self}()||Function("return this")(),o=n.regeneratorRuntime&&Object.getOwnPropertyNames(n).indexOf("regeneratorRuntime")>=0,i=o&&n.regeneratorRuntime;if(n.regeneratorRuntime=void 0,t.exports=e(4),o)n.regeneratorRuntime=i;else try{delete n.regeneratorRuntime}catch(t){n.regeneratorRuntime=void 0}},function(t,r){!function(r){"use strict";var e,n=Object.prototype,o=n.hasOwnProperty,i="function"==typeof Symbol?Symbol:{},a=i.iterator||"@@iterator",u=i.asyncIterator||"@@asyncIterator",c=i.toStringTag||"@@toStringTag",f="object"==typeof t,s=r.regeneratorRuntime;if(s)f&&(t.exports=s);else{(s=r.regeneratorRuntime=f?t.exports:{}).wrap=b;var l="suspendedStart",h="suspendedYield",p="executing",v="completed",d={},y={};y[a]=function(){return this};var g=Object.getPrototypeOf,m=g&&g(g(F([])));m&&m!==n&&o.call(m,a)&&(y=m);var w=O.prototype=L.prototype=Object.create(y);E.prototype=w.constructor=O,O.constructor=E,O[c]=E.displayName="GeneratorFunction",s.isGeneratorFunction=function(t){var r="function"==typeof t&&t.constructor;return!!r&&(r===E||"GeneratorFunction"===(r.displayName||r.name))},s.mark=function(t){return Object.setPrototypeOf?Object.setPrototypeOf(t,O):(t.__proto__=O,c in t||(t[c]="GeneratorFunction")),t.prototype=Object.create(w),t},s.awrap=function(t){return{__await:t}},j(_.prototype),_.prototype[u]=function(){return this},s.AsyncIterator=_,s.async=function(t,r,e,n){var o=new _(b(t,r,e,n));return s.isGeneratorFunction(r)?o:o.next().then(function(t){return t.done?t.value:o.next()})},j(w),w[c]="Generator",w[a]=function(){return this},w.toString=function(){return"[object Generator]"},s.keys=function(t){var r=[];for(var e in t)r.push(e);return r.reverse(),function e(){for(;r.length;){var n=r.pop();if(n in t)return e.value=n,e.done=!1,e}return e.done=!0,e}},s.values=F,N.prototype={constructor:N,reset:function(t){if(this.prev=0,this.next=0,this.sent=this._sent=e,this.done=!1,this.delegate=null,this.method="next",this.arg=e,this.tryEntries.forEach(I),!t)for(var r in this)"t"===r.charAt(0)&&o.call(this,r)&&!isNaN(+r.slice(1))&&(this[r]=e)},stop:function(){this.done=!0;var t=this.tryEntries[0].completion;if("throw"===t.type)throw t.arg;return this.rval},dispatchException:function(t){if(this.done)throw t;var r=this;function n(n,o){return u.type="throw",u.arg=t,r.next=n,o&&(r.method="next",r.arg=e),!!o}for(var i=this.tryEntries.length-1;i>=0;--i){var a=this.tryEntries[i],u=a.completion;if("root"===a.tryLoc)return n("end");if(a.tryLoc<=this.prev){var c=o.call(a,"catchLoc"),f=o.call(a,"finallyLoc");if(c&&f){if(this.prev=0;--e){var n=this.tryEntries[e];if(n.tryLoc<=this.prev&&o.call(n,"finallyLoc")&&this.prev=0;--r){var e=this.tryEntries[r];if(e.finallyLoc===t)return this.complete(e.completion,e.afterLoc),I(e),d}},catch:function(t){for(var r=this.tryEntries.length-1;r>=0;--r){var e=this.tryEntries[r];if(e.tryLoc===t){var n=e.completion;if("throw"===n.type){var o=n.arg;I(e)}return o}}throw new Error("illegal catch attempt")},delegateYield:function(t,r,n){return this.delegate={iterator:F(t),resultName:r,nextLoc:n},"next"===this.method&&(this.arg=e),d}}}function b(t,r,e,n){var o=r&&r.prototype instanceof L?r:L,i=Object.create(o.prototype),a=new N(n||[]);return i._invoke=function(t,r,e){var n=l;return function(o,i){if(n===p)throw new Error("Generator is already running");if(n===v){if("throw"===o)throw i;return R()}for(e.method=o,e.arg=i;;){var a=e.delegate;if(a){var u=k(a,e);if(u){if(u===d)continue;return u}}if("next"===e.method)e.sent=e._sent=e.arg;else if("throw"===e.method){if(n===l)throw n=v,e.arg;e.dispatchException(e.arg)}else"return"===e.method&&e.abrupt("return",e.arg);n=p;var c=x(t,r,e);if("normal"===c.type){if(n=e.done?v:h,c.arg===d)continue;return{value:c.arg,done:e.done}}"throw"===c.type&&(n=v,e.method="throw",e.arg=c.arg)}}}(t,e,a),i}function x(t,r,e){try{return{type:"normal",arg:t.call(r,e)}}catch(t){return{type:"throw",arg:t}}}function L(){}function E(){}function O(){}function j(t){["next","throw","return"].forEach(function(r){t[r]=function(t){return this._invoke(r,t)}})}function _(t){var r;this._invoke=function(e,n){function i(){return new Promise(function(r,i){!function r(e,n,i,a){var u=x(t[e],t,n);if("throw"!==u.type){var c=u.arg,f=c.value;return f&&"object"==typeof f&&o.call(f,"__await")?Promise.resolve(f.__await).then(function(t){r("next",t,i,a)},function(t){r("throw",t,i,a)}):Promise.resolve(f).then(function(t){c.value=t,i(c)},function(t){return r("throw",t,i,a)})}a(u.arg)}(e,n,r,i)})}return r=r?r.then(i,i):i()}}function k(t,r){var n=t.iterator[r.method];if(n===e){if(r.delegate=null,"throw"===r.method){if(t.iterator.return&&(r.method="return",r.arg=e,k(t,r),"throw"===r.method))return d;r.method="throw",r.arg=new TypeError("The iterator does not provide a 'throw' method")}return d}var o=x(n,t.iterator,r.arg);if("throw"===o.type)return r.method="throw",r.arg=o.arg,r.delegate=null,d;var i=o.arg;return i?i.done?(r[t.resultName]=i.value,r.next=t.nextLoc,"return"!==r.method&&(r.method="next",r.arg=e),r.delegate=null,d):i:(r.method="throw",r.arg=new TypeError("iterator result is not an object"),r.delegate=null,d)}function P(t){var r={tryLoc:t[0]};1 in t&&(r.catchLoc=t[1]),2 in t&&(r.finallyLoc=t[2],r.afterLoc=t[3]),this.tryEntries.push(r)}function I(t){var r=t.completion||{};r.type="normal",delete r.arg,t.completion=r}function N(t){this.tryEntries=[{tryLoc:"root"}],t.forEach(P,this),this.reset(!0)}function F(t){if(t){var r=t[a];if(r)return r.call(t);if("function"==typeof t.next)return t;if(!isNaN(t.length)){var n=-1,i=function r(){for(;++n
- *
- * Version: MPL 1.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Verto HTML5/Javascript Telephony Signaling and Control Protocol Stack for FreeSWITCH
- *
- * The Initial Developer of the Original Code is
- * Anthony Minessale II
- * Portions created by the Initial Developer are Copyright (C)
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Anthony Minessale II
- *
- * jquery.FSRTC.js - WebRTC Glue code
- *
- */
-(function($) {
-
- // Find the line in sdpLines that starts with |prefix|, and, if specified,
- // contains |substr| (case-insensitive search).
- function findLine(sdpLines, prefix, substr) {
- return findLineInRange(sdpLines, 0, -1, prefix, substr);
- }
-
- // Find the line in sdpLines[startLine...endLine - 1] that starts with |prefix|
- // and, if specified, contains |substr| (case-insensitive search).
- function findLineInRange(sdpLines, startLine, endLine, prefix, substr) {
- var realEndLine = (endLine != -1) ? endLine : sdpLines.length;
- for (var i = startLine; i < realEndLine; ++i) {
- if (sdpLines[i].indexOf(prefix) === 0) {
- if (!substr || sdpLines[i].toLowerCase().indexOf(substr.toLowerCase()) !== -1) {
- return i;
- }
- }
- }
- return null;
- }
-
- // Gets the codec payload type from an a=rtpmap:X line.
- function getCodecPayloadType(sdpLine) {
- var pattern = new RegExp('a=rtpmap:(\\d+) \\w+\\/\\d+');
- var result = sdpLine.match(pattern);
- return (result && result.length == 2) ? result[1] : null;
- }
-
- // Returns a new m= line with the specified codec as the first one.
- function setDefaultCodec(mLine, payload) {
- var elements = mLine.split(' ');
- var newLine = [];
- var index = 0;
- for (var i = 0; i < elements.length; i++) {
- if (index === 3) { // Format of media starts from the fourth.
- newLine[index++] = payload; // Put target payload to the first.
- }
- if (elements[i] !== payload) newLine[index++] = elements[i];
- }
- return newLine.join(' ');
- }
-
- $.FSRTC = function(options) {
- this.options = $.extend({
- useVideo: null,
- useStereo: false,
- userData: null,
- localVideo: null,
- screenShare: false,
- useCamera: "any",
- iceServers: false,
- videoParams: {},
- audioParams: {},
- callbacks: {
- onICEComplete: function() {},
- onICE: function() {},
- onOfferSDP: function() {}
- },
- useStream: null,
- }, options);
-
- this.audioEnabled = true;
- this.videoEnabled = true;
-
-
- this.mediaData = {
- SDP: null,
- profile: {},
- candidateList: []
- };
-
- this.constraints = {
- offerToReceiveAudio: this.options.useSpeak === "none" ? false : true,
- offerToReceiveVideo: this.options.useVideo ? true : false,
- };
-
- if (self.options.useVideo) {
- self.options.useVideo.style.display = 'none';
- }
-
- setCompat();
- checkCompat();
- };
-
- $.FSRTC.validRes = [];
-
- $.FSRTC.prototype.useVideo = function(obj, local) {
- var self = this;
-
- if (obj) {
- self.options.useVideo = obj;
- self.options.localVideo = local;
- self.constraints.offerToReceiveVideo = true;
- } else {
- self.options.useVideo = null;
- self.options.localVideo = null;
- self.constraints.offerToReceiveVideo = false;
- }
-
- if (self.options.useVideo) {
- self.options.useVideo.style.display = 'none';
- }
- };
-
- $.FSRTC.prototype.useStereo = function(on) {
- var self = this;
- self.options.useStereo = on;
- };
-
- // Sets Opus in stereo if stereo is enabled, by adding the stereo=1 fmtp param.
- $.FSRTC.prototype.stereoHack = function(sdp) {
- var self = this;
-
- if (!self.options.useStereo) {
- return sdp;
- }
-
- var sdpLines = sdp.split('\r\n');
-
- // Find opus payload.
- var opusIndex = findLine(sdpLines, 'a=rtpmap', 'opus/48000'), opusPayload;
-
- if (!opusIndex) {
- return sdp;
- } else {
- opusPayload = getCodecPayloadType(sdpLines[opusIndex]);
- }
-
- // Find the payload in fmtp line.
- var fmtpLineIndex = findLine(sdpLines, 'a=fmtp:' + opusPayload.toString());
-
- if (fmtpLineIndex === null) {
- // create an fmtp line
- sdpLines[opusIndex] = sdpLines[opusIndex] + '\r\na=fmtp:' + opusPayload.toString() + " stereo=1; sprop-stereo=1"
- } else {
- // Append stereo=1 to fmtp line.
- sdpLines[fmtpLineIndex] = sdpLines[fmtpLineIndex].concat('; stereo=1; sprop-stereo=1');
- }
-
- sdp = sdpLines.join('\r\n');
- return sdp;
- };
-
- function setCompat() {
- }
-
- function checkCompat() {
- return true;
- }
-
- function onStreamError(self, e) {
- console.log('There has been a problem retrieving the streams - did you allow access? Check Device Resolution', e);
- doCallback(self, "onError", e);
- }
-
- function onStreamSuccess(self, stream) {
- console.log("Stream Success");
- doCallback(self, "onStream", stream);
- }
-
- function onRemoteStreamSuccess(self, stream) {
- console.log("Remote Stream Success");
- doCallback(self, "onRemoteStream", stream);
- }
-
- function onICE(self, candidate) {
- self.mediaData.candidate = candidate;
- self.mediaData.candidateList.push(self.mediaData.candidate);
-
- doCallback(self, "onICE");
- }
-
- function doCallback(self, func, arg) {
- if (func in self.options.callbacks) {
- self.options.callbacks[func](self, arg);
- }
- }
-
- function onICEComplete(self, candidate) {
- console.log("ICE Complete");
- doCallback(self, "onICEComplete");
- }
-
- function onChannelError(self, e) {
- console.error("Channel Error", e);
- doCallback(self, "onError", e);
- }
-
- function onICESDP(self, sdp) {
- self.mediaData.SDP = self.stereoHack(sdp.sdp);
- console.log("ICE SDP");
- doCallback(self, "onICESDP");
- }
-
- function onAnswerSDP(self, sdp) {
- self.answer.SDP = self.stereoHack(sdp.sdp);
- console.log("ICE ANSWER SDP");
- doCallback(self, "onAnswerSDP", self.answer.SDP);
- }
-
- function onMessage(self, msg) {
- console.log("Message");
- doCallback(self, "onICESDP", msg);
- }
-
- FSRTCattachMediaStream = function(element, stream) {
- if (typeof element.srcObject !== 'undefined') {
- element.srcObject = stream;
- } else {
- console.error('Error attaching stream to element.');
- }
- }
-
- function onRemoteStream(self, stream) {
- if (self.options.useVideo) {
- self.options.useVideo.style.display = 'block';
-
- // Hacks for Mobile Safari
- var iOS = ['iPad', 'iPhone', 'iPod'].indexOf(navigator.platform) >= 0;
-
- if (iOS) {
- self.options.useVideo.setAttribute("playsinline", true);
- }
- }
-
- var element = self.options.useAudio;
- console.log("REMOTE STREAM", stream, element);
-
- FSRTCattachMediaStream(element, stream);
-
-
-
- //self.options.useAudio.play();
- self.remoteStream = stream;
- onRemoteStreamSuccess(self, stream);
- }
-
- function onOfferSDP(self, sdp) {
- self.mediaData.SDP = self.stereoHack(sdp.sdp);
- console.log("Offer SDP");
- doCallback(self, "onOfferSDP");
- }
-
- $.FSRTC.prototype.answer = function(sdp, onSuccess, onError) {
- this.peer.addAnswerSDP({
- type: "answer",
- sdp: sdp
- },
- onSuccess, onError);
- };
-
- $.FSRTC.prototype.stopPeer = function() {
- if (self.peer) {
- console.log("stopping peer");
- self.peer.stop();
- }
- }
-
- $.FSRTC.prototype.stop = function() {
- var self = this;
-
- if (self.options.useVideo) {
- self.options.useVideo.style.display = 'none';
- self.options.useVideo['src'] = '';
- }
-
- if (self.localStream && !self.options.useStream) {
- if(typeof self.localStream.stop == 'function') {
- self.localStream.stop();
- } else {
- if (self.localStream.active){
- var tracks = self.localStream.getTracks();
- console.log(tracks);
- tracks.forEach(function(track, index){
- console.log(track);
- track.stop();
- })
- }
- }
- self.localStream = null;
- }
-
- if (self.options.localVideo) {
- deactivateLocalVideo(self.options.localVideo);
- }
-
- if (self.options.localVideoStream && !self.options.useStream) {
- if(typeof self.options.localVideoStream.stop == 'function') {
- self.options.localVideoStream.stop();
- } else {
- if (self.options.localVideoStream.active){
- var tracks = self.options.localVideoStream.getTracks();
- console.log(tracks);
- tracks.forEach(function(track, index){
- console.log(track);
- track.stop();
- })
- }
- }
- }
-
- if (self.peer) {
- console.log("stopping peer");
- self.peer.stop();
- }
- };
-
- $.FSRTC.prototype.getMute = function() {
- var self = this;
- return self.audioEnabled;
- }
-
- $.FSRTC.prototype.setMute = function(what) {
- var self = this;
- if (!self.localStream) {
- return false;
- }
- var audioTracks = self.localStream.getAudioTracks();
-
- for (var i = 0, len = audioTracks.length; i < len; i++ ) {
- switch(what) {
- case "on":
- audioTracks[i].enabled = true;
- break;
- case "off":
- audioTracks[i].enabled = false;
- break;
- case "toggle":
- audioTracks[i].enabled = !audioTracks[i].enabled;
- default:
- break;
- }
-
- self.audioEnabled = audioTracks[i].enabled;
- }
-
- return !self.audioEnabled;
- }
-
- $.FSRTC.prototype.getVideoMute = function() {
- var self = this;
- return self.videoEnabled;
- }
-
- $.FSRTC.prototype.setVideoMute = function(what) {
- var self = this;
- if (!self.localStream) {
- return false;
- }
- var videoTracks = self.localStream.getVideoTracks();
-
- for (var i = 0, len = videoTracks.length; i < len; i++ ) {
- switch(what) {
- case "on":
- videoTracks[i].enabled = true;
- break;
- case "off":
- videoTracks[i].enabled = false;
- break;
- case "toggle":
- videoTracks[i].enabled = !videoTracks[i].enabled;
- default:
- break;
- }
-
- self.videoEnabled = videoTracks[i].enabled;
- }
-
- return !self.videoEnabled;
- }
-
- $.FSRTC.prototype.createAnswer = function(params) {
- var self = this;
- self.type = "answer";
- self.remoteSDP = params.sdp;
- console.debug("inbound sdp: ", params.sdp);
-
- function onSuccess(stream) {
- self.localStream = stream;
-
- self.peer = FSRTCPeerConnection({
- type: self.type,
- attachStream: self.localStream,
- onICE: function(candidate) {
- return onICE(self, candidate);
- },
- onICEComplete: function() {
- return onICEComplete(self);
- },
- onRemoteStream: function(stream) {
- return onRemoteStream(self, stream);
- },
- onICESDP: function(sdp) {
- return onICESDP(self, sdp);
- },
- onChannelError: function(e) {
- return onChannelError(self, e);
- },
- constraints: self.constraints,
- iceServers: self.options.iceServers,
- offerSDP: {
- type: "offer",
- sdp: self.remoteSDP
- },
- turnServer: self.options.turnServer
- });
-
- onStreamSuccess(self, stream);
- }
-
- function onError(e) {
- onStreamError(self, e);
- }
-
- var mediaParams = getMediaParams(self);
-
- console.log("Audio constraints", mediaParams.audio);
- console.log("Video constraints", mediaParams.video);
-
- if (self.options.useVideo && self.options.localVideo && !self.options.useStream) {
- getUserMedia({
- constraints: {
- audio: false,
- video: { deviceId: params.useCamera },
- },
- localVideo: self.options.localVideo,
- onsuccess: function(e) {self.options.localVideoStream = e; console.log("local video ready");},
- onerror: function(e) {console.error("local video error!");}
- });
- }
-
- if (self.options.useStream) {
- if (self.options.useVideo) {
- self.options.localVideoStream = self.options.useStream;
- if (self.options.localVideo) {
- activateLocalVideo(self.options.localVideo, self.options.useStream);
- }
- }
- onSuccess(self.options.useStream);
- }
- else {
- getUserMedia({
- constraints: {
- audio: mediaParams.audio,
- video: mediaParams.video
- },
- video: mediaParams.useVideo,
- onsuccess: onSuccess,
- onerror: onError
- });
- }
-
- };
-
- function getMediaParams(obj) {
-
- var audio;
-
- if (obj.options.useMic && obj.options.useMic === "none") {
- console.log("Microphone Disabled");
- audio = false;
- } else if (obj.options.videoParams && obj.options.screenShare) {//obj.options.videoParams.chromeMediaSource == 'desktop') {
- console.error("SCREEN SHARE", obj.options.videoParams);
- audio = false;
- } else {
- audio = {
- };
-
- if (obj.options.audioParams) {
- audio = obj.options.audioParams;
- }
-
- if (obj.options.useMic !== "any") {
- //audio.optional = [{sourceId: obj.options.useMic}];
- audio.deviceId = {exact: obj.options.useMic};
- }
- }
-
- if (obj.options.useVideo && obj.options.localVideo && !obj.options.useStream) {
- getUserMedia({
- constraints: {
- audio: false,
- video: { deviceId: obj.options.useCamera },
- },
- localVideo: obj.options.localVideo,
- onsuccess: function(e) {obj.options.localVideoStream = e; console.log("local video ready");},
- onerror: function(e) {console.error("local video error!");}
- });
- }
-
- var video = {};
- var bestFrameRate = obj.options.videoParams.vertoBestFrameRate;
- var minFrameRate = obj.options.videoParams.minFrameRate || 15;
- delete obj.options.videoParams.vertoBestFrameRate;
-
- if (obj.options.screenShare) {
- if (!obj.options.useCamera && !!navigator.mozGetUserMedia) {
- //This is an issue, only FireFox needs to ask this additional question if its screen or window we need a better way
- var dowin = window.confirm("Do you want to share an application window? If not you can share an entire screen.");
-
- video = {
- width: {min: obj.options.videoParams.minWidth, max: obj.options.videoParams.maxWidth},
- height: {min: obj.options.videoParams.minHeight, max: obj.options.videoParams.maxHeight},
- mediaSource: dowin ? "window" : "screen"
- }
- } else {
- var opt = [];
- if (obj.options.useCamera) {
- opt.push({sourceId: obj.options.useCamera});
- }
-
- if (bestFrameRate) {
- opt.push({minFrameRate: bestFrameRate});
- opt.push({maxFrameRate: bestFrameRate});
- }
-
- video = {
- mandatory: obj.options.videoParams,
- optional: opt
- };
- // NOTE: This is a workaround for
- // https://bugs.chromium.org/p/chromium/issues/detail?id=862325
- if (!!navigator.userAgent.match(/Android/i)) {
- delete video.frameRate.min;
- }
- }
- } else {
-
- video = {
- //mandatory: obj.options.videoParams,
- width: {min: obj.options.videoParams.minWidth, max: obj.options.videoParams.maxWidth},
- height: {min: obj.options.videoParams.minHeight, max: obj.options.videoParams.maxHeight}
- };
-
-
-
- var useVideo = obj.options.useVideo;
-
- if (useVideo && obj.options.useCamera && obj.options.useCamera !== "none") {
- //if (!video.optional) {
- //video.optional = [];
- //}
-
-
- if (obj.options.useCamera !== "any") {
- //video.optional.push({sourceId: obj.options.useCamera});
- video.deviceId = {
- exact: obj.options.useCamera,
- };
- }
-
- if (bestFrameRate) {
- //video.optional.push({minFrameRate: bestFrameRate});
- //video.optional.push({maxFrameRate: bestFrameRate});
- video.frameRate = {ideal: bestFrameRate, min: minFrameRate, max: 30};
- }
-
- } else {
- console.log("Camera Disabled");
- video = false;
- useVideo = false;
- }
- }
-
- return {audio: audio, video: video, useVideo: useVideo};
- }
-
- $.FSRTC.prototype.call = function(profile) {
- checkCompat();
-
- var self = this;
- var screen = false;
-
- self.type = "offer";
-
- if (self.options.videoParams && self.options.screenShare) { //self.options.videoParams.chromeMediaSource == 'desktop') {
- screen = true;
- }
-
- function onSuccess(stream) {
- self.localStream = stream;
-
- if (screen) {
- self.constraints.offerToReceiveVideo = false;
- self.constraints.offerToReceiveAudio = false;
- self.constraints.offerToSendAudio = false;
- }
-
- self.peer = FSRTCPeerConnection({
- type: self.type,
- attachStream: self.localStream,
- onICE: function(candidate) {
- return onICE(self, candidate);
- },
- onICEComplete: function() {
- return onICEComplete(self);
- },
- onRemoteStream: screen ? function(stream) {} : function(stream) {
- return onRemoteStream(self, stream);
- },
- onOfferSDP: function(sdp) {
- return onOfferSDP(self, sdp);
- },
- onICESDP: function(sdp) {
- return onICESDP(self, sdp);
- },
- onChannelError: function(e) {
- return onChannelError(self, e);
- },
- constraints: self.constraints,
- iceServers: self.options.iceServers,
- turnServer: self.options.turnServer
- });
-
- onStreamSuccess(self, stream);
- }
-
- function onError(e) {
- onStreamError(self, e);
- }
-
- var mediaParams = getMediaParams(self);
-
- console.log("Audio constraints", mediaParams.audio);
- console.log("Video constraints", mediaParams.video);
-
- if (self.options.useStream) {
- if (self.options.useVideo) {
- self.options.localVideoStream = self.options.useStream;
- if (self.options.localVideo) {
- activateLocalVideo(self.options.localVideo, self.options.useStream);
- }
- }
- onSuccess(self.options.useStream);
- }
- else if (mediaParams.audio || mediaParams.video) {
-
- getUserMedia({
- constraints: {
- audio: mediaParams.audio,
- video: mediaParams.video
- },
- video: mediaParams.useVideo,
- onsuccess: onSuccess,
- onerror: onError
- });
-
- } else {
- onSuccess(null);
- }
-
-
-
- /*
- navigator.getUserMedia({
- video: self.options.useVideo,
- audio: true
- }, onSuccess, onError);
- */
-
- };
-
- // DERIVED from RTCPeerConnection-v1.5
- // 2013, @muazkh - github.com/muaz-khan
- // MIT License - https://www.webrtc-experiment.com/licence/
- // Documentation - https://github.com/muaz-khan/WebRTC-Experiment/tree/master/RTCPeerConnection
-
- function FSRTCPeerConnection(options) {
- var gathering = false, done = false;
- var config = {};
- var default_ice = [{ urls: ['stun:stun.l.google.com:19302'] }];
-
- if (self.options.turnServer) {
- default_ice.push(self.options.turnServer)
- }
-
- if (options.iceServers) {
- if (typeof(options.iceServers) === "boolean") {
- config.iceServers = default_ice;
- } else {
- config.iceServers = options.iceServers;
- }
- }
-
- config.bundlePolicy = "max-compat";
-
- var peer = new window.RTCPeerConnection(config);
-
- openOffererChannel();
- var x = 0;
-
- function ice_handler() {
-
- done = true;
- gathering = null;
-
- if (options.onICEComplete) {
- options.onICEComplete();
- }
-
- if (options.type == "offer") {
- options.onICESDP(peer.localDescription);
- } else {
- if (!x && options.onICESDP) {
- options.onICESDP(peer.localDescription);
- }
- }
- }
-
- peer.onicecandidate = function(event) {
-
- if (done) {
- return;
- }
-
- if (!gathering) {
- gathering = setTimeout(ice_handler, 1000);
- }
-
- if (event) {
- if (event.candidate) {
- options.onICE(event.candidate);
- }
- } else {
- done = true;
-
- if (gathering) {
- clearTimeout(gathering);
- gathering = null;
- }
-
- ice_handler();
- }
- };
-
- // attachStream = MediaStream;
- if (options.attachStream) peer.addStream(options.attachStream);
-
- // attachStreams[0] = audio-stream;
- // attachStreams[1] = video-stream;
- // attachStreams[2] = screen-capturing-stream;
- if (options.attachStreams && options.attachStream.length) {
- var streams = options.attachStreams;
- for (var i = 0; i < streams.length; i++) {
- peer.addStream(streams[i]);
- }
- }
-
- peer.onaddstream = function(event) {
- var remoteMediaStream = event.stream;
-
- // onRemoteStreamEnded(MediaStream)
- remoteMediaStream.oninactive = function () {
- if (options.onRemoteStreamEnded) options.onRemoteStreamEnded(remoteMediaStream);
- };
-
- // onRemoteStream(MediaStream)
- if (options.onRemoteStream) options.onRemoteStream(remoteMediaStream);
-
- //console.debug('on:add:stream', remoteMediaStream);
- };
-
- //var constraints = options.constraints || {
- // offerToReceiveAudio: true,
- //offerToReceiveVideo: true
- //};
-
- // onOfferSDP(RTCSessionDescription)
- function createOffer() {
- if (!options.onOfferSDP) return;
-
- peer.createOffer(function(sessionDescription) {
- sessionDescription.sdp = serializeSdp(sessionDescription.sdp);
- peer.setLocalDescription(sessionDescription);
- options.onOfferSDP(sessionDescription);
- },
- onSdpError, options.constraints);
- }
-
- // onAnswerSDP(RTCSessionDescription)
- function createAnswer() {
- if (options.type != "answer") return;
-
- //options.offerSDP.sdp = addStereo(options.offerSDP.sdp);
- peer.setRemoteDescription(new window.RTCSessionDescription(options.offerSDP), onSdpSuccess, onSdpError);
- peer.createAnswer(function(sessionDescription) {
- sessionDescription.sdp = serializeSdp(sessionDescription.sdp);
- peer.setLocalDescription(sessionDescription);
- if (options.onAnswerSDP) {
- options.onAnswerSDP(sessionDescription);
- }
- },
- onSdpError);
- }
-
-
- if ((options.onChannelMessage) || !options.onChannelMessage) {
- createOffer();
- createAnswer();
- }
-
- // DataChannel Bandwidth
- function setBandwidth(sdp) {
- // remove existing bandwidth lines
- sdp = sdp.replace(/b=AS([^\r\n]+\r\n)/g, '');
- sdp = sdp.replace(/a=mid:data\r\n/g, 'a=mid:data\r\nb=AS:1638400\r\n');
-
- return sdp;
- }
-
- // old: FF<>Chrome interoperability management
- function getInteropSDP(sdp) {
- var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split(''),
- extractedChars = '';
-
- function getChars() {
- extractedChars += chars[parseInt(Math.random() * 40)] || '';
- if (extractedChars.length < 40) getChars();
-
- return extractedChars;
- }
-
- // usually audio-only streaming failure occurs out of audio-specific crypto line
- // a=crypto:1 AES_CM_128_HMAC_SHA1_32 --------- kAttributeCryptoVoice
- if (options.onAnswerSDP) sdp = sdp.replace(/(a=crypto:0 AES_CM_128_HMAC_SHA1_32)(.*?)(\r\n)/g, '');
-
- // video-specific crypto line i.e. SHA1_80
- // a=crypto:1 AES_CM_128_HMAC_SHA1_80 --------- kAttributeCryptoVideo
- var inline = getChars() + '\r\n' + (extractedChars = '');
- sdp = sdp.indexOf('a=crypto') == -1 ? sdp.replace(/c=IN/g, 'a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:' + inline + 'c=IN') : sdp;
-
- return sdp;
- }
-
- function serializeSdp(sdp) {
- return sdp;
- }
-
- // DataChannel management
- var channel;
-
- function openOffererChannel() {
- if (!options.onChannelMessage) return;
-
- _openOffererChannel();
-
- return;
- }
-
- function _openOffererChannel() {
- channel = peer.createDataChannel(options.channel || 'RTCDataChannel', {
- reliable: false
- });
-
- setChannelEvents();
- }
-
- function setChannelEvents() {
- channel.onmessage = function(event) {
- if (options.onChannelMessage) options.onChannelMessage(event);
- };
-
- channel.onopen = function() {
- if (options.onChannelOpened) options.onChannelOpened(channel);
- };
- channel.onclose = function(event) {
- if (options.onChannelClosed) options.onChannelClosed(event);
-
- console.warn('WebRTC DataChannel closed', event);
- };
- channel.onerror = function(event) {
- if (options.onChannelError) options.onChannelError(event);
-
- console.error('WebRTC DataChannel error', event);
- };
- }
-
- function openAnswererChannel() {
- peer.ondatachannel = function(event) {
- channel = event.channel;
- channel.binaryType = 'blob';
- setChannelEvents();
- };
-
- return;
- }
-
- // fake:true is also available on chrome under a flag!
- function useless() {
- log('Error in fake:true');
- }
-
- function onSdpSuccess() {}
-
- function onSdpError(e) {
- if (options.onChannelError) {
- options.onChannelError(e);
- }
- console.error('sdp error:', e);
- }
-
- return {
- addAnswerSDP: function(sdp, cbSuccess, cbError) {
-
- peer.setRemoteDescription(new window.RTCSessionDescription(sdp), cbSuccess ? cbSuccess : onSdpSuccess, cbError ? cbError : onSdpError);
- },
- addICE: function(candidate) {
- peer.addIceCandidate(new window.RTCIceCandidate({
- sdpMLineIndex: candidate.sdpMLineIndex,
- candidate: candidate.candidate
- }));
- },
-
- peer: peer,
- channel: channel,
- sendData: function(message) {
- if (channel) {
- channel.send(message);
- }
- },
-
- stop: function() {
- peer.close();
- if (options.attachStream) {
- if(typeof options.attachStream.stop == 'function') {
- options.attachStream.stop();
- } else {
- options.attachStream.active = false;
- }
- }
- }
-
- };
- }
-
- // getUserMedia
- var video_constraints = {
- //mandatory: {},
- //optional: []
- };
-
- function activateLocalVideo(el, stream) {
- el.srcObject = stream;
- el.style.display = 'block';
- }
-
- function deactivateLocalVideo(el) {
- el.srcObject = null;
- el.style.display = 'none';
- }
-
- function getUserMedia(options) {
- var n = navigator,
- media;
- n.getMedia = n.getUserMedia;
- n.getMedia(options.constraints || {
- audio: true,
- video: video_constraints
- },
- streaming, options.onerror ||
- function(e) {
- console.error(e);
- });
-
- function streaming(stream) {
- if (options.localVideo) {
- activateLocalVideo(options.localVideo, stream);
- }
-
- if (options.onsuccess) {
- options.onsuccess(stream);
- }
-
- media = stream;
- }
-
- return media;
- }
-
- $.FSRTC.resSupported = function(w, h) {
- for (var i in $.FSRTC.validRes) {
- if ($.FSRTC.validRes[i][0] == w && $.FSRTC.validRes[i][1] == h) {
- return true;
- }
- }
-
- return false;
- }
-
- $.FSRTC.bestResSupported = function() {
- var w = 0, h = 0;
-
- for (var i in $.FSRTC.validRes) {
- if ($.FSRTC.validRes[i][0] >= w && $.FSRTC.validRes[i][1] >= h) {
- w = $.FSRTC.validRes[i][0];
- h = $.FSRTC.validRes[i][1];
- }
- }
-
- return [w, h];
- }
-
- var resList = [[160, 120], [320, 180], [320, 240], [640, 360], [640, 480], [1280, 720], [1920, 1080]];
- var resI = 0;
- var ttl = 0;
-
- var checkRes = function (cam, func) {
-
- if (resI >= resList.length) {
- var res = {
- 'validRes': $.FSRTC.validRes,
- 'bestResSupported': $.FSRTC.bestResSupported()
- };
-
- localStorage.setItem("res_" + cam, $.toJSON(res));
-
- if (func) return func(res);
- return;
- }
-
- w = resList[resI][0];
- h = resList[resI][1];
- resI++;
-
- var video = {
- width: {exact: w},
- height: {exact: h}
- };
-
- if (cam !== "any") {
- video.deviceId = {
- exact: cam,
- };
- }
-
- getUserMedia({
- constraints: {
- audio: ttl++ == 0,
- video: video
- },
- onsuccess: function(e) {
- e.getTracks().forEach(function(track) {track.stop();});
- console.info(w + "x" + h + " supported."); $.FSRTC.validRes.push([w, h]); checkRes(cam, func);},
- onerror: function(e) {console.warn( w + "x" + h + " not supported."); checkRes(cam, func);}
- });
- }
-
-
- $.FSRTC.getValidRes = function (cam, func) {
- var used = [];
- var cached = localStorage.getItem("res_" + cam);
-
- if (cached) {
- var cache = $.parseJSON(cached);
-
- if (cache) {
- $.FSRTC.validRes = cache.validRes;
- console.log("CACHED RES FOR CAM " + cam, cache);
- } else {
- console.error("INVALID CACHE");
- }
- return func ? func(cache) : null;
- }
-
-
- $.FSRTC.validRes = [];
- resI = 0;
-
- checkRes(cam, func);
- }
-
- $.FSRTC.checkPerms = function (runtime, check_audio, check_video) {
- getUserMedia({
- constraints: {
- audio: check_audio,
- video: check_video,
- },
- onsuccess: function(e) {
-
- e.getTracks().forEach(function(track) {track.stop();});
-
- console.info("media perm init complete");
- if (runtime) {
- setTimeout(runtime, 100, true);
- }
- },
- onerror: function(e) {
- if (check_video && check_audio) {
- console.error("error, retesting with audio params only");
- return $.FSRTC.checkPerms(runtime, check_audio, false);
- }
-
- console.error("media perm init error");
-
- if (runtime) {
- runtime(false)
- }
- }
- });
- }
-
-})(jQuery);
-/*
- * Verto HTML5/Javascript Telephony Signaling and Control Protocol Stack for FreeSWITCH
- * Copyright (C) 2005-2014, Anthony Minessale II
- *
- * Version: MPL 1.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is jquery.jsonrpclient.js modified for Verto HTML5/Javascript Telephony Signaling and Control Protocol Stack for FreeSWITCH
- *
- * The Initial Developer of the Original Code is
- * Textalk AB http://textalk.se/
- * Portions created by the Initial Developer are Copyright (C)
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Anthony Minessale II
- *
- * jquery.jsonrpclient.js - JSON RPC client code
- *
- */
-/**
- * This plugin requires jquery.json.js to be available, or at least the methods $.toJSON and
- * $.parseJSON.
- *
- * The plan is to make use of websockets if they are available, but work just as well with only
- * http if not.
- *
- * Usage example:
- *
- * var foo = new $.JsonRpcClient({ ajaxUrl: '/backend/jsonrpc' });
- * foo.call(
- * 'bar', [ 'A parameter', 'B parameter' ],
- * function(result) { alert('Foo bar answered: ' + result.my_answer); },
- * function(error) { console.log('There was an error', error); }
- * );
- *
- * More examples are available in README.md
- */
-(function($) {
- /**
- * @fn new
- * @memberof $.JsonRpcClient
- *
- * @param options An object stating the backends:
- * ajaxUrl A url (relative or absolute) to a http(s) backend.
- * socketUrl A url (relative of absolute) to a ws(s) backend.
- * onmessage A socket message handler for other messages (non-responses).
- * getSocket A function returning a WebSocket or null.
- * It must take an onmessage_cb and bind it to the onmessage event
- * (or chain it before/after some other onmessage handler).
- * Or, it could return null if no socket is available.
- * The returned instance must have readyState <= 1, and if less than 1,
- * react to onopen binding.
- */
- $.JsonRpcClient = function(options) {
- var self = this;
- this.options = $.extend({
- ajaxUrl : null,
- socketUrl : null, ///< The ws-url for default getSocket.
- onmessage : null, ///< Other onmessage-handler.
- login : null, /// auth login
- passwd : null, /// auth passwd
- sessid : null,
- loginParams : null,
- userVariables : null,
- getSocket : function(onmessage_cb) { return self._getSocket(onmessage_cb); }
- }, options);
-
- self.ws_cnt = 0;
-
- // Declare an instance version of the onmessage callback to wrap 'this'.
- this.wsOnMessage = function(event) { self._wsOnMessage(event); };
- };
-
- /// Holding the WebSocket on default getsocket.
- $.JsonRpcClient.prototype._ws_socket = null;
-
- /// Object : { success_cb: cb, error_cb: cb }
- $.JsonRpcClient.prototype._ws_callbacks = {};
-
- /// The next JSON-RPC request id.
- $.JsonRpcClient.prototype._current_id = 1;
-
-
- $.JsonRpcClient.prototype.speedTest = function (bytes, cb) {
- var socket = this.options.getSocket(this.wsOnMessage);
- if (socket !== null) {
- this.speedCB = cb;
- this.speedBytes = bytes;
- socket.send("#SPU " + bytes);
-
- var loops = bytes / 1024;
- var rem = bytes % 1024;
- var i;
- var data = new Array(1024).join(".");
- for (i = 0; i < loops; i++) {
- socket.send("#SPB " + data);
- }
-
- if (rem) {
- socket.send("#SPB " + data);
- }
-
- socket.send("#SPE");
- }
- };
-
-
-
- /**
- * @fn call
- * @memberof $.JsonRpcClient
- *
- * @param method The method to run on JSON-RPC server.
- * @param params The params; an array or object.
- * @param success_cb A callback for successful request.
- * @param error_cb A callback for error.
- */
- $.JsonRpcClient.prototype.call = function(method, params, success_cb, error_cb) {
- // Construct the JSON-RPC 2.0 request.
-
- if (!params) {
- params = {};
- }
-
- if (this.options.sessid) {
- params.sessid = this.options.sessid;
- }
-
- var request = {
- jsonrpc : '2.0',
- method : method,
- params : params,
- id : this._current_id++ // Increase the id counter to match request/response
- };
-
- if (!success_cb) {
- success_cb = function(e){console.log("Success: ", e);};
- }
-
- if (!error_cb) {
- error_cb = function(e){console.log("Error: ", e);};
- }
-
- // Try making a WebSocket call.
- var socket = this.options.getSocket(this.wsOnMessage);
- if (socket !== null) {
- this._wsCall(socket, request, success_cb, error_cb);
- return;
- }
-
- // No WebSocket, and no HTTP backend? This won't work.
- if (this.options.ajaxUrl === null) {
- throw "$.JsonRpcClient.call used with no websocket and no http endpoint.";
- }
-
- $.ajax({
- type : 'POST',
- url : this.options.ajaxUrl,
- data : $.toJSON(request),
- dataType : 'json',
- cache : false,
-
- success : function(data) {
- if ('error' in data) error_cb(data.error, this);
- success_cb(data.result, this);
- },
-
- // JSON-RPC Server could return non-200 on error
- error : function(jqXHR, textStatus, errorThrown) {
- try {
- var response = $.parseJSON(jqXHR.responseText);
-
- if ('console' in window) console.log(response);
-
- error_cb(response.error, this);
- } catch (err) {
- // Perhaps the responseText wasn't really a jsonrpc-error.
- error_cb({ error: jqXHR.responseText }, this);
- }
- }
- });
- };
-
- /**
- * Notify sends a command to the server that won't need a response. In http, there is probably
- * an empty response - that will be dropped, but in ws there should be no response at all.
- *
- * This is very similar to call, but has no id and no handling of callbacks.
- *
- * @fn notify
- * @memberof $.JsonRpcClient
- *
- * @param method The method to run on JSON-RPC server.
- * @param params The params; an array or object.
- */
- $.JsonRpcClient.prototype.notify = function(method, params) {
- // Construct the JSON-RPC 2.0 request.
-
- if (this.options.sessid) {
- params.sessid = this.options.sessid;
- }
-
- var request = {
- jsonrpc: '2.0',
- method: method,
- params: params
- };
-
- // Try making a WebSocket call.
- var socket = this.options.getSocket(this.wsOnMessage);
- if (socket !== null) {
- this._wsCall(socket, request);
- return;
- }
-
- // No WebSocket, and no HTTP backend? This won't work.
- if (this.options.ajaxUrl === null) {
- throw "$.JsonRpcClient.notify used with no websocket and no http endpoint.";
- }
-
- $.ajax({
- type : 'POST',
- url : this.options.ajaxUrl,
- data : $.toJSON(request),
- dataType : 'json',
- cache : false
- });
- };
-
- /**
- * Make a batch-call by using a callback.
- *
- * The callback will get an object "batch" as only argument. On batch, you can call the methods
- * "call" and "notify" just as if it was a normal $.JsonRpcClient object, and all calls will be
- * sent as a batch call then the callback is done.
- *
- * @fn batch
- * @memberof $.JsonRpcClient
- *
- * @param callback The main function which will get a batch handler to run call and notify on.
- * @param all_done_cb A callback function to call after all results have been handled.
- * @param error_cb A callback function to call if there is an error from the server.
- * Note, that batch calls should always get an overall success, and the
- * only error
- */
- $.JsonRpcClient.prototype.batch = function(callback, all_done_cb, error_cb) {
- var batch = new $.JsonRpcClient._batchObject(this, all_done_cb, error_cb);
- callback(batch);
- batch._execute();
- };
-
- /**
- * The default getSocket handler.
- *
- * @param onmessage_cb The callback to be bound to onmessage events on the socket.
- *
- * @fn _getSocket
- * @memberof $.JsonRpcClient
- */
-
- $.JsonRpcClient.prototype.socketReady = function() {
- if (this._ws_socket === null || this._ws_socket.readyState > 1) {
- return false;
- }
-
- return true;
- };
-
- $.JsonRpcClient.prototype.closeSocket = function() {
- var self = this;
- if (self.socketReady()) {
- self._ws_socket.onclose = function (w) {console.log("Closing Socket");};
- self._ws_socket.close();
- }
- };
-
- $.JsonRpcClient.prototype.loginData = function(params) {
- var self = this;
- self.options.login = params.login;
- self.options.passwd = params.passwd;
- self.options.loginParams = params.loginParams;
- self.options.userVariables = params.userVariables;
- };
-
- $.JsonRpcClient.prototype.connectSocket = function(onmessage_cb) {
- var self = this;
-
- if (self.to) {
- clearTimeout(self.to);
- }
-
- if (!self.socketReady()) {
- self.authing = false;
-
- if (self._ws_socket) {
- delete self._ws_socket;
- }
-
- // No socket, or dying socket, let's get a new one.
- self._ws_socket = new WebSocket(self.options.socketUrl);
-
- if (self._ws_socket) {
- // Set up onmessage handler.
- self._ws_socket.onmessage = onmessage_cb;
- self._ws_socket.onclose = function (w) {
- if (!self.ws_sleep) {
- self.ws_sleep = 1000;
- }
-
- if (self.options.onWSClose) {
- self.options.onWSClose(self);
- }
-
- if (self.ws_cnt > 10 && self.options.wsFallbackURL) {
- self.options.socketUrl = self.options.wsFallbackURL;
- }
-
- console.error("Websocket Lost " + self.ws_cnt + " sleep: " + self.ws_sleep + "msec");
-
- self.to = setTimeout(function() {
- console.log("Attempting Reconnection....");
- self.connectSocket(onmessage_cb);
- }, self.ws_sleep);
-
- self.ws_cnt++;
-
- if (self.ws_sleep < 3000 && (self.ws_cnt % 10) === 0) {
- self.ws_sleep += 1000;
- }
- };
-
- // Set up sending of message for when the socket is open.
- self._ws_socket.onopen = function() {
- if (self.to) {
- clearTimeout(self.to);
- }
- self.ws_sleep = 1000;
- self.ws_cnt = 0;
- if (self.options.onWSConnect) {
- self.options.onWSConnect(self);
- }
-
- var req;
- // Send the requests.
- while ((req = $.JsonRpcClient.q.pop())) {
- self._ws_socket.send(req);
- }
- };
- }
- }
-
- return self._ws_socket ? true : false;
- };
-
- $.JsonRpcClient.prototype.stopRetrying = function() {
- if (self.to)
- clearTimeout(self.to);
- }
-
- $.JsonRpcClient.prototype._getSocket = function(onmessage_cb) {
- // If there is no ws url set, we don't have a socket.
- // Likewise, if there is no window.WebSocket.
- if (this.options.socketUrl === null || !("WebSocket" in window)) return null;
-
- this.connectSocket(onmessage_cb);
-
- return this._ws_socket;
- };
-
- /**
- * Queue to save messages delivered when websocket is not ready
- */
- $.JsonRpcClient.q = [];
-
- /**
- * Internal handler to dispatch a JRON-RPC request through a websocket.
- *
- * @fn _wsCall
- * @memberof $.JsonRpcClient
- */
- $.JsonRpcClient.prototype._wsCall = function(socket, request, success_cb, error_cb) {
- var request_json = $.toJSON(request);
-
- if (socket.readyState < 1) {
- // The websocket is not open yet; we have to set sending of the message in onopen.
- self = this; // In closure below, this is set to the WebSocket. Use self instead.
- $.JsonRpcClient.q.push(request_json);
- } else {
- // We have a socket and it should be ready to send on.
- socket.send(request_json);
- }
-
- // Setup callbacks. If there is an id, this is a call and not a notify.
- if ('id' in request && typeof success_cb !== 'undefined') {
- this._ws_callbacks[request.id] = { request: request_json, request_obj: request, success_cb: success_cb, error_cb: error_cb };
- }
- };
-
- /**
- * Internal handler for the websocket messages. It determines if the message is a JSON-RPC
- * response, and if so, tries to couple it with a given callback. Otherwise, it falls back to
- * given external onmessage-handler, if any.
- *
- * @param event The websocket onmessage-event.
- */
- $.JsonRpcClient.prototype._wsOnMessage = function(event) {
- // Check if this could be a JSON RPC message.
- var response;
-
- // Special sub proto
- if (event.data[0] == "#" && event.data[1] == "S" && event.data[2] == "P") {
- if (event.data[3] == "U") {
- this.up_dur = parseInt(event.data.substring(4));
- } else if (this.speedCB && event.data[3] == "D") {
- this.down_dur = parseInt(event.data.substring(4));
-
- var up_kps = (((this.speedBytes * 8) / (this.up_dur / 1000)) / 1024).toFixed(0);
- var down_kps = (((this.speedBytes * 8) / (this.down_dur / 1000)) / 1024).toFixed(0);
-
- console.info("Speed Test: Up: " + up_kps + " Down: " + down_kps);
- var cb = this.speedCB;
- this.speedCB = null;
- cb(event, {
- upDur: this.up_dur,
- downDur: this.down_dur,
- upKPS: up_kps,
- downKPS: down_kps
- });
- }
-
- return;
- }
-
-
- try {
- response = $.parseJSON(event.data);
-
- /// @todo Make using the jsonrcp 2.0 check optional, to use this on JSON-RPC 1 backends.
-
- if (typeof response === 'object' &&
- 'jsonrpc' in response &&
- response.jsonrpc === '2.0') {
-
- /// @todo Handle bad response (without id).
-
- // If this is an object with result, it is a response.
- if ('result' in response && this._ws_callbacks[response.id]) {
- // Get the success callback.
- var success_cb = this._ws_callbacks[response.id].success_cb;
-
- /*
- // set the sessid if present
- if ('sessid' in response.result && !this.options.sessid || (this.options.sessid != response.result.sessid)) {
- this.options.sessid = response.result.sessid;
- if (this.options.sessid) {
- console.log("setting session UUID to: " + this.options.sessid);
- }
- }
- */
- // Delete the callback from the storage.
- delete this._ws_callbacks[response.id];
-
- // Run callback with result as parameter.
- success_cb(response.result, this);
- return;
- } else if ('error' in response && this._ws_callbacks[response.id]) {
- // If this is an object with error, it is an error response.
-
- // Get the error callback.
- var error_cb = this._ws_callbacks[response.id].error_cb;
- var orig_req = this._ws_callbacks[response.id].request;
-
- // if this is an auth request, send the credentials and resend the failed request
- if (!self.authing && response.error.code == -32000 && self.options.login && self.options.passwd) {
- self.authing = true;
-
- this.call("login", { login: self.options.login, passwd: self.options.passwd, loginParams: self.options.loginParams,
- userVariables: self.options.userVariables},
- this._ws_callbacks[response.id].request_obj.method == "login" ?
- function(e) {
- self.authing = false;
- console.log("logged in");
- delete self._ws_callbacks[response.id];
-
- if (self.options.onWSLogin) {
- self.options.onWSLogin(true, self);
- }
- }
-
- :
-
- function(e) {
- self.authing = false;
- console.log("logged in, resending request id: " + response.id);
- var socket = self.options.getSocket(self.wsOnMessage);
- if (socket !== null) {
- socket.send(orig_req);
- }
- if (self.options.onWSLogin) {
- self.options.onWSLogin(true, self);
- }
- },
-
- function(e) {
- console.log("error logging in, request id:", response.id);
- delete self._ws_callbacks[response.id];
- error_cb(response.error, this);
- if (self.options.onWSLogin) {
- self.options.onWSLogin(false, self);
- }
- });
- return;
- }
-
- // Delete the callback from the storage.
- delete this._ws_callbacks[response.id];
-
- // Run callback with the error object as parameter.
- error_cb(response.error, this);
- return;
- }
- }
- } catch (err) {
- // Probably an error while parsing a non json-string as json. All real JSON-RPC cases are
- // handled above, and the fallback method is called below.
- console.log("ERROR: "+ err);
- return;
- }
-
- // This is not a JSON-RPC response. Call the fallback message handler, if given.
- if (typeof this.options.onmessage === 'function') {
- event.eventData = response;
- if (!event.eventData) {
- event.eventData = {};
- }
-
- var reply = this.options.onmessage(event);
-
- if (reply && typeof reply === "object" && event.eventData.id) {
- var msg = {
- jsonrpc: "2.0",
- id: event.eventData.id,
- result: reply
- };
-
- var socket = self.options.getSocket(self.wsOnMessage);
- if (socket !== null) {
- socket.send($.toJSON(msg));
- }
- }
- }
- };
-
-
- /************************************************************************************************
- * Batch object with methods
- ************************************************************************************************/
-
- /**
- * Handling object for batch calls.
- */
- $.JsonRpcClient._batchObject = function(jsonrpcclient, all_done_cb, error_cb) {
- // Array of objects to hold the call and notify requests. Each objects will have the request
- // object, and unless it is a notify, success_cb and error_cb.
- this._requests = [];
-
- this.jsonrpcclient = jsonrpcclient;
- this.all_done_cb = all_done_cb;
- this.error_cb = typeof error_cb === 'function' ? error_cb : function() {};
-
- };
-
- /**
- * @sa $.JsonRpcClient.prototype.call
- */
- $.JsonRpcClient._batchObject.prototype.call = function(method, params, success_cb, error_cb) {
-
- if (!params) {
- params = {};
- }
-
- if (this.options.sessid) {
- params.sessid = this.options.sessid;
- }
-
- if (!success_cb) {
- success_cb = function(e){console.log("Success: ", e);};
- }
-
- if (!error_cb) {
- error_cb = function(e){console.log("Error: ", e);};
- }
-
- this._requests.push({
- request : {
- jsonrpc : '2.0',
- method : method,
- params : params,
- id : this.jsonrpcclient._current_id++ // Use the client's id series.
- },
- success_cb : success_cb,
- error_cb : error_cb
- });
- };
-
- /**
- * @sa $.JsonRpcClient.prototype.notify
- */
- $.JsonRpcClient._batchObject.prototype.notify = function(method, params) {
- if (this.options.sessid) {
- params.sessid = this.options.sessid;
- }
-
- this._requests.push({
- request : {
- jsonrpc : '2.0',
- method : method,
- params : params
- }
- });
- };
-
- /**
- * Executes the batched up calls.
- */
- $.JsonRpcClient._batchObject.prototype._execute = function() {
- var self = this;
-
- if (this._requests.length === 0) return; // All done :P
-
- // Collect all request data and sort handlers by request id.
- var batch_request = [];
- var handlers = {};
- var i = 0;
- var call;
- var success_cb;
- var error_cb;
-
- // If we have a WebSocket, just send the requests individually like normal calls.
- var socket = self.jsonrpcclient.options.getSocket(self.jsonrpcclient.wsOnMessage);
- if (socket !== null) {
- for (i = 0; i < this._requests.length; i++) {
- call = this._requests[i];
- success_cb = ('success_cb' in call) ? call.success_cb : undefined;
- error_cb = ('error_cb' in call) ? call.error_cb : undefined;
- self.jsonrpcclient._wsCall(socket, call.request, success_cb, error_cb);
- }
-
- if (typeof all_done_cb === 'function') all_done_cb(result);
- return;
- }
-
- for (i = 0; i < this._requests.length; i++) {
- call = this._requests[i];
- batch_request.push(call.request);
-
- // If the request has an id, it should handle returns (otherwise it's a notify).
- if ('id' in call.request) {
- handlers[call.request.id] = {
- success_cb : call.success_cb,
- error_cb : call.error_cb
- };
- }
- }
-
- success_cb = function(data) { self._batchCb(data, handlers, self.all_done_cb); };
-
- // No WebSocket, and no HTTP backend? This won't work.
- if (self.jsonrpcclient.options.ajaxUrl === null) {
- throw "$.JsonRpcClient.batch used with no websocket and no http endpoint.";
- }
-
- // Send request
- $.ajax({
- url : self.jsonrpcclient.options.ajaxUrl,
- data : $.toJSON(batch_request),
- dataType : 'json',
- cache : false,
- type : 'POST',
-
- // Batch-requests should always return 200
- error : function(jqXHR, textStatus, errorThrown) {
- self.error_cb(jqXHR, textStatus, errorThrown);
- },
- success : success_cb
- });
- };
-
- /**
- * Internal helper to match the result array from a batch call to their respective callbacks.
- *
- * @fn _batchCb
- * @memberof $.JsonRpcClient
- */
- $.JsonRpcClient._batchObject.prototype._batchCb = function(result, handlers, all_done_cb) {
- for (var i = 0; i < result.length; i++) {
- var response = result[i];
-
- // Handle error
- if ('error' in response) {
- if (response.id === null || !(response.id in handlers)) {
- // An error on a notify? Just log it to the console.
- if ('console' in window) console.log(response);
- } else {
- handlers[response.id].error_cb(response.error, this);
- }
- } else {
- // Here we should always have a correct id and no error.
- if (!(response.id in handlers) && 'console' in window) {
- console.log(response);
- } else {
- handlers[response.id].success_cb(response.result, this);
- }
- }
- }
-
- if (typeof all_done_cb === 'function') all_done_cb(result);
- };
-
-})(jQuery);
-
-/*
- * Verto HTML5/Javascript Telephony Signaling and Control Protocol Stack for FreeSWITCH
- * Copyright (C) 2005-2014, Anthony Minessale II
- *
- * Version: MPL 1.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Verto HTML5/Javascript Telephony Signaling and Control Protocol Stack for FreeSWITCH
- *
- * The Initial Developer of the Original Code is
- * Anthony Minessale II
- * Portions created by the Initial Developer are Copyright (C)
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Anthony Minessale II
- *
- * jquery.verto.js - Main interface
- *
- */
-
-(function($) {
- var sources = [];
-
- var generateGUID = (typeof(window.crypto) !== 'undefined' && typeof(window.crypto.getRandomValues) !== 'undefined') ?
- function() {
- // If we have a cryptographically secure PRNG, use that
- // http://stackoverflow.com/questions/6906916/collisions-when-generating-uuids-in-javascript
- var buf = new Uint16Array(8);
- window.crypto.getRandomValues(buf);
- var S4 = function(num) {
- var ret = num.toString(16);
- while (ret.length < 4) {
- ret = "0" + ret;
- }
- return ret;
- };
- return (S4(buf[0]) + S4(buf[1]) + "-" + S4(buf[2]) + "-" + S4(buf[3]) + "-" + S4(buf[4]) + "-" + S4(buf[5]) + S4(buf[6]) + S4(buf[7]));
- }
-
- :
-
- function() {
- // Otherwise, just use Math.random
- // http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#2117523
- return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
- var r = Math.random() * 16 | 0,
- v = c == 'x' ? r : (r & 0x3 | 0x8);
- return v.toString(16);
- });
- };
-
- /// MASTER OBJ
- $.verto = function(options, callbacks) {
- var verto = this;
-
- $.verto.saved.push(verto);
-
- verto.options = $.extend({
- login: null,
- passwd: null,
- socketUrl: null,
- tag: null,
- localTag: null,
- videoParams: {},
- audioParams: {},
- loginParams: {},
- deviceParams: {onResCheck: null},
- userVariables: {},
- iceServers: false,
- ringSleep: 6000,
- sessid: null,
- useStream: null
- }, options);
-
- if (verto.options.deviceParams.useCamera) {
- $.FSRTC.getValidRes(verto.options.deviceParams.useCamera, verto.options.deviceParams.onResCheck);
- }
-
- if (!verto.options.deviceParams.useMic) {
- verto.options.deviceParams.useMic = "any";
- }
-
- if (!verto.options.deviceParams.useSpeak) {
- verto.options.deviceParams.useSpeak = "any";
- }
-
- if (verto.options.sessid) {
- verto.sessid = verto.options.sessid;
- } else {
- verto.sessid = localStorage.getItem("verto_session_uuid") || generateGUID();
- localStorage.setItem("verto_session_uuid", verto.sessid);
- }
-
- verto.dialogs = {};
- verto.callbacks = callbacks || {};
- verto.eventSUBS = {};
-
- verto.rpcClient = new $.JsonRpcClient({
- login: verto.options.login,
- passwd: verto.options.passwd,
- socketUrl: verto.options.socketUrl,
- wsFallbackURL: verto.options.wsFallbackURL,
- turnServer: verto.options.turnServer,
- loginParams: verto.options.loginParams,
- userVariables: verto.options.userVariables,
- sessid: verto.sessid,
- onmessage: function(e) {
- return verto.handleMessage(e.eventData);
- },
- onWSConnect: function(o) {
- o.call('login', {});
- },
- onWSLogin: function(success) {
- if (verto.callbacks.onWSLogin) {
- verto.callbacks.onWSLogin(verto, success);
- }
- },
- onWSClose: function(success) {
- if (verto.callbacks.onWSClose) {
- verto.callbacks.onWSClose(verto, success);
- }
- verto.purge();
- }
- });
-
- var tag = verto.options.tag;
- if (typeof(tag) === "function") {
- tag = tag();
- }
-
- if (verto.options.ringFile && verto.options.tag) {
- verto.ringer = $("#" + tag);
- }
-
- verto.rpcClient.call('login', {});
-
- };
-
-
- $.verto.prototype.deviceParams = function(obj) {
- var verto = this;
-
- for (var i in obj) {
- verto.options.deviceParams[i] = obj[i];
- }
-
- if (obj.useCamera) {
- $.FSRTC.getValidRes(verto.options.deviceParams.useCamera, obj ? obj.onResCheck : undefined);
- }
- };
-
- $.verto.prototype.videoParams = function(obj) {
- var verto = this;
-
- for (var i in obj) {
- verto.options.videoParams[i] = obj[i];
- }
- };
-
- $.verto.prototype.iceServers = function(obj) {
- var verto = this;
- verto.options.iceServers = obj;
- };
-
- $.verto.prototype.loginData = function(params) {
- var verto = this;
- verto.options.login = params.login;
- verto.options.passwd = params.passwd;
- verto.rpcClient.loginData(params);
- };
-
- $.verto.prototype.logout = function(msg) {
- var verto = this;
- verto.rpcClient.closeSocket();
- if (verto.callbacks.onWSClose) {
- verto.callbacks.onWSClose(verto, false);
- }
- verto.purge();
- };
-
- $.verto.prototype.login = function(msg) {
- var verto = this;
- verto.logout();
- verto.rpcClient.call('login', {});
- };
-
- $.verto.prototype.message = function(msg) {
- var verto = this;
- var err = 0;
-
- if (!msg.to) {
- console.error("Missing To");
- err++;
- }
-
- if (!msg.body) {
- console.error("Missing Body");
- err++;
- }
-
- if (err) {
- return false;
- }
-
- verto.sendMethod("verto.info", {
- msg: msg
- });
-
- return true;
- };
-
- $.verto.prototype.processReply = function(method, success, e) {
- var verto = this;
- var i;
-
- //console.log("Response: " + method, success, e);
-
- switch (method) {
- case "verto.subscribe":
- for (i in e.unauthorizedChannels) {
- drop_bad(verto, e.unauthorizedChannels[i]);
- }
- for (i in e.subscribedChannels) {
- mark_ready(verto, e.subscribedChannels[i]);
- }
-
- break;
- case "verto.unsubscribe":
- //console.error(e);
- break;
- }
- };
-
- $.verto.prototype.sendMethod = function(method, params) {
- var verto = this;
-
- verto.rpcClient.call(method, params,
-
- function(e) {
- /* Success */
- verto.processReply(method, true, e);
- },
-
- function(e) {
- /* Error */
- verto.processReply(method, false, e);
- });
- };
-
- function do_sub(verto, channel, obj) {
-
- }
-
- function drop_bad(verto, channel) {
- console.error("drop unauthorized channel: " + channel);
- delete verto.eventSUBS[channel];
- }
-
- function mark_ready(verto, channel) {
- for (var j in verto.eventSUBS[channel]) {
- verto.eventSUBS[channel][j].ready = true;
- console.log("subscribed to channel: " + channel);
- if (verto.eventSUBS[channel][j].readyHandler) {
- verto.eventSUBS[channel][j].readyHandler(verto, channel);
- }
- }
- }
-
- var SERNO = 1;
-
- function do_subscribe(verto, channel, subChannels, sparams) {
- var params = sparams || {};
-
- var local = params.local;
-
- var obj = {
- eventChannel: channel,
- userData: params.userData,
- handler: params.handler,
- ready: false,
- readyHandler: params.readyHandler,
- serno: SERNO++
- };
-
- var isnew = false;
-
- if (!verto.eventSUBS[channel]) {
- verto.eventSUBS[channel] = [];
- subChannels.push(channel);
- isnew = true;
- }
-
- verto.eventSUBS[channel].push(obj);
-
- if (local) {
- obj.ready = true;
- obj.local = true;
- }
-
- if (!isnew && verto.eventSUBS[channel][0].ready) {
- obj.ready = true;
- if (obj.readyHandler) {
- obj.readyHandler(verto, channel);
- }
- }
-
- return {
- serno: obj.serno,
- eventChannel: channel
- };
-
- }
-
- $.verto.prototype.subscribe = function(channel, sparams) {
- var verto = this;
- var r = [];
- var subChannels = [];
- var params = sparams || {};
-
- if (typeof(channel) === "string") {
- r.push(do_subscribe(verto, channel, subChannels, params));
- } else {
- for (var i in channel) {
- r.push(do_subscribe(verto, channel, subChannels, params));
- }
- }
-
- if (subChannels.length) {
- verto.sendMethod("verto.subscribe", {
- eventChannel: subChannels.length == 1 ? subChannels[0] : subChannels,
- subParams: params.subParams
- });
- }
-
- return r;
- };
-
- $.verto.prototype.unsubscribe = function(handle) {
- var verto = this;
- var i;
-
- if (!handle) {
- for (i in verto.eventSUBS) {
- if (verto.eventSUBS[i]) {
- verto.unsubscribe(verto.eventSUBS[i]);
- }
- }
- } else {
- var unsubChannels = {};
- var sendChannels = [];
- var channel;
-
- if (typeof(handle) == "string") {
- delete verto.eventSUBS[handle];
- unsubChannels[handle]++;
- } else {
- for (i in handle) {
- if (typeof(handle[i]) == "string") {
- channel = handle[i];
- delete verto.eventSUBS[channel];
- unsubChannels[channel]++;
- } else {
- var repl = [];
- channel = handle[i].eventChannel;
-
- for (var j in verto.eventSUBS[channel]) {
- if (verto.eventSUBS[channel][j].serno == handle[i].serno) {} else {
- repl.push(verto.eventSUBS[channel][j]);
- }
- }
-
- verto.eventSUBS[channel] = repl;
-
- if (verto.eventSUBS[channel].length === 0) {
- delete verto.eventSUBS[channel];
- unsubChannels[channel]++;
- }
- }
- }
- }
-
- for (var u in unsubChannels) {
- console.log("Sending Unsubscribe for: ", u);
- sendChannels.push(u);
- }
-
- if (sendChannels.length) {
- verto.sendMethod("verto.unsubscribe", {
- eventChannel: sendChannels.length == 1 ? sendChannels[0] : sendChannels
- });
- }
- }
- };
-
- $.verto.prototype.broadcast = function(channel, params) {
- var verto = this;
- var msg = {
- eventChannel: channel,
- data: {}
- };
- for (var i in params) {
- msg.data[i] = params[i];
- }
- verto.sendMethod("verto.broadcast", msg);
- };
-
- $.verto.prototype.purge = function(callID) {
- var verto = this;
- var x = 0;
- var i;
-
- for (i in verto.dialogs) {
- if (!x) {
- console.log("purging dialogs");
- }
- x++;
- verto.dialogs[i].setState($.verto.enum.state.purge);
- }
-
- for (i in verto.eventSUBS) {
- if (verto.eventSUBS[i]) {
- console.log("purging subscription: " + i);
- delete verto.eventSUBS[i];
- }
- }
- };
-
- $.verto.prototype.hangup = function(callID) {
- var verto = this;
- if (callID) {
- var dialog = verto.dialogs[callID];
-
- if (dialog) {
- dialog.hangup();
- }
- } else {
- for (var i in verto.dialogs) {
- verto.dialogs[i].hangup();
- }
- }
- };
-
- $.verto.prototype.newCall = function(args, callbacks) {
- var verto = this;
-
- if (!verto.rpcClient.socketReady()) {
- console.error("Not Connected...");
- return;
- }
-
- if (args["useCamera"]) {
- verto.options.deviceParams["useCamera"] = args["useCamera"];
- }
-
- var dialog = new $.verto.dialog($.verto.enum.direction.outbound, this, args);
-
- if (callbacks) {
- dialog.callbacks = callbacks;
- }
-
- dialog.invite();
-
- return dialog;
- };
-
- $.verto.prototype.handleMessage = function(data) {
- var verto = this;
-
- if (!(data && data.method)) {
- console.error("Invalid Data", data);
- return;
- }
-
- if (data.params.callID) {
- var dialog = verto.dialogs[data.params.callID];
-
- if (data.method === "verto.attach" && dialog) {
- delete dialog.verto.dialogs[dialog.callID];
- dialog.rtc.stop();
- dialog = null;
- }
-
- if (dialog) {
-
- switch (data.method) {
- case 'verto.bye':
- dialog.hangup(data.params);
- break;
- case 'verto.answer':
- dialog.handleAnswer(data.params);
- break;
- case 'verto.media':
- dialog.handleMedia(data.params);
- break;
- case 'verto.display':
- dialog.handleDisplay(data.params);
- break;
- case 'verto.info':
- dialog.handleInfo(data.params);
- break;
- default:
- console.debug("INVALID METHOD OR NON-EXISTANT CALL REFERENCE IGNORED", dialog, data.method);
- break;
- }
- } else {
-
- switch (data.method) {
- case 'verto.attach':
- data.params.attach = true;
-
- if (data.params.sdp && data.params.sdp.indexOf("m=video") > 0) {
- data.params.useVideo = true;
- }
-
- if (data.params.sdp && data.params.sdp.indexOf("stereo=1") > 0) {
- data.params.useStereo = true;
- }
-
- dialog = new $.verto.dialog($.verto.enum.direction.inbound, verto, data.params);
- dialog.setState($.verto.enum.state.recovering);
-
- break;
- case 'verto.invite':
-
- if (data.params.sdp && data.params.sdp.indexOf("m=video") > 0) {
- data.params.wantVideo = true;
- }
-
- if (data.params.sdp && data.params.sdp.indexOf("stereo=1") > 0) {
- data.params.useStereo = true;
- }
-
- dialog = new $.verto.dialog($.verto.enum.direction.inbound, verto, data.params);
- break;
- default:
- console.debug("INVALID METHOD OR NON-EXISTANT CALL REFERENCE IGNORED");
- break;
- }
- }
-
- return {
- method: data.method
- };
- } else {
- switch (data.method) {
- case 'verto.punt':
- verto.purge();
- verto.logout();
- break;
- case 'verto.event':
- var list = null;
- var key = null;
-
- if (data.params) {
- key = data.params.eventChannel;
- }
-
- if (key) {
- list = verto.eventSUBS[key];
-
- if (!list) {
- list = verto.eventSUBS[key.split(".")[0]];
- }
- }
-
- if (!list && key && key === verto.sessid) {
- if (verto.callbacks.onMessage) {
- verto.callbacks.onMessage(verto, null, $.verto.enum.message.pvtEvent, data.params);
- }
- } else if (!list && key && verto.dialogs[key]) {
- verto.dialogs[key].sendMessage($.verto.enum.message.pvtEvent, data.params);
- } else if (!list) {
- if (!key) {
- key = "UNDEFINED";
- }
- console.error("UNSUBBED or invalid EVENT " + key + " IGNORED");
- } else {
- for (var i in list) {
- var sub = list[i];
-
- if (!sub || !sub.ready) {
- console.error("invalid EVENT for " + key + " IGNORED");
- } else if (sub.handler) {
- sub.handler(verto, data.params, sub.userData);
- } else if (verto.callbacks.onEvent) {
- verto.callbacks.onEvent(verto, data.params, sub.userData);
- } else {
- console.log("EVENT:", data.params);
- }
- }
- }
-
- break;
-
- case "verto.info":
- if (verto.callbacks.onMessage) {
- verto.callbacks.onMessage(verto, null, $.verto.enum.message.info, data.params.msg);
- }
- //console.error(data);
- console.debug("MESSAGE from: " + data.params.msg.from, data.params.msg.body);
-
- break;
-
- case 'verto.clientReady':
- if (verto.callbacks.onMessage) {
- verto.callbacks.onMessage(verto, null, $.verto.enum.message.clientReady, data.params);
- }
- console.debug("CLIENT READY", data.params);
- break;
-
- default:
- console.error("INVALID METHOD OR NON-EXISTANT CALL REFERENCE IGNORED", data.method);
- break;
- }
- }
- };
-
- var del_array = function(array, name) {
- var r = [];
- var len = array.length;
-
- for (var i = 0; i < len; i++) {
- if (array[i] != name) {
- r.push(array[i]);
- }
- }
-
- return r;
- };
-
- var hashArray = function() {
- var vha = this;
-
- var hash = {};
- var array = [];
-
- vha.reorder = function(a) {
- array = a;
- var h = hash;
- hash = {};
-
- var len = array.length;
-
- for (var i = 0; i < len; i++) {
- var key = array[i];
- if (h[key]) {
- hash[key] = h[key];
- delete h[key];
- }
- }
- h = undefined;
- };
-
- vha.clear = function() {
- hash = undefined;
- array = undefined;
- hash = {};
- array = [];
- };
-
- vha.add = function(name, val, insertAt) {
- var redraw = false;
-
- if (!hash[name]) {
- if (insertAt === undefined || insertAt < 0 || insertAt >= array.length) {
- array.push(name);
- } else {
- var x = 0;
- var n = [];
- var len = array.length;
-
- for (var i = 0; i < len; i++) {
- if (x++==insertAt) {
- n.push(name);
- }
- n.push(array[i]);
- }
-
- array = undefined;
- array = n;
- n = undefined;
- redraw = true;
- }
- }
-
- hash[name] = val;
-
- return redraw;
- };
-
- vha.del = function(name) {
- var r = false;
-
- if (hash[name]) {
- array = del_array(array, name);
- delete hash[name];
- r = true;
- } else {
- console.error("can't del nonexistant key " + name);
- }
-
- return r;
- };
-
- vha.get = function(name) {
- return hash[name];
- };
-
- vha.order = function() {
- return array;
- };
-
- vha.hash = function() {
- return hash;
- };
-
- vha.indexOf = function(name) {
- var len = array.length;
-
- for (var i = 0; i < len; i++) {
- if (array[i] == name) {
- return i;
- }
- }
- };
-
- vha.arrayLen = function() {
- return array.length;
- };
-
- vha.asArray = function() {
- var r = [];
-
- var len = array.length;
-
- for (var i = 0; i < len; i++) {
- var key = array[i];
- r.push(hash[key]);
- }
-
- return r;
- };
-
- vha.each = function(cb) {
- var len = array.length;
-
- for (var i = 0; i < len; i++) {
- cb(array[i], hash[array[i]]);
- }
- };
-
- vha.dump = function(html) {
- var str = "";
-
- vha.each(function(name, val) {
- str += "name: " + name + " val: " + JSON.stringify(val) + (html ? " " : "\n");
- });
-
- return str;
- };
-
- };
-
- $.verto.liveArray = function(verto, context, name, config) {
- var la = this;
- var lastSerno = 0;
- var binding = null;
- var user_obj = config.userObj;
- var local = false;
-
- // Inherit methods of hashArray
- hashArray.call(la);
-
- // Save the hashArray add, del, reorder, clear methods so we can make our own.
- la._add = la.add;
- la._del = la.del;
- la._reorder = la.reorder;
- la._clear = la.clear;
-
- la.context = context;
- la.name = name;
- la.user_obj = user_obj;
-
- la.verto = verto;
- la.broadcast = function(channel, obj) {
- verto.broadcast(channel, obj);
- };
- la.errs = 0;
-
- la.clear = function() {
- la._clear();
- lastSerno = 0;
-
- if (la.onChange) {
- la.onChange(la, {
- action: "clear"
- });
- }
- };
-
- la.checkSerno = function(serno) {
- if (serno < 0) {
- return true;
- }
-
- if (lastSerno > 0 && serno != (lastSerno + 1)) {
- if (la.onErr) {
- la.onErr(la, {
- lastSerno: lastSerno,
- serno: serno
- });
- }
- la.errs++;
- console.debug(la.errs);
- if (la.errs < 3) {
- la.bootstrap(la.user_obj);
- }
- return false;
- } else {
- lastSerno = serno;
- return true;
- }
- };
-
- la.reorder = function(serno, a) {
- if (la.checkSerno(serno)) {
- la._reorder(a);
- if (la.onChange) {
- la.onChange(la, {
- serno: serno,
- action: "reorder"
- });
- }
- }
- };
-
- la.init = function(serno, val, key, index) {
- if (key === null || key === undefined) {
- key = serno;
- }
- if (la.checkSerno(serno)) {
- if (la.onChange) {
- la.onChange(la, {
- serno: serno,
- action: "init",
- index: index,
- key: key,
- data: val
- });
- }
- }
- };
-
- la.bootObj = function(serno, val) {
- if (la.checkSerno(serno)) {
-
- //la.clear();
- for (var i in val) {
- la._add(val[i][0], val[i][1]);
- }
-
- if (la.onChange) {
- la.onChange(la, {
- serno: serno,
- action: "bootObj",
- data: val,
- redraw: true
- });
- }
- }
- };
-
- // @param serno La is the serial number for la particular request.
- // @param key If looking at it as a hash table, la represents the key in the hashArray object where you want to store the val object.
- // @param index If looking at it as an array, la represents the position in the array where you want to store the val object.
- // @param val La is the object you want to store at the key or index location in the hash table / array.
- la.add = function(serno, val, key, index) {
- if (key === null || key === undefined) {
- key = serno;
- }
- if (la.checkSerno(serno)) {
- var redraw = la._add(key, val, index);
- if (la.onChange) {
- la.onChange(la, {
- serno: serno,
- action: "add",
- index: index,
- key: key,
- data: val,
- redraw: redraw
- });
- }
- }
- };
-
- la.modify = function(serno, val, key, index) {
- if (key === null || key === undefined) {
- key = serno;
- }
- if (la.checkSerno(serno)) {
- la._add(key, val, index);
- if (la.onChange) {
- la.onChange(la, {
- serno: serno,
- action: "modify",
- key: key,
- data: val,
- index: index
- });
- }
- }
- };
-
- la.del = function(serno, key, index) {
- if (key === null || key === undefined) {
- key = serno;
- }
- if (la.checkSerno(serno)) {
- if (index === null || index < 0 || index === undefined) {
- index = la.indexOf(key);
- }
- var ok = la._del(key);
-
- if (ok && la.onChange) {
- la.onChange(la, {
- serno: serno,
- action: "del",
- key: key,
- index: index
- });
- }
- }
- };
-
- var eventHandler = function(v, e, la) {
- var packet = e.data;
-
- //console.error("READ:", packet);
-
- if (packet.name != la.name) {
- return;
- }
-
- switch (packet.action) {
-
- case "init":
- la.init(packet.wireSerno, packet.data, packet.hashKey, packet.arrIndex);
- break;
-
- case "bootObj":
- la.bootObj(packet.wireSerno, packet.data);
- break;
- case "add":
- la.add(packet.wireSerno, packet.data, packet.hashKey, packet.arrIndex);
- break;
-
- case "modify":
- if (! (packet.arrIndex || packet.hashKey)) {
- console.error("Invalid Packet", packet);
- } else {
- la.modify(packet.wireSerno, packet.data, packet.hashKey, packet.arrIndex);
- }
- break;
- case "del":
- if (! (packet.arrIndex || packet.hashKey)) {
- console.error("Invalid Packet", packet);
- } else {
- la.del(packet.wireSerno, packet.hashKey, packet.arrIndex);
- }
- break;
-
- case "clear":
- la.clear();
- break;
-
- case "reorder":
- la.reorder(packet.wireSerno, packet.order);
- break;
-
- default:
- if (la.checkSerno(packet.wireSerno)) {
- if (la.onChange) {
- la.onChange(la, {
- serno: packet.wireSerno,
- action: packet.action,
- data: packet.data
- });
- }
- }
- break;
- }
- };
-
- if (la.context) {
- binding = la.verto.subscribe(la.context, {
- handler: eventHandler,
- userData: la,
- subParams: config.subParams
- });
- }
-
- la.destroy = function() {
- la._clear();
- la.verto.unsubscribe(binding);
- };
-
- la.sendCommand = function(cmd, obj) {
- var self = la;
- self.broadcast(self.context, {
- liveArray: {
- command: cmd,
- context: self.context,
- name: self.name,
- obj: obj
- }
- });
- };
-
- la.bootstrap = function(obj) {
- var self = la;
- la.sendCommand("bootstrap", obj);
- //self.heartbeat();
- };
-
- la.changepage = function(obj) {
- var self = la;
- self.clear();
- self.broadcast(self.context, {
- liveArray: {
- command: "changepage",
- context: la.context,
- name: la.name,
- obj: obj
- }
- });
- };
-
- la.heartbeat = function(obj) {
- var self = la;
-
- var callback = function() {
- self.heartbeat.call(self, obj);
- };
- self.broadcast(self.context, {
- liveArray: {
- command: "heartbeat",
- context: self.context,
- name: self.name,
- obj: obj
- }
- });
- self.hb_pid = setTimeout(callback, 30000);
- };
-
- la.bootstrap(la.user_obj);
- };
-
- $.verto.liveTable = function(verto, context, name, jq, config) {
- var dt;
- var la = new $.verto.liveArray(verto, context, name, {
- subParams: config.subParams
- });
- var lt = this;
-
- lt.liveArray = la;
- lt.dataTable = dt;
- lt.verto = verto;
-
- lt.destroy = function() {
- if (dt) {
- dt.fnDestroy();
- }
- if (la) {
- la.destroy();
- }
-
- dt = null;
- la = null;
- };
-
- la.onErr = function(obj, args) {
- console.error("Error: ", obj, args);
- };
-
- /* back compat so jsonstatus can always be enabled */
- function genRow(data) {
- if (typeof(data[4]) === "string" && data[4].indexOf("{") > -1) {
- var tmp = $.parseJSON(data[4]);
- data[4] = tmp.oldStatus;
- data[5] = null;
- }
- return data;
- }
-
- function genArray(obj) {
- var data = obj.asArray();
-
- for (var i in data) {
- data[i] = genRow(data[i]);
- }
-
- return data;
- }
-
-
- la.onChange = function(obj, args) {
- var index = 0;
- var iserr = 0;
-
- if (!dt) {
- if (!config.aoColumns) {
- if (args.action != "init") {
- return;
- }
-
- config.aoColumns = [];
-
- for (var i in args.data) {
- config.aoColumns.push({
- "sTitle": args.data[i]
- });
- }
- }
-
- dt = jq.dataTable(config);
- }
-
- if (dt && (args.action == "del" || args.action == "modify")) {
- index = args.index;
-
- if (index === undefined && args.key) {
- index = la.indexOf(args.key);
- }
-
- if (index === undefined) {
- console.error("INVALID PACKET Missing INDEX\n", args);
- return;
- }
- }
-
- if (config.onChange) {
- config.onChange(obj, args);
- }
-
- try {
- switch (args.action) {
- case "bootObj":
- if (!args.data) {
- console.error("missing data");
- return;
- }
- dt.fnClearTable();
- dt.fnAddData(genArray(obj));
- dt.fnAdjustColumnSizing();
- break;
- case "add":
- if (!args.data) {
- console.error("missing data");
- return;
- }
- if (args.redraw > -1) {
- // specific position, more costly
- dt.fnClearTable();
- dt.fnAddData(genArray(obj));
- } else {
- dt.fnAddData(genRow(args.data));
- }
- dt.fnAdjustColumnSizing();
- break;
- case "modify":
- if (!args.data) {
- return;
- }
- //console.debug(args, index);
- dt.fnUpdate(genRow(args.data), index);
- dt.fnAdjustColumnSizing();
- break;
- case "del":
- dt.fnDeleteRow(index);
- dt.fnAdjustColumnSizing();
- break;
- case "clear":
- dt.fnClearTable();
- break;
- case "reorder":
- // specific position, more costly
- dt.fnClearTable();
- dt.fnAddData(genArray(obj));
- break;
- case "hide":
- jq.hide();
- break;
-
- case "show":
- jq.show();
- break;
-
- }
- } catch(err) {
- console.error("ERROR: " + err);
- iserr++;
- }
-
- if (iserr) {
- obj.errs++;
- if (obj.errs < 3) {
- obj.bootstrap(obj.user_obj);
- }
- } else {
- obj.errs = 0;
- }
-
- };
-
- la.onChange(la, {
- action: "init"
- });
-
- };
-
- var CONFMAN_SERNO = 1;
-
- /*
- Conference Manager without jQuery table.
- */
-
- $.verto.conf = function(verto, params) {
- var conf = this;
-
- conf.params = $.extend({
- dialog: null,
- hasVid: false,
- laData: null,
- onBroadcast: null,
- onLaChange: null,
- onLaRow: null
- }, params);
-
- conf.verto = verto;
- conf.serno = CONFMAN_SERNO++;
-
- createMainModeratorMethods();
-
- verto.subscribe(conf.params.laData.modChannel, {
- handler: function(v, e) {
- if (conf.params.onBroadcast) {
- conf.params.onBroadcast(verto, conf, e.data);
- }
- }
- });
-
- verto.subscribe(conf.params.laData.infoChannel, {
- handler: function(v, e) {
- if (typeof(conf.params.infoCallback) === "function") {
- conf.params.infoCallback(v,e);
- }
- }
- });
-
- verto.subscribe(conf.params.laData.chatChannel, {
- handler: function(v, e) {
- if (typeof(conf.params.chatCallback) === "function") {
- conf.params.chatCallback(v,e);
- }
- }
- });
- };
-
- $.verto.conf.prototype.modCommand = function(cmd, id, value) {
- var conf = this;
-
- conf.verto.rpcClient.call("verto.broadcast", {
- "eventChannel": conf.params.laData.modChannel,
- "data": {
- "application": "conf-control",
- "command": cmd,
- "id": id,
- "value": value
- }
- });
- };
-
- $.verto.conf.prototype.destroy = function() {
- var conf = this;
-
- conf.destroyed = true;
- conf.params.onBroadcast(conf.verto, conf, 'destroy');
-
- if (conf.params.laData.modChannel) {
- conf.verto.unsubscribe(conf.params.laData.modChannel);
- }
-
- if (conf.params.laData.chatChannel) {
- conf.verto.unsubscribe(conf.params.laData.chatChannel);
- }
-
- if (conf.params.laData.infoChannel) {
- conf.verto.unsubscribe(conf.params.laData.infoChannel);
- }
- };
-
- function createMainModeratorMethods() {
- $.verto.conf.prototype.listVideoLayouts = function() {
- this.modCommand("list-videoLayouts", null, null);
- };
-
- $.verto.conf.prototype.play = function(file) {
- this.modCommand("play", null, file);
- };
-
- $.verto.conf.prototype.stop = function() {
- this.modCommand("stop", null, "all");
- };
-
- $.verto.conf.prototype.deaf = function(memberID) {
- this.modCommand("deaf", parseInt(memberID));
- };
-
- $.verto.conf.prototype.undeaf = function(memberID) {
- this.modCommand("undeaf", parseInt(memberID));
- };
-
- $.verto.conf.prototype.record = function(file) {
- this.modCommand("recording", null, ["start", file]);
- };
-
- $.verto.conf.prototype.stopRecord = function() {
- this.modCommand("recording", null, ["stop", "all"]);
- };
-
- $.verto.conf.prototype.snapshot = function(file) {
- if (!this.params.hasVid) {
- throw 'Conference has no video';
- }
- this.modCommand("vid-write-png", null, file);
- };
-
- $.verto.conf.prototype.setVideoLayout = function(layout, canvasID) {
- if (!this.params.hasVid) {
- throw 'Conference has no video';
- }
- if (canvasID) {
- this.modCommand("vid-layout", null, [layout, canvasID]);
- } else {
- this.modCommand("vid-layout", null, layout);
- }
- };
-
- $.verto.conf.prototype.kick = function(memberID) {
- this.modCommand("kick", parseInt(memberID));
- };
-
- $.verto.conf.prototype.muteMic = function(memberID) {
- this.modCommand("tmute", parseInt(memberID));
- };
-
- $.verto.conf.prototype.muteVideo = function(memberID) {
- if (!this.params.hasVid) {
- throw 'Conference has no video';
- }
- this.modCommand("tvmute", parseInt(memberID));
- };
-
- $.verto.conf.prototype.presenter = function(memberID) {
- if (!this.params.hasVid) {
- throw 'Conference has no video';
- }
- this.modCommand("vid-res-id", parseInt(memberID), "presenter");
- };
-
- $.verto.conf.prototype.videoFloor = function(memberID) {
- if (!this.params.hasVid) {
- throw 'Conference has no video';
- }
- this.modCommand("vid-floor", parseInt(memberID), "force");
- };
-
- $.verto.conf.prototype.banner = function(memberID, text) {
- if (!this.params.hasVid) {
- throw 'Conference has no video';
- }
- this.modCommand("vid-banner", parseInt(memberID), escape(text));
- };
-
- $.verto.conf.prototype.volumeDown = function(memberID) {
- this.modCommand("volume_out", parseInt(memberID), "down");
- };
-
- $.verto.conf.prototype.volumeUp = function(memberID) {
- this.modCommand("volume_out", parseInt(memberID), "up");
- };
-
- $.verto.conf.prototype.gainDown = function(memberID) {
- this.modCommand("volume_in", parseInt(memberID), "down");
- };
-
- $.verto.conf.prototype.gainUp = function(memberID) {
- this.modCommand("volume_in", parseInt(memberID), "up");
- };
-
- $.verto.conf.prototype.transfer = function(memberID, exten) {
- this.modCommand("transfer", parseInt(memberID), exten);
- };
-
- $.verto.conf.prototype.sendChat = function(message, type) {
- var conf = this;
- conf.verto.rpcClient.call("verto.broadcast", {
- "eventChannel": conf.params.laData.chatChannel,
- "data": {
- "action": "send",
- "message": message,
- "type": type
- }
- });
- };
-
- }
-
- $.verto.modfuncs = {};
-
- $.verto.confMan = function(verto, params) {
- var confMan = this;
-
- confMan.params = $.extend({
- tableID: null,
- statusID: null,
- mainModID: null,
- dialog: null,
- hasVid: false,
- laData: null,
- onBroadcast: null,
- onLaChange: null,
- onLaRow: null
- }, params);
-
- confMan.verto = verto;
- confMan.serno = CONFMAN_SERNO++;
- confMan.canvasCount = confMan.params.laData.canvasCount;
-
- function genMainMod(jq) {
- var play_id = "play_" + confMan.serno;
- var stop_id = "stop_" + confMan.serno;
- var recording_id = "recording_" + confMan.serno;
- var snapshot_id = "snapshot_" + confMan.serno;
- var rec_stop_id = "recording_stop" + confMan.serno;
- var div_id = "confman_" + confMan.serno;
-
- var html = " " +
- "Play " +
- "Stop " +
- "Record " +
- "Record Stop " +
- (confMan.params.hasVid ? "PNG Snapshot " : "") +
- "
";
-
- jq.html(html);
-
- $.verto.modfuncs.change_video_layout = function(id, canvas_id) {
- var val = $("#" + id + " option:selected").text();
- if (val !== "none") {
- confMan.modCommand("vid-layout", null, [val, canvas_id]);
- }
- };
-
- if (confMan.params.hasVid) {
- for (var j = 0; j < confMan.canvasCount; j++) {
- var vlayout_id = "confman_vid_layout_" + j + "_" + confMan.serno;
- var vlselect_id = "confman_vl_select_" + j + "_" + confMan.serno;
-
-
- var vlhtml = " " +
- "Video Layout Canvas " + (j+1) +
- " " +
- "
";
- jq.append(vlhtml);
- }
-
- $("#" + snapshot_id).click(function() {
- var file = prompt("Please enter file name", "");
- if (file) {
- confMan.modCommand("vid-write-png", null, file);
- }
- });
- }
-
- $("#" + play_id).click(function() {
- var file = prompt("Please enter file name", "");
- if (file) {
- confMan.modCommand("play", null, file);
- }
- });
-
- $("#" + stop_id).click(function() {
- confMan.modCommand("stop", null, "all");
- });
-
- $("#" + recording_id).click(function() {
- var file = prompt("Please enter file name", "");
- if (file) {
- confMan.modCommand("recording", null, ["start", file]);
- }
- });
-
- $("#" + rec_stop_id).click(function() {
- confMan.modCommand("recording", null, ["stop", "all"]);
- });
-
- }
-
- function genControls(jq, rowid) {
- var x = parseInt(rowid);
- var kick_id = "kick_" + x;
- var canvas_in_next_id = "canvas_in_next_" + x;
- var canvas_in_prev_id = "canvas_in_prev_" + x;
- var canvas_out_next_id = "canvas_out_next_" + x;
- var canvas_out_prev_id = "canvas_out_prev_" + x;
-
- var canvas_in_set_id = "canvas_in_set_" + x;
- var canvas_out_set_id = "canvas_out_set_" + x;
-
- var layer_set_id = "layer_set_" + x;
- var layer_next_id = "layer_next_" + x;
- var layer_prev_id = "layer_prev_" + x;
-
- var tmute_id = "tmute_" + x;
- var tvmute_id = "tvmute_" + x;
- var vbanner_id = "vbanner_" + x;
- var tvpresenter_id = "tvpresenter_" + x;
- var tvfloor_id = "tvfloor_" + x;
- var box_id = "box_" + x;
- var gainup_id = "gain_in_up" + x;
- var gaindn_id = "gain_in_dn" + x;
- var volup_id = "vol_in_up" + x;
- var voldn_id = "vol_in_dn" + x;
- var transfer_id = "transfer" + x;
-
-
- var html = "";
-
- html += "General Controls
";
-
- html += "Kick " +
- "Mute " +
- "Gain - " +
- "Gain + " +
- "Vol - " +
- "Vol + " +
- "Transfer ";
-
- if (confMan.params.hasVid) {
- html += "Video Controls ";
-
-
- html += "VMute " +
- "Presenter " +
- "Vid Floor " +
- "Banner ";
-
- if (confMan.canvasCount > 1) {
- html += "Canvas Controls " +
- "Set Input Canvas " +
- "Prev Input Canvas " +
- "Next Input Canvas " +
-
- " " +
-
- "Set Watching Canvas " +
- "Prev Watching Canvas " +
- "Next Watching Canvas ";
- }
-
- html += " " +
-
- "Set Layer " +
- "Prev Layer " +
- "Next Layer " +
-
-
-
- "";
- }
-
- jq.html(html);
-
-
- if (!jq.data("mouse")) {
- $("#" + box_id).hide();
- }
-
- jq.mouseover(function(e) {
- jq.data({"mouse": true});
- $("#" + box_id).show();
- });
-
- jq.mouseout(function(e) {
- jq.data({"mouse": false});
- $("#" + box_id).hide();
- });
-
- $("#" + transfer_id).click(function() {
- var xten = prompt("Enter Extension");
- if (xten) {
- confMan.modCommand("transfer", x, xten);
- }
- });
-
- $("#" + kick_id).click(function() {
- confMan.modCommand("kick", x);
- });
-
-
- $("#" + layer_set_id).click(function() {
- var cid = prompt("Please enter layer ID", "");
- if (cid) {
- confMan.modCommand("vid-layer", x, cid);
- }
- });
-
- $("#" + layer_next_id).click(function() {
- confMan.modCommand("vid-layer", x, "next");
- });
- $("#" + layer_prev_id).click(function() {
- confMan.modCommand("vid-layer", x, "prev");
- });
-
- $("#" + canvas_in_set_id).click(function() {
- var cid = prompt("Please enter canvas ID", "");
- if (cid) {
- confMan.modCommand("vid-canvas", x, cid);
- }
- });
-
- $("#" + canvas_out_set_id).click(function() {
- var cid = prompt("Please enter canvas ID", "");
- if (cid) {
- confMan.modCommand("vid-watching-canvas", x, cid);
- }
- });
-
- $("#" + canvas_in_next_id).click(function() {
- confMan.modCommand("vid-canvas", x, "next");
- });
- $("#" + canvas_in_prev_id).click(function() {
- confMan.modCommand("vid-canvas", x, "prev");
- });
-
-
- $("#" + canvas_out_next_id).click(function() {
- confMan.modCommand("vid-watching-canvas", x, "next");
- });
- $("#" + canvas_out_prev_id).click(function() {
- confMan.modCommand("vid-watching-canvas", x, "prev");
- });
-
- $("#" + tmute_id).click(function() {
- confMan.modCommand("tmute", x);
- });
-
- if (confMan.params.hasVid) {
- $("#" + tvmute_id).click(function() {
- confMan.modCommand("tvmute", x);
- });
- $("#" + tvpresenter_id).click(function() {
- confMan.modCommand("vid-res-id", x, "presenter");
- });
- $("#" + tvfloor_id).click(function() {
- confMan.modCommand("vid-floor", x, "force");
- });
- $("#" + vbanner_id).click(function() {
- var text = prompt("Please enter text", "");
- if (text) {
- confMan.modCommand("vid-banner", x, escape(text));
- }
- });
- }
-
- $("#" + gainup_id).click(function() {
- confMan.modCommand("volume_in", x, "up");
- });
-
- $("#" + gaindn_id).click(function() {
- confMan.modCommand("volume_in", x, "down");
- });
-
- $("#" + volup_id).click(function() {
- confMan.modCommand("volume_out", x, "up");
- });
-
- $("#" + voldn_id).click(function() {
- confMan.modCommand("volume_out", x, "down");
- });
-
- return html;
- }
-
- var atitle = "";
- var awidth = 0;
-
- //$(".jsDataTable").width(confMan.params.hasVid ? "900px" : "800px");
-
- verto.subscribe(confMan.params.laData.infoChannel, {
- handler: function(v, e) {
- if (typeof(confMan.params.infoCallback) === "function") {
- confMan.params.infoCallback(v,e);
- }
- }
- });
-
- verto.subscribe(confMan.params.laData.chatChannel, {
- handler: function(v, e) {
- if (typeof(confMan.params.chatCallback) === "function") {
- confMan.params.chatCallback(v,e);
- }
- }
- });
-
- if (confMan.params.laData.role === "moderator") {
- atitle = "Action";
- awidth = 600;
-
- if (confMan.params.mainModID) {
- genMainMod($(confMan.params.mainModID));
- $(confMan.params.displayID).html("Moderator Controls Ready ");
- } else {
- $(confMan.params.mainModID).html("");
- }
-
- verto.subscribe(confMan.params.laData.modChannel, {
- handler: function(v, e) {
- //console.error("MODDATA:", e.data);
- if (confMan.params.onBroadcast) {
- confMan.params.onBroadcast(verto, confMan, e.data);
- }
-
- if (e.data["conf-command"] === "list-videoLayouts") {
- for (var j = 0; j < confMan.canvasCount; j++) {
- var vlselect_id = "#confman_vl_select_" + j + "_" + confMan.serno;
- var vlayout_id = "#confman_vid_layout_" + j + "_" + confMan.serno;
-
- var x = 0;
- var options;
-
- $(vlselect_id).selectmenu({});
- $(vlselect_id).selectmenu("enable");
- $(vlselect_id).empty();
-
- $(vlselect_id).append(new Option("Choose a Layout", "none"));
-
- if (e.data.responseData) {
- var rdata = [];
-
- for (var i in e.data.responseData) {
- rdata.push(e.data.responseData[i].name);
- }
-
- options = rdata.sort(function(a, b) {
- var ga = a.substring(0, 6) == "group:" ? true : false;
- var gb = b.substring(0, 6) == "group:" ? true : false;
-
- if ((ga || gb) && ga != gb) {
- return ga ? -1 : 1;
- }
-
- return ( ( a == b ) ? 0 : ( ( a > b ) ? 1 : -1 ) );
- });
-
- for (var i in options) {
- $(vlselect_id).append(new Option(options[i], options[i]));
- x++;
- }
- }
-
- if (x) {
- $(vlselect_id).selectmenu('refresh', true);
- } else {
- $(vlayout_id).hide();
- }
- }
- } else {
-
- if (!confMan.destroyed && confMan.params.displayID) {
- $(confMan.params.displayID).html(e.data.response + " ");
- if (confMan.lastTimeout) {
- clearTimeout(confMan.lastTimeout);
- confMan.lastTimeout = 0;
- }
- confMan.lastTimeout = setTimeout(function() { $(confMan.params.displayID).html(confMan.destroyed ? "" : "Moderator Controls Ready ");}, 4000);
- }
- }
- }
- });
-
-
- if (confMan.params.hasVid) {
- confMan.modCommand("list-videoLayouts", null, null);
- }
- }
-
- var row_callback = null;
-
- if (confMan.params.laData.role === "moderator") {
- row_callback = function(nRow, aData, iDisplayIndex, iDisplayIndexFull) {
- if (!aData[5]) {
- var $row = $('td:eq(5)', nRow);
- genControls($row, aData);
-
- if (confMan.params.onLaRow) {
- confMan.params.onLaRow(verto, confMan, $row, aData);
- }
- }
- };
- }
-
- confMan.lt = new $.verto.liveTable(verto, confMan.params.laData.laChannel, confMan.params.laData.laName, $(confMan.params.tableID), {
- subParams: {
- callID: confMan.params.dialog ? confMan.params.dialog.callID : null
- },
-
- "onChange": function(obj, args) {
- $(confMan.params.statusID).text("Conference Members: " + " (" + obj.arrayLen() + " Total)");
- if (confMan.params.onLaChange) {
- confMan.params.onLaChange(verto, confMan, $.verto.enum.confEvent.laChange, obj, args);
- }
- },
-
- "aaData": [],
- "aoColumns": [
- {
- "sTitle": "ID",
- "sWidth": "50"
- },
- {
- "sTitle": "Number",
- "sWidth": "250"
- },
- {
- "sTitle": "Name",
- "sWidth": "250"
- },
- {
- "sTitle": "Codec",
- "sWidth": "100"
- },
- {
- "sTitle": "Status",
- "sWidth": confMan.params.hasVid ? "200px" : "150px"
- },
- {
- "sTitle": atitle,
- "sWidth": awidth,
- }
- ],
- "bAutoWidth": true,
- "bDestroy": true,
- "bSort": false,
- "bInfo": false,
- "bFilter": false,
- "bLengthChange": false,
- "bPaginate": false,
- "iDisplayLength": 1400,
-
- "oLanguage": {
- "sEmptyTable": "The Conference is Empty....."
- },
-
- "fnRowCallback": row_callback
-
- });
- };
-
- $.verto.confMan.prototype.modCommand = function(cmd, id, value) {
- var confMan = this;
-
- confMan.verto.rpcClient.call("verto.broadcast", {
- "eventChannel": confMan.params.laData.modChannel,
- "data": {
- "application": "conf-control",
- "command": cmd,
- "id": id,
- "value": value
- }
- });
- };
-
- $.verto.confMan.prototype.sendChat = function(message, type) {
- var confMan = this;
- confMan.verto.rpcClient.call("verto.broadcast", {
- "eventChannel": confMan.params.laData.chatChannel,
- "data": {
- "action": "send",
- "message": message,
- "type": type
- }
- });
- };
-
-
- $.verto.confMan.prototype.destroy = function() {
- var confMan = this;
-
- confMan.destroyed = true;
-
- if (confMan.lt) {
- confMan.lt.destroy();
- }
-
- if (confMan.params.laData.chatChannel) {
- confMan.verto.unsubscribe(confMan.params.laData.chatChannel);
- }
-
- if (confMan.params.laData.modChannel) {
- confMan.verto.unsubscribe(confMan.params.laData.modChannel);
- }
-
- if (confMan.params.mainModID) {
- $(confMan.params.mainModID).html("");
- }
- };
-
- $.verto.dialog = function(direction, verto, params) {
- var dialog = this;
-
- dialog.params = $.extend({
- useVideo: verto.options.useVideo,
- useStereo: verto.options.useStereo,
- screenShare: false,
- useCamera: false,
- useMic: verto.options.deviceParams.useMic,
- useSpeak: verto.options.deviceParams.useSpeak,
- tag: verto.options.tag,
- localTag: verto.options.localTag,
- login: verto.options.login,
- videoParams: verto.options.videoParams,
- useStream: verto.options.useStream,
- }, params);
-
-
- if (!dialog.params.screenShare) {
- dialog.params.useCamera = verto.options.deviceParams.useCamera;
- }
-
- dialog.verto = verto;
- dialog.direction = direction;
- dialog.lastState = null;
- dialog.state = dialog.lastState = $.verto.enum.state.new;
- dialog.callbacks = verto.callbacks;
- dialog.answered = false;
- dialog.attach = params.attach || false;
- dialog.screenShare = params.screenShare || false;
- dialog.useCamera = dialog.params.useCamera;
- dialog.useMic = dialog.params.useMic;
- dialog.useSpeak = dialog.params.useSpeak;
-
- if (dialog.params.callID) {
- dialog.callID = dialog.params.callID;
- } else {
- dialog.callID = dialog.params.callID = generateGUID();
- }
-
- if (typeof(dialog.params.tag) === "function") {
- dialog.params.tag = dialog.params.tag();
- }
-
- if (dialog.params.tag) {
- dialog.audioStream = document.getElementById(dialog.params.tag);
-
- if (dialog.params.useVideo) {
- dialog.videoStream = dialog.audioStream;
- }
- } //else conjure one TBD
-
- if (dialog.params.localTag) {
- dialog.localVideo = document.getElementById(dialog.params.localTag);
- }
-
- dialog.verto.dialogs[dialog.callID] = dialog;
-
- var RTCcallbacks = {};
-
- if (dialog.direction == $.verto.enum.direction.inbound) {
- if (dialog.params.display_direction === "outbound") {
- dialog.params.remote_caller_id_name = dialog.params.caller_id_name;
- dialog.params.remote_caller_id_number = dialog.params.caller_id_number;
- } else {
- dialog.params.remote_caller_id_name = dialog.params.callee_id_name;
- dialog.params.remote_caller_id_number = dialog.params.callee_id_number;
- }
-
- if (!dialog.params.remote_caller_id_name) {
- dialog.params.remote_caller_id_name = "Nobody";
- }
-
- if (!dialog.params.remote_caller_id_number) {
- dialog.params.remote_caller_id_number = "UNKNOWN";
- }
-
- RTCcallbacks.onMessage = function(rtc, msg) {
- console.debug(msg);
- };
-
- RTCcallbacks.onAnswerSDP = function(rtc, sdp) {
- console.error("answer sdp", sdp);
- };
- } else {
- dialog.params.remote_caller_id_name = "Outbound Call";
- dialog.params.remote_caller_id_number = dialog.params.destination_number;
- }
-
- RTCcallbacks.onICESDP = function(rtc) {
- console.log("RECV " + rtc.type + " SDP", rtc.mediaData.SDP);
-
- if (dialog.state == $.verto.enum.state.requesting || dialog.state == $.verto.enum.state.answering || dialog.state == $.verto.enum.state.active) {
- location.reload();
- return;
- }
-
- if (rtc.type == "offer") {
- if (dialog.state == $.verto.enum.state.active) {
- dialog.setState($.verto.enum.state.requesting);
- dialog.sendMethod("verto.attach", {
- sdp: rtc.mediaData.SDP
- });
- } else {
- dialog.setState($.verto.enum.state.requesting);
-
- dialog.sendMethod("verto.invite", {
- sdp: rtc.mediaData.SDP
- });
- }
- } else { //answer
- dialog.setState($.verto.enum.state.answering);
-
- dialog.sendMethod(dialog.attach ? "verto.attach" : "verto.answer", {
- sdp: dialog.rtc.mediaData.SDP
- });
- }
- };
-
- RTCcallbacks.onICE = function(rtc) {
- //console.log("cand", rtc.mediaData.candidate);
- if (rtc.type == "offer") {
- console.log("offer", rtc.mediaData.candidate);
- return;
- }
- };
-
- RTCcallbacks.onStream = function(rtc, stream) {
- if (dialog.callbacks.permissionCallback &&
- typeof dialog.callbacks.permissionCallback.onGranted === 'function') {
- dialog.callbacks.permissionCallback.onGranted(stream);
- }
- else if (dialog.verto.options.permissionCallback &&
- typeof dialog.verto.options.permissionCallback.onGranted === 'function'){
- dialog.verto.options.permissionCallback.onGranted(stream);
- }
- console.log("stream started");
- };
-
- RTCcallbacks.onRemoteStream = function(rtc, stream) {
- if (typeof dialog.callbacks.onRemoteStream === 'function') {
- dialog.callbacks.onRemoteStream(stream, dialog);
- }
- console.log("remote stream started");
- };
-
- RTCcallbacks.onError = function(e) {
- if (dialog.callbacks.permissionCallback &&
- typeof dialog.callbacks.permissionCallback.onDenied === 'function') {
- dialog.callbacks.permissionCallback.onDenied();
- }
- else if (dialog.verto.options.permissionCallback &&
- typeof dialog.verto.options.permissionCallback.onDenied === 'function'){
- dialog.verto.options.permissionCallback.onDenied();
- }
- console.error("ERROR:", e);
- dialog.hangup({cause: "Device or Permission Error"});
- };
-
- dialog.rtc = new $.FSRTC({
- callbacks: RTCcallbacks,
- localVideo: dialog.screenShare ? null : dialog.localVideo,
- useVideo: dialog.params.useVideo ? dialog.videoStream : null,
- useAudio: dialog.audioStream,
- useStereo: dialog.params.useStereo,
- videoParams: dialog.params.videoParams,
- audioParams: verto.options.audioParams,
- iceServers: verto.options.iceServers,
- screenShare: dialog.screenShare,
- useCamera: dialog.useCamera,
- useMic: dialog.useMic,
- useSpeak: dialog.useSpeak,
- turnServer: verto.options.turnServer,
- useStream: dialog.params.useStream
- });
-
- dialog.rtc.verto = dialog.verto;
-
- if (dialog.direction == $.verto.enum.direction.inbound) {
- if (dialog.attach) {
- dialog.answer();
- } else {
- dialog.ring();
- }
- }
- };
-
- $.verto.dialog.prototype.invite = function() {
- var dialog = this;
- dialog.rtc.call();
- };
-
- $.verto.dialog.prototype.sendMethod = function(method, obj) {
- var dialog = this;
- obj.dialogParams = {};
-
- for (var i in dialog.params) {
- if (i == "sdp" && method != "verto.invite" && method != "verto.attach") {
- continue;
- }
-
- if ((obj.noDialogParams && i != "callID")) {
- continue;
- }
-
- obj.dialogParams[i] = dialog.params[i];
- }
-
- delete obj.noDialogParams;
-
- dialog.verto.rpcClient.call(method, obj,
-
- function(e) {
- /* Success */
- dialog.processReply(method, true, e);
- },
-
- function(e) {
- /* Error */
- dialog.processReply(method, false, e);
- });
- };
-
- function checkStateChange(oldS, newS) {
-
- if (newS == $.verto.enum.state.purge || $.verto.enum.states[oldS.name][newS.name]) {
- return true;
- }
-
- return false;
- }
-
-
- // Attach audio output device to video element using device/sink ID.
- function find_name(id) {
- for (var i in $.verto.audioOutDevices) {
- var source = $.verto.audioOutDevices[i];
- if (source.id === id) {
- return(source.label);
- }
- }
-
- return id;
- }
-
- $.verto.dialog.prototype.setAudioPlaybackDevice = function(sinkId, callback, arg) {
- var dialog = this;
- var element = dialog.audioStream;
-
- if (typeof element.sinkId !== 'undefined') {
- var devname = find_name(sinkId);
- console.info("Dialog: " + dialog.callID + " Setting speaker:", element, devname);
-
- element.setSinkId(sinkId)
- .then(function() {
- console.log("Dialog: " + dialog.callID + ' Success, audio output device attached: ' + sinkId);
- if (callback) {
- callback(true, devname, arg);
- }
- })
- .catch(function(error) {
- var errorMessage = error;
- if (error.name === 'SecurityError') {
- errorMessage = "Dialog: " + dialog.callID + ' You need to use HTTPS for selecting audio output ' +
- 'device: ' + error;
- }
- if (callback) {
- callback(false, null, arg);
- }
- console.error(errorMessage);
- });
- } else {
- console.warn("Dialog: " + dialog.callID + ' Browser does not support output device selection.');
- if (callback) {
- callback(false, null, arg);
- }
- }
- }
-
- $.verto.dialog.prototype.setState = function(state) {
- var dialog = this;
-
- if (dialog.state == $.verto.enum.state.ringing) {
- dialog.stopRinging();
- }
-
- if (dialog.state == state || !checkStateChange(dialog.state, state)) {
- console.error("Dialog " + dialog.callID + ": INVALID state change from " + dialog.state.name + " to " + state.name);
- dialog.hangup();
- return false;
- }
-
- console.log("Dialog " + dialog.callID + ": state change from " + dialog.state.name + " to " + state.name);
-
- dialog.lastState = dialog.state;
- dialog.state = state;
-
- if (dialog.callbacks.onDialogState) {
- dialog.callbacks.onDialogState(this);
- }
-
- switch (dialog.state) {
-
- case $.verto.enum.state.early:
- case $.verto.enum.state.active:
-
- var speaker = dialog.useSpeak;
- console.info("Using Speaker: ", speaker);
-
- if (speaker && speaker !== "any" && speaker !== "none") {
- setTimeout(function() {
- dialog.setAudioPlaybackDevice(speaker);
- }, 500);
- }
-
- break;
-
- case $.verto.enum.state.trying:
- setTimeout(function() {
- if (dialog.state == $.verto.enum.state.trying) {
- dialog.setState($.verto.enum.state.hangup);
- }
- }, 30000);
- break;
- case $.verto.enum.state.purge:
- dialog.setState($.verto.enum.state.destroy);
- break;
- case $.verto.enum.state.hangup:
-
- if (dialog.lastState.val > $.verto.enum.state.requesting.val && dialog.lastState.val < $.verto.enum.state.hangup.val) {
- dialog.sendMethod("verto.bye", {});
- }
-
- dialog.setState($.verto.enum.state.destroy);
- break;
- case $.verto.enum.state.destroy:
-
- if (typeof(dialog.verto.options.tag) === "function") {
- $('#' + dialog.params.tag).remove();
- }
-
- delete dialog.verto.dialogs[dialog.callID];
- if (dialog.params.screenShare) {
- dialog.rtc.stopPeer();
- } else {
- dialog.rtc.stop();
- }
- break;
- }
-
- return true;
- };
-
- $.verto.dialog.prototype.processReply = function(method, success, e) {
- var dialog = this;
-
- //console.log("Response: " + method + " State:" + dialog.state.name, success, e);
-
- switch (method) {
-
- case "verto.answer":
- case "verto.attach":
- if (success) {
- dialog.setState($.verto.enum.state.active);
- } else {
- dialog.hangup();
- }
- break;
- case "verto.invite":
- if (success) {
- dialog.setState($.verto.enum.state.trying);
- } else {
- dialog.setState($.verto.enum.state.destroy);
- }
- break;
-
- case "verto.bye":
- dialog.hangup();
- break;
-
- case "verto.modify":
- if (e.holdState) {
- if (e.holdState == "held") {
- if (dialog.state != $.verto.enum.state.held) {
- dialog.setState($.verto.enum.state.held);
- }
- } else if (e.holdState == "active") {
- if (dialog.state != $.verto.enum.state.active) {
- dialog.setState($.verto.enum.state.active);
- }
- }
- }
-
- if (success) {}
-
- break;
-
- default:
- break;
- }
-
- };
-
- $.verto.dialog.prototype.hangup = function(params) {
- var dialog = this;
-
- if (params) {
- if (params.causeCode) {
- dialog.causeCode = params.causeCode;
- }
-
- if (params.cause) {
- dialog.cause = params.cause;
- }
- }
-
- if (!dialog.cause && !dialog.causeCode) {
- dialog.cause = "NORMAL_CLEARING";
- }
-
- if (dialog.state.val >= $.verto.enum.state.new.val && dialog.state.val < $.verto.enum.state.hangup.val) {
- dialog.setState($.verto.enum.state.hangup);
- } else if (dialog.state.val < $.verto.enum.state.destroy) {
- dialog.setState($.verto.enum.state.destroy);
- }
- };
-
- $.verto.dialog.prototype.stopRinging = function() {
- var dialog = this;
- if (dialog.verto.ringer) {
- dialog.verto.ringer.stop();
- }
- };
-
- $.verto.dialog.prototype.indicateRing = function() {
- var dialog = this;
-
- if (dialog.verto.ringer) {
- dialog.verto.ringer.attr("src", dialog.verto.options.ringFile)[0].play();
-
- setTimeout(function() {
- dialog.stopRinging();
- if (dialog.state == $.verto.enum.state.ringing) {
- dialog.indicateRing();
- }
- },
- dialog.verto.options.ringSleep);
- }
- };
-
- $.verto.dialog.prototype.ring = function() {
- var dialog = this;
-
- dialog.setState($.verto.enum.state.ringing);
- dialog.indicateRing();
- };
-
- $.verto.dialog.prototype.useVideo = function(on) {
- var dialog = this;
-
- dialog.params.useVideo = on;
-
- if (on) {
- dialog.videoStream = dialog.audioStream;
- } else {
- dialog.videoStream = null;
- }
-
- dialog.rtc.useVideo(dialog.videoStream, dialog.localVideo);
-
- };
-
- $.verto.dialog.prototype.setMute = function(what) {
- var dialog = this;
- return dialog.rtc.setMute(what);
- };
-
- $.verto.dialog.prototype.getMute = function() {
- var dialog = this;
- return dialog.rtc.getMute();
- };
-
- $.verto.dialog.prototype.setVideoMute = function(what) {
- var dialog = this;
- return dialog.rtc.setVideoMute(what);
- };
-
- $.verto.dialog.prototype.getVideoMute = function() {
- var dialog = this;
- return dialog.rtc.getVideoMute();
- };
-
- $.verto.dialog.prototype.useStereo = function(on) {
- var dialog = this;
-
- dialog.params.useStereo = on;
- dialog.rtc.useStereo(on);
- };
-
- $.verto.dialog.prototype.dtmf = function(digits) {
- var dialog = this;
- if (digits) {
- dialog.sendMethod("verto.info", {
- dtmf: digits
- });
- }
- };
-
- $.verto.dialog.prototype.rtt = function(obj) {
- var dialog = this;
- var pobj = {};
-
- if (!obj) {
- return false;
- }
-
- pobj.code = obj.code;
- pobj.chars = obj.chars;
-
-
- if (pobj.chars || pobj.code) {
- dialog.sendMethod("verto.info", {
- txt: obj,
- noDialogParams: true
- });
- }
- };
-
- $.verto.dialog.prototype.transfer = function(dest, params) {
- var dialog = this;
- if (dest) {
- dialog.sendMethod("verto.modify", {
- action: "transfer",
- destination: dest,
- params: params
- });
- }
- };
-
- $.verto.dialog.prototype.replace = function(replaceCallID, params) {
- var dialog = this;
- if (replaceCallID) {
- dialog.sendMethod("verto.modify", {
- action: "replace",
- replaceCallID: replaceCallID,
- params: params
- });
- }
- };
-
- $.verto.dialog.prototype.hold = function(params) {
- var dialog = this;
-
- dialog.sendMethod("verto.modify", {
- action: "hold",
- params: params
- });
- };
-
- $.verto.dialog.prototype.unhold = function(params) {
- var dialog = this;
-
- dialog.sendMethod("verto.modify", {
- action: "unhold",
- params: params
- });
- };
-
- $.verto.dialog.prototype.toggleHold = function(params) {
- var dialog = this;
-
- dialog.sendMethod("verto.modify", {
- action: "toggleHold",
- params: params
- });
- };
-
- $.verto.dialog.prototype.message = function(msg) {
- var dialog = this;
- var err = 0;
-
- msg.from = dialog.params.login;
-
- if (!msg.to) {
- console.error("Missing To");
- err++;
- }
-
- if (!msg.body) {
- console.error("Missing Body");
- err++;
- }
-
- if (err) {
- return false;
- }
-
- dialog.sendMethod("verto.info", {
- msg: msg
- });
-
- return true;
- };
-
- $.verto.dialog.prototype.answer = function(params) {
- var dialog = this;
-
- if (!dialog.answered) {
- if (!params) {
- params = {};
- }
-
- params.sdp = dialog.params.sdp;
-
- if (params) {
- if (params.useVideo) {
- dialog.useVideo(true);
- }
- dialog.params.callee_id_name = params.callee_id_name;
- dialog.params.callee_id_number = params.callee_id_number;
-
- if (params.useCamera) {
- dialog.useCamera = params.useCamera;
- }
-
- if (params.useMic) {
- dialog.useMic = params.useMic;
- }
-
- if (params.useSpeak) {
- dialog.useSpeak = params.useSpeak;
- }
- }
-
- dialog.rtc.createAnswer(params);
- dialog.answered = true;
- }
- };
-
- $.verto.dialog.prototype.handleAnswer = function(params) {
- var dialog = this;
-
- dialog.gotAnswer = true;
-
- if (dialog.state.val >= $.verto.enum.state.active.val) {
- return;
- }
-
- if (dialog.state.val >= $.verto.enum.state.early.val) {
- dialog.setState($.verto.enum.state.active);
- } else {
- if (dialog.gotEarly) {
- console.log("Dialog " + dialog.callID + " Got answer while still establishing early media, delaying...");
- } else {
- console.log("Dialog " + dialog.callID + " Answering Channel");
- dialog.rtc.answer(params.sdp, function() {
- dialog.setState($.verto.enum.state.active);
- }, function(e) {
- console.error(e);
- dialog.hangup();
- });
- console.log("Dialog " + dialog.callID + "ANSWER SDP", params.sdp);
- }
- }
-
-
- };
-
- $.verto.dialog.prototype.cidString = function(enc) {
- var dialog = this;
- var party = dialog.params.remote_caller_id_name + (enc ? " <" : " <") + dialog.params.remote_caller_id_number + (enc ? ">" : ">");
- return party;
- };
-
- $.verto.dialog.prototype.sendMessage = function(msg, params) {
- var dialog = this;
-
- if (dialog.callbacks.onMessage) {
- dialog.callbacks.onMessage(dialog.verto, dialog, msg, params);
- }
- };
-
- $.verto.dialog.prototype.handleInfo = function(params) {
- var dialog = this;
-
- dialog.sendMessage($.verto.enum.message.info, params);
-
- };
-
- $.verto.dialog.prototype.handleDisplay = function(params) {
- var dialog = this;
-
- if (params.display_name) {
- dialog.params.remote_caller_id_name = params.display_name;
- }
- if (params.display_number) {
- dialog.params.remote_caller_id_number = params.display_number;
- }
-
- dialog.sendMessage($.verto.enum.message.display, {});
- };
-
- $.verto.dialog.prototype.handleMedia = function(params) {
- var dialog = this;
-
- if (dialog.state.val >= $.verto.enum.state.early.val) {
- return;
- }
-
- dialog.gotEarly = true;
-
- dialog.rtc.answer(params.sdp, function() {
- console.log("Dialog " + dialog.callID + "Establishing early media");
- dialog.setState($.verto.enum.state.early);
-
- if (dialog.gotAnswer) {
- console.log("Dialog " + dialog.callID + "Answering Channel");
- dialog.setState($.verto.enum.state.active);
- }
- }, function(e) {
- console.error(e);
- dialog.hangup();
- });
- console.log("Dialog " + dialog.callID + "EARLY SDP", params.sdp);
- };
-
- $.verto.ENUM = function(s) {
- var i = 0,
- o = {};
- s.split(" ").map(function(x) {
- o[x] = {
- name: x,
- val: i++
- };
- });
- return Object.freeze(o);
- };
-
- $.verto.enum = {};
-
- $.verto.enum.states = Object.freeze({
- new: {
- requesting: 1,
- recovering: 1,
- ringing: 1,
- destroy: 1,
- answering: 1,
- hangup: 1
- },
- requesting: {
- trying: 1,
- hangup: 1,
- active: 1
- },
- recovering: {
- answering: 1,
- hangup: 1
- },
- trying: {
- active: 1,
- early: 1,
- hangup: 1
- },
- ringing: {
- answering: 1,
- hangup: 1
- },
- answering: {
- active: 1,
- hangup: 1
- },
- active: {
- answering: 1,
- requesting: 1,
- hangup: 1,
- held: 1
- },
- held: {
- hangup: 1,
- active: 1
- },
- early: {
- hangup: 1,
- active: 1
- },
- hangup: {
- destroy: 1
- },
- destroy: {},
- purge: {
- destroy: 1
- }
- });
-
- $.verto.enum.state = $.verto.ENUM("new requesting trying recovering ringing answering early active held hangup destroy purge");
- $.verto.enum.direction = $.verto.ENUM("inbound outbound");
- $.verto.enum.message = $.verto.ENUM("display info pvtEvent clientReady");
-
- $.verto.enum = Object.freeze($.verto.enum);
-
- $.verto.saved = [];
-
- $.verto.unloadJobs = [];
-
- var unloadEventName = 'beforeunload';
- // Hacks for Mobile Safari
- var iOS = ['iPad', 'iPhone', 'iPod'].indexOf(navigator.platform) >= 0;
- if (iOS) {
- unloadEventName = 'pagehide';
- }
-
- $(window).bind(unloadEventName, function() {
- for (var f in $.verto.unloadJobs) {
- $.verto.unloadJobs[f]();
- }
-
- if ($.verto.haltClosure)
- return $.verto.haltClosure();
-
- for (var i in $.verto.saved) {
- var verto = $.verto.saved[i];
- if (verto) {
- verto.purge();
- verto.logout();
- }
- }
-
- return $.verto.warnOnUnload;
- });
-
- $.verto.videoDevices = [];
- $.verto.audioInDevices = [];
- $.verto.audioOutDevices = [];
-
- var checkDevices = function(runtime) {
- console.info("enumerating devices");
- var aud_in = [], aud_out = [], vid = [];
- var has_video = 0, has_audio = 0;
- var Xstream;
-
- function gotDevices(deviceInfos) {
- // Handles being called several times to update labels. Preserve values.
- for (var i = 0; i !== deviceInfos.length; ++i) {
- var deviceInfo = deviceInfos[i];
- var text = "";
-
- console.log(deviceInfo);
- console.log(deviceInfo.kind + ": " + deviceInfo.label + " id = " + deviceInfo.deviceId);
-
- if (deviceInfo.kind === 'audioinput') {
- text = deviceInfo.label || 'microphone ' + (aud_in.length + 1);
- aud_in.push({id: deviceInfo.deviceId, kind: "audio_in", label: text});
- } else if (deviceInfo.kind === 'audiooutput') {
- text = deviceInfo.label || 'speaker ' + (aud_out.length + 1);
- aud_out.push({id: deviceInfo.deviceId, kind: "audio_out", label: text});
- } else if (deviceInfo.kind === 'videoinput') {
- text = deviceInfo.label || 'camera ' + (vid.length + 1);
- vid.push({id: deviceInfo.deviceId, kind: "video", label: text});
- } else {
- console.log('Some other kind of source/device: ', deviceInfo);
- }
- }
-
-
- $.verto.videoDevices = vid;
- $.verto.audioInDevices = aud_in;
- $.verto.audioOutDevices = aud_out;
-
- console.info("Audio IN Devices", $.verto.audioInDevices);
- console.info("Audio Out Devices", $.verto.audioOutDevices);
- console.info("Video Devices", $.verto.videoDevices);
-
- if (Xstream) {
- Xstream.getTracks().forEach(function(track) {track.stop();});
- }
-
- if (runtime) {
- runtime(true);
- }
- }
-
-
-
-
- function handleError(error) {
- console.log('device enumeration error: ', error);
- if (runtime) runtime(false);
- }
-
-
- function checkTypes(devs) {
- for (var i = 0; i !== devs.length; ++i) {
-
- if (devs[i].kind === 'audioinput') {
- has_audio++;
- } else if (devs[i].kind === 'videoinput') {
- has_video++;
- }
- }
-
- navigator.getUserMedia({ audio: (has_audio > 0 ? true : false), video: (has_video > 0 ? true : false)},
- function(stream) {
- Xstream = stream;
- navigator.mediaDevices.enumerateDevices().then(gotDevices).catch(handleError);
- },
- function(err) {
- console.log("The following error occurred: " + err.name);
- }
- );
- }
-
- navigator.mediaDevices.enumerateDevices().then(checkTypes).catch(handleError);
-
- };
-
- $.verto.refreshDevices = function(runtime) {
- checkDevices(runtime);
- }
-
- $.verto.init = function(obj, runtime) {
- if (!obj) {
- obj = {};
- }
-
- if (!obj.skipPermCheck && !obj.skipDeviceCheck) {
- $.FSRTC.checkPerms(function(status) {
- checkDevices(runtime);
- }, true, true);
- } else if (obj.skipPermCheck && !obj.skipDeviceCheck) {
- checkDevices(runtime);
- } else if (!obj.skipPermCheck && obj.skipDeviceCheck) {
- $.FSRTC.checkPerms(function(status) {
- runtime(status);
- }, true, true);
- } else {
- runtime(null);
- }
-
- }
-
- $.verto.genUUID = function () {
- return generateGUID();
- }
-
-
-})(jQuery);
-(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.adapter = 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= 14393 &&
- url.indexOf('?transport=udp') === -1;
- });
-
- delete server.url;
- server.urls = isString ? urls[0] : urls;
- return !!urls.length;
- }
- });
-}
-
-// Determines the intersection of local and remote capabilities.
-function getCommonCapabilities(localCapabilities, remoteCapabilities) {
- var commonCapabilities = {
- codecs: [],
- headerExtensions: [],
- fecMechanisms: []
- };
-
- var findCodecByPayloadType = function(pt, codecs) {
- pt = parseInt(pt, 10);
- for (var i = 0; i < codecs.length; i++) {
- if (codecs[i].payloadType === pt ||
- codecs[i].preferredPayloadType === pt) {
- return codecs[i];
- }
- }
- };
-
- var rtxCapabilityMatches = function(lRtx, rRtx, lCodecs, rCodecs) {
- var lCodec = findCodecByPayloadType(lRtx.parameters.apt, lCodecs);
- var rCodec = findCodecByPayloadType(rRtx.parameters.apt, rCodecs);
- return lCodec && rCodec &&
- lCodec.name.toLowerCase() === rCodec.name.toLowerCase();
- };
-
- localCapabilities.codecs.forEach(function(lCodec) {
- for (var i = 0; i < remoteCapabilities.codecs.length; i++) {
- var rCodec = remoteCapabilities.codecs[i];
- if (lCodec.name.toLowerCase() === rCodec.name.toLowerCase() &&
- lCodec.clockRate === rCodec.clockRate) {
- if (lCodec.name.toLowerCase() === 'rtx' &&
- lCodec.parameters && rCodec.parameters.apt) {
- // for RTX we need to find the local rtx that has a apt
- // which points to the same local codec as the remote one.
- if (!rtxCapabilityMatches(lCodec, rCodec,
- localCapabilities.codecs, remoteCapabilities.codecs)) {
- continue;
- }
- }
- rCodec = JSON.parse(JSON.stringify(rCodec)); // deepcopy
- // number of channels is the highest common number of channels
- rCodec.numChannels = Math.min(lCodec.numChannels,
- rCodec.numChannels);
- // push rCodec so we reply with offerer payload type
- commonCapabilities.codecs.push(rCodec);
-
- // determine common feedback mechanisms
- rCodec.rtcpFeedback = rCodec.rtcpFeedback.filter(function(fb) {
- for (var j = 0; j < lCodec.rtcpFeedback.length; j++) {
- if (lCodec.rtcpFeedback[j].type === fb.type &&
- lCodec.rtcpFeedback[j].parameter === fb.parameter) {
- return true;
- }
- }
- return false;
- });
- // FIXME: also need to determine .parameters
- // see https://github.com/openpeer/ortc/issues/569
- break;
- }
- }
- });
-
- localCapabilities.headerExtensions.forEach(function(lHeaderExtension) {
- for (var i = 0; i < remoteCapabilities.headerExtensions.length;
- i++) {
- var rHeaderExtension = remoteCapabilities.headerExtensions[i];
- if (lHeaderExtension.uri === rHeaderExtension.uri) {
- commonCapabilities.headerExtensions.push(rHeaderExtension);
- break;
- }
- }
- });
-
- // FIXME: fecMechanisms
- return commonCapabilities;
-}
-
-// is action=setLocalDescription with type allowed in signalingState
-function isActionAllowedInSignalingState(action, type, signalingState) {
- return {
- offer: {
- setLocalDescription: ['stable', 'have-local-offer'],
- setRemoteDescription: ['stable', 'have-remote-offer']
- },
- answer: {
- setLocalDescription: ['have-remote-offer', 'have-local-pranswer'],
- setRemoteDescription: ['have-local-offer', 'have-remote-pranswer']
- }
- }[type][action].indexOf(signalingState) !== -1;
-}
-
-function maybeAddCandidate(iceTransport, candidate) {
- // Edge's internal representation adds some fields therefore
- // not all fieldѕ are taken into account.
- var alreadyAdded = iceTransport.getRemoteCandidates()
- .find(function(remoteCandidate) {
- return candidate.foundation === remoteCandidate.foundation &&
- candidate.ip === remoteCandidate.ip &&
- candidate.port === remoteCandidate.port &&
- candidate.priority === remoteCandidate.priority &&
- candidate.protocol === remoteCandidate.protocol &&
- candidate.type === remoteCandidate.type;
- });
- if (!alreadyAdded) {
- iceTransport.addRemoteCandidate(candidate);
- }
- return !alreadyAdded;
-}
-
-
-// https://w3c.github.io/mediacapture-main/#mediastream
-// Helper function to add the track to the stream and
-// dispatch the event ourselves.
-function addTrackToStreamAndFireEvent(track, stream) {
- stream.addTrack(track);
- var e = new Event('addtrack'); // TODO: MediaStreamTrackEvent
- e.track = track;
- stream.dispatchEvent(e);
-}
-
-function removeTrackFromStreamAndFireEvent(track, stream) {
- stream.removeTrack(track);
- var e = new Event('removetrack'); // TODO: MediaStreamTrackEvent
- e.track = track;
- stream.dispatchEvent(e);
-}
-
-function fireAddTrack(pc, track, receiver, streams) {
- var trackEvent = new Event('track');
- trackEvent.track = track;
- trackEvent.receiver = receiver;
- trackEvent.transceiver = {receiver: receiver};
- trackEvent.streams = streams;
- window.setTimeout(function() {
- pc._dispatchEvent('track', trackEvent);
- });
-}
-
-function makeError(name, description) {
- var e = new Error(description);
- e.name = name;
- return e;
-}
-
-module.exports = function(window, edgeVersion) {
- var RTCPeerConnection = function(config) {
- var pc = this;
-
- var _eventTarget = document.createDocumentFragment();
- ['addEventListener', 'removeEventListener', 'dispatchEvent']
- .forEach(function(method) {
- pc[method] = _eventTarget[method].bind(_eventTarget);
- });
-
- this.canTrickleIceCandidates = null;
-
- this.needNegotiation = false;
-
- this.localStreams = [];
- this.remoteStreams = [];
-
- this.localDescription = null;
- this.remoteDescription = null;
-
- this.signalingState = 'stable';
- this.iceConnectionState = 'new';
- this.iceGatheringState = 'new';
-
- config = JSON.parse(JSON.stringify(config || {}));
-
- this.usingBundle = config.bundlePolicy === 'max-bundle';
- if (config.rtcpMuxPolicy === 'negotiate') {
- throw(makeError('NotSupportedError',
- 'rtcpMuxPolicy \'negotiate\' is not supported'));
- } else if (!config.rtcpMuxPolicy) {
- config.rtcpMuxPolicy = 'require';
- }
-
- switch (config.iceTransportPolicy) {
- case 'all':
- case 'relay':
- break;
- default:
- config.iceTransportPolicy = 'all';
- break;
- }
-
- switch (config.bundlePolicy) {
- case 'balanced':
- case 'max-compat':
- case 'max-bundle':
- break;
- default:
- config.bundlePolicy = 'balanced';
- break;
- }
-
- config.iceServers = filterIceServers(config.iceServers || [], edgeVersion);
-
- this._iceGatherers = [];
- if (config.iceCandidatePoolSize) {
- for (var i = config.iceCandidatePoolSize; i > 0; i--) {
- this._iceGatherers = new window.RTCIceGatherer({
- iceServers: config.iceServers,
- gatherPolicy: config.iceTransportPolicy
- });
- }
- } else {
- config.iceCandidatePoolSize = 0;
- }
-
- this._config = config;
-
- // per-track iceGathers, iceTransports, dtlsTransports, rtpSenders, ...
- // everything that is needed to describe a SDP m-line.
- this.transceivers = [];
-
- this._sdpSessionId = SDPUtils.generateSessionId();
- this._sdpSessionVersion = 0;
-
- this._dtlsRole = undefined; // role for a=setup to use in answers.
-
- this._isClosed = false;
- };
-
- // set up event handlers on prototype
- RTCPeerConnection.prototype.onicecandidate = null;
- RTCPeerConnection.prototype.onaddstream = null;
- RTCPeerConnection.prototype.ontrack = null;
- RTCPeerConnection.prototype.onremovestream = null;
- RTCPeerConnection.prototype.onsignalingstatechange = null;
- RTCPeerConnection.prototype.oniceconnectionstatechange = null;
- RTCPeerConnection.prototype.onicegatheringstatechange = null;
- RTCPeerConnection.prototype.onnegotiationneeded = null;
- RTCPeerConnection.prototype.ondatachannel = null;
-
- RTCPeerConnection.prototype._dispatchEvent = function(name, event) {
- if (this._isClosed) {
- return;
- }
- this.dispatchEvent(event);
- if (typeof this['on' + name] === 'function') {
- this['on' + name](event);
- }
- };
-
- RTCPeerConnection.prototype._emitGatheringStateChange = function() {
- var event = new Event('icegatheringstatechange');
- this._dispatchEvent('icegatheringstatechange', event);
- };
-
- RTCPeerConnection.prototype.getConfiguration = function() {
- return this._config;
- };
-
- RTCPeerConnection.prototype.getLocalStreams = function() {
- return this.localStreams;
- };
-
- RTCPeerConnection.prototype.getRemoteStreams = function() {
- return this.remoteStreams;
- };
-
- // internal helper to create a transceiver object.
- // (whih is not yet the same as the WebRTC 1.0 transceiver)
- RTCPeerConnection.prototype._createTransceiver = function(kind) {
- var hasBundleTransport = this.transceivers.length > 0;
- var transceiver = {
- track: null,
- iceGatherer: null,
- iceTransport: null,
- dtlsTransport: null,
- localCapabilities: null,
- remoteCapabilities: null,
- rtpSender: null,
- rtpReceiver: null,
- kind: kind,
- mid: null,
- sendEncodingParameters: null,
- recvEncodingParameters: null,
- stream: null,
- associatedRemoteMediaStreams: [],
- wantReceive: true
- };
- if (this.usingBundle && hasBundleTransport) {
- transceiver.iceTransport = this.transceivers[0].iceTransport;
- transceiver.dtlsTransport = this.transceivers[0].dtlsTransport;
- } else {
- var transports = this._createIceAndDtlsTransports();
- transceiver.iceTransport = transports.iceTransport;
- transceiver.dtlsTransport = transports.dtlsTransport;
- }
- this.transceivers.push(transceiver);
- return transceiver;
- };
-
- RTCPeerConnection.prototype.addTrack = function(track, stream) {
- var alreadyExists = this.transceivers.find(function(s) {
- return s.track === track;
- });
-
- if (alreadyExists) {
- throw makeError('InvalidAccessError', 'Track already exists.');
- }
-
- if (this.signalingState === 'closed') {
- throw makeError('InvalidStateError',
- 'Attempted to call addTrack on a closed peerconnection.');
- }
-
- var transceiver;
- for (var i = 0; i < this.transceivers.length; i++) {
- if (!this.transceivers[i].track &&
- this.transceivers[i].kind === track.kind) {
- transceiver = this.transceivers[i];
- }
- }
- if (!transceiver) {
- transceiver = this._createTransceiver(track.kind);
- }
-
- this._maybeFireNegotiationNeeded();
-
- if (this.localStreams.indexOf(stream) === -1) {
- this.localStreams.push(stream);
- }
-
- transceiver.track = track;
- transceiver.stream = stream;
- transceiver.rtpSender = new window.RTCRtpSender(track,
- transceiver.dtlsTransport);
- return transceiver.rtpSender;
- };
-
- RTCPeerConnection.prototype.addStream = function(stream) {
- var pc = this;
- if (edgeVersion >= 15025) {
- stream.getTracks().forEach(function(track) {
- pc.addTrack(track, stream);
- });
- } else {
- // Clone is necessary for local demos mostly, attaching directly
- // to two different senders does not work (build 10547).
- // Fixed in 15025 (or earlier)
- var clonedStream = stream.clone();
- stream.getTracks().forEach(function(track, idx) {
- var clonedTrack = clonedStream.getTracks()[idx];
- track.addEventListener('enabled', function(event) {
- clonedTrack.enabled = event.enabled;
- });
- });
- clonedStream.getTracks().forEach(function(track) {
- pc.addTrack(track, clonedStream);
- });
- }
- };
-
- RTCPeerConnection.prototype.removeTrack = function(sender) {
- if (!(sender instanceof window.RTCRtpSender)) {
- throw new TypeError('Argument 1 of RTCPeerConnection.removeTrack ' +
- 'does not implement interface RTCRtpSender.');
- }
-
- var transceiver = this.transceivers.find(function(t) {
- return t.rtpSender === sender;
- });
-
- if (!transceiver) {
- throw makeError('InvalidAccessError',
- 'Sender was not created by this connection.');
- }
- var stream = transceiver.stream;
-
- transceiver.rtpSender.stop();
- transceiver.rtpSender = null;
- transceiver.track = null;
- transceiver.stream = null;
-
- // remove the stream from the set of local streams
- var localStreams = this.transceivers.map(function(t) {
- return t.stream;
- });
- if (localStreams.indexOf(stream) === -1 &&
- this.localStreams.indexOf(stream) > -1) {
- this.localStreams.splice(this.localStreams.indexOf(stream), 1);
- }
-
- this._maybeFireNegotiationNeeded();
- };
-
- RTCPeerConnection.prototype.removeStream = function(stream) {
- var pc = this;
- stream.getTracks().forEach(function(track) {
- var sender = pc.getSenders().find(function(s) {
- return s.track === track;
- });
- if (sender) {
- pc.removeTrack(sender);
- }
- });
- };
-
- RTCPeerConnection.prototype.getSenders = function() {
- return this.transceivers.filter(function(transceiver) {
- return !!transceiver.rtpSender;
- })
- .map(function(transceiver) {
- return transceiver.rtpSender;
- });
- };
-
- RTCPeerConnection.prototype.getReceivers = function() {
- return this.transceivers.filter(function(transceiver) {
- return !!transceiver.rtpReceiver;
- })
- .map(function(transceiver) {
- return transceiver.rtpReceiver;
- });
- };
-
-
- RTCPeerConnection.prototype._createIceGatherer = function(sdpMLineIndex,
- usingBundle) {
- var pc = this;
- if (usingBundle && sdpMLineIndex > 0) {
- return this.transceivers[0].iceGatherer;
- } else if (this._iceGatherers.length) {
- return this._iceGatherers.shift();
- }
- var iceGatherer = new window.RTCIceGatherer({
- iceServers: this._config.iceServers,
- gatherPolicy: this._config.iceTransportPolicy
- });
- Object.defineProperty(iceGatherer, 'state',
- {value: 'new', writable: true}
- );
-
- this.transceivers[sdpMLineIndex].candidates = [];
- this.transceivers[sdpMLineIndex].bufferCandidates = function(event) {
- var end = !event.candidate || Object.keys(event.candidate).length === 0;
- // polyfill since RTCIceGatherer.state is not implemented in
- // Edge 10547 yet.
- iceGatherer.state = end ? 'completed' : 'gathering';
- if (pc.transceivers[sdpMLineIndex].candidates !== null) {
- pc.transceivers[sdpMLineIndex].candidates.push(event.candidate);
- }
- };
- iceGatherer.addEventListener('localcandidate',
- this.transceivers[sdpMLineIndex].bufferCandidates);
- return iceGatherer;
- };
-
- // start gathering from an RTCIceGatherer.
- RTCPeerConnection.prototype._gather = function(mid, sdpMLineIndex) {
- var pc = this;
- var iceGatherer = this.transceivers[sdpMLineIndex].iceGatherer;
- if (iceGatherer.onlocalcandidate) {
- return;
- }
- var candidates = this.transceivers[sdpMLineIndex].candidates;
- this.transceivers[sdpMLineIndex].candidates = null;
- iceGatherer.removeEventListener('localcandidate',
- this.transceivers[sdpMLineIndex].bufferCandidates);
- iceGatherer.onlocalcandidate = function(evt) {
- if (pc.usingBundle && sdpMLineIndex > 0) {
- // if we know that we use bundle we can drop candidates with
- // Ń•dpMLineIndex > 0. If we don't do this then our state gets
- // confused since we dispose the extra ice gatherer.
- return;
- }
- var event = new Event('icecandidate');
- event.candidate = {sdpMid: mid, sdpMLineIndex: sdpMLineIndex};
-
- var cand = evt.candidate;
- // Edge emits an empty object for RTCIceCandidateComplete‥
- var end = !cand || Object.keys(cand).length === 0;
- if (end) {
- // polyfill since RTCIceGatherer.state is not implemented in
- // Edge 10547 yet.
- if (iceGatherer.state === 'new' || iceGatherer.state === 'gathering') {
- iceGatherer.state = 'completed';
- }
- } else {
- if (iceGatherer.state === 'new') {
- iceGatherer.state = 'gathering';
- }
- // RTCIceCandidate doesn't have a component, needs to be added
- cand.component = 1;
- event.candidate.candidate = SDPUtils.writeCandidate(cand);
- }
-
- // update local description.
- var sections = SDPUtils.splitSections(pc.localDescription.sdp);
- if (!end) {
- sections[event.candidate.sdpMLineIndex + 1] +=
- 'a=' + event.candidate.candidate + '\r\n';
- } else {
- sections[event.candidate.sdpMLineIndex + 1] +=
- 'a=end-of-candidates\r\n';
- }
- pc.localDescription.sdp = sections.join('');
- var complete = pc.transceivers.every(function(transceiver) {
- return transceiver.iceGatherer &&
- transceiver.iceGatherer.state === 'completed';
- });
-
- if (pc.iceGatheringState !== 'gathering') {
- pc.iceGatheringState = 'gathering';
- pc._emitGatheringStateChange();
- }
-
- // Emit candidate. Also emit null candidate when all gatherers are
- // complete.
- if (!end) {
- pc._dispatchEvent('icecandidate', event);
- }
- if (complete) {
- pc._dispatchEvent('icecandidate', new Event('icecandidate'));
- pc.iceGatheringState = 'complete';
- pc._emitGatheringStateChange();
- }
- };
-
- // emit already gathered candidates.
- window.setTimeout(function() {
- candidates.forEach(function(candidate) {
- var e = new Event('RTCIceGatherEvent');
- e.candidate = candidate;
- iceGatherer.onlocalcandidate(e);
- });
- }, 0);
- };
-
- // Create ICE transport and DTLS transport.
- RTCPeerConnection.prototype._createIceAndDtlsTransports = function() {
- var pc = this;
- var iceTransport = new window.RTCIceTransport(null);
- iceTransport.onicestatechange = function() {
- pc._updateConnectionState();
- };
-
- var dtlsTransport = new window.RTCDtlsTransport(iceTransport);
- dtlsTransport.ondtlsstatechange = function() {
- pc._updateConnectionState();
- };
- dtlsTransport.onerror = function() {
- // onerror does not set state to failed by itpc.
- Object.defineProperty(dtlsTransport, 'state',
- {value: 'failed', writable: true});
- pc._updateConnectionState();
- };
-
- return {
- iceTransport: iceTransport,
- dtlsTransport: dtlsTransport
- };
- };
-
- // Destroy ICE gatherer, ICE transport and DTLS transport.
- // Without triggering the callbacks.
- RTCPeerConnection.prototype._disposeIceAndDtlsTransports = function(
- sdpMLineIndex) {
- var iceGatherer = this.transceivers[sdpMLineIndex].iceGatherer;
- if (iceGatherer) {
- delete iceGatherer.onlocalcandidate;
- delete this.transceivers[sdpMLineIndex].iceGatherer;
- }
- var iceTransport = this.transceivers[sdpMLineIndex].iceTransport;
- if (iceTransport) {
- delete iceTransport.onicestatechange;
- delete this.transceivers[sdpMLineIndex].iceTransport;
- }
- var dtlsTransport = this.transceivers[sdpMLineIndex].dtlsTransport;
- if (dtlsTransport) {
- delete dtlsTransport.ondtlsstatechange;
- delete dtlsTransport.onerror;
- delete this.transceivers[sdpMLineIndex].dtlsTransport;
- }
- };
-
- // Start the RTP Sender and Receiver for a transceiver.
- RTCPeerConnection.prototype._transceive = function(transceiver,
- send, recv) {
- var params = getCommonCapabilities(transceiver.localCapabilities,
- transceiver.remoteCapabilities);
- if (send && transceiver.rtpSender) {
- params.encodings = transceiver.sendEncodingParameters;
- params.rtcp = {
- cname: SDPUtils.localCName,
- compound: transceiver.rtcpParameters.compound
- };
- if (transceiver.recvEncodingParameters.length) {
- params.rtcp.ssrc = transceiver.recvEncodingParameters[0].ssrc;
- }
- transceiver.rtpSender.send(params);
- }
- if (recv && transceiver.rtpReceiver && params.codecs.length > 0) {
- // remove RTX field in Edge 14942
- if (transceiver.kind === 'video'
- && transceiver.recvEncodingParameters
- && edgeVersion < 15019) {
- transceiver.recvEncodingParameters.forEach(function(p) {
- delete p.rtx;
- });
- }
- if (transceiver.recvEncodingParameters.length) {
- params.encodings = transceiver.recvEncodingParameters;
- }
- params.rtcp = {
- compound: transceiver.rtcpParameters.compound
- };
- if (transceiver.rtcpParameters.cname) {
- params.rtcp.cname = transceiver.rtcpParameters.cname;
- }
- if (transceiver.sendEncodingParameters.length) {
- params.rtcp.ssrc = transceiver.sendEncodingParameters[0].ssrc;
- }
- transceiver.rtpReceiver.receive(params);
- }
- };
-
- RTCPeerConnection.prototype.setLocalDescription = function(description) {
- var pc = this;
-
- if (!isActionAllowedInSignalingState('setLocalDescription',
- description.type, this.signalingState) || this._isClosed) {
- return Promise.reject(makeError('InvalidStateError',
- 'Can not set local ' + description.type +
- ' in state ' + pc.signalingState));
- }
-
- var sections;
- var sessionpart;
- if (description.type === 'offer') {
- // VERY limited support for SDP munging. Limited to:
- // * changing the order of codecs
- sections = SDPUtils.splitSections(description.sdp);
- sessionpart = sections.shift();
- sections.forEach(function(mediaSection, sdpMLineIndex) {
- var caps = SDPUtils.parseRtpParameters(mediaSection);
- pc.transceivers[sdpMLineIndex].localCapabilities = caps;
- });
-
- this.transceivers.forEach(function(transceiver, sdpMLineIndex) {
- pc._gather(transceiver.mid, sdpMLineIndex);
- });
- } else if (description.type === 'answer') {
- sections = SDPUtils.splitSections(pc.remoteDescription.sdp);
- sessionpart = sections.shift();
- var isIceLite = SDPUtils.matchPrefix(sessionpart,
- 'a=ice-lite').length > 0;
- sections.forEach(function(mediaSection, sdpMLineIndex) {
- var transceiver = pc.transceivers[sdpMLineIndex];
- var iceGatherer = transceiver.iceGatherer;
- var iceTransport = transceiver.iceTransport;
- var dtlsTransport = transceiver.dtlsTransport;
- var localCapabilities = transceiver.localCapabilities;
- var remoteCapabilities = transceiver.remoteCapabilities;
-
- // treat bundle-only as not-rejected.
- var rejected = SDPUtils.isRejected(mediaSection) &&
- SDPUtils.matchPrefix(mediaSection, 'a=bundle-only').length === 0;
-
- if (!rejected && !transceiver.isDatachannel) {
- var remoteIceParameters = SDPUtils.getIceParameters(
- mediaSection, sessionpart);
- var remoteDtlsParameters = SDPUtils.getDtlsParameters(
- mediaSection, sessionpart);
- if (isIceLite) {
- remoteDtlsParameters.role = 'server';
- }
-
- if (!pc.usingBundle || sdpMLineIndex === 0) {
- pc._gather(transceiver.mid, sdpMLineIndex);
- if (iceTransport.state === 'new') {
- iceTransport.start(iceGatherer, remoteIceParameters,
- isIceLite ? 'controlling' : 'controlled');
- }
- if (dtlsTransport.state === 'new') {
- dtlsTransport.start(remoteDtlsParameters);
- }
- }
-
- // Calculate intersection of capabilities.
- var params = getCommonCapabilities(localCapabilities,
- remoteCapabilities);
-
- // Start the RTCRtpSender. The RTCRtpReceiver for this
- // transceiver has already been started in setRemoteDescription.
- pc._transceive(transceiver,
- params.codecs.length > 0,
- false);
- }
- });
- }
-
- this.localDescription = {
- type: description.type,
- sdp: description.sdp
- };
- switch (description.type) {
- case 'offer':
- this._updateSignalingState('have-local-offer');
- break;
- case 'answer':
- this._updateSignalingState('stable');
- break;
- default:
- throw new TypeError('unsupported type "' + description.type +
- '"');
- }
-
- return Promise.resolve();
- };
-
- RTCPeerConnection.prototype.setRemoteDescription = function(description) {
- var pc = this;
-
- if (!isActionAllowedInSignalingState('setRemoteDescription',
- description.type, this.signalingState) || this._isClosed) {
- return Promise.reject(makeError('InvalidStateError',
- 'Can not set remote ' + description.type +
- ' in state ' + pc.signalingState));
- }
-
- var streams = {};
- this.remoteStreams.forEach(function(stream) {
- streams[stream.id] = stream;
- });
- var receiverList = [];
- var sections = SDPUtils.splitSections(description.sdp);
- var sessionpart = sections.shift();
- var isIceLite = SDPUtils.matchPrefix(sessionpart,
- 'a=ice-lite').length > 0;
- var usingBundle = SDPUtils.matchPrefix(sessionpart,
- 'a=group:BUNDLE ').length > 0;
- this.usingBundle = usingBundle;
- var iceOptions = SDPUtils.matchPrefix(sessionpart,
- 'a=ice-options:')[0];
- if (iceOptions) {
- this.canTrickleIceCandidates = iceOptions.substr(14).split(' ')
- .indexOf('trickle') >= 0;
- } else {
- this.canTrickleIceCandidates = false;
- }
-
- sections.forEach(function(mediaSection, sdpMLineIndex) {
- var lines = SDPUtils.splitLines(mediaSection);
- var kind = SDPUtils.getKind(mediaSection);
- // treat bundle-only as not-rejected.
- var rejected = SDPUtils.isRejected(mediaSection) &&
- SDPUtils.matchPrefix(mediaSection, 'a=bundle-only').length === 0;
- var protocol = lines[0].substr(2).split(' ')[2];
-
- var direction = SDPUtils.getDirection(mediaSection, sessionpart);
- var remoteMsid = SDPUtils.parseMsid(mediaSection);
-
- var mid = SDPUtils.getMid(mediaSection) || SDPUtils.generateIdentifier();
-
- // Reject datachannels which are not implemented yet.
- if (kind === 'application' && protocol === 'DTLS/SCTP') {
- pc.transceivers[sdpMLineIndex] = {
- mid: mid,
- isDatachannel: true
- };
- return;
- }
-
- var transceiver;
- var iceGatherer;
- var iceTransport;
- var dtlsTransport;
- var rtpReceiver;
- var sendEncodingParameters;
- var recvEncodingParameters;
- var localCapabilities;
-
- var track;
- // FIXME: ensure the mediaSection has rtcp-mux set.
- var remoteCapabilities = SDPUtils.parseRtpParameters(mediaSection);
- var remoteIceParameters;
- var remoteDtlsParameters;
- if (!rejected) {
- remoteIceParameters = SDPUtils.getIceParameters(mediaSection,
- sessionpart);
- remoteDtlsParameters = SDPUtils.getDtlsParameters(mediaSection,
- sessionpart);
- remoteDtlsParameters.role = 'client';
- }
- recvEncodingParameters =
- SDPUtils.parseRtpEncodingParameters(mediaSection);
-
- var rtcpParameters = SDPUtils.parseRtcpParameters(mediaSection);
-
- var isComplete = SDPUtils.matchPrefix(mediaSection,
- 'a=end-of-candidates', sessionpart).length > 0;
- var cands = SDPUtils.matchPrefix(mediaSection, 'a=candidate:')
- .map(function(cand) {
- return SDPUtils.parseCandidate(cand);
- })
- .filter(function(cand) {
- return cand.component === 1;
- });
-
- // Check if we can use BUNDLE and dispose transports.
- if ((description.type === 'offer' || description.type === 'answer') &&
- !rejected && usingBundle && sdpMLineIndex > 0 &&
- pc.transceivers[sdpMLineIndex]) {
- pc._disposeIceAndDtlsTransports(sdpMLineIndex);
- pc.transceivers[sdpMLineIndex].iceGatherer =
- pc.transceivers[0].iceGatherer;
- pc.transceivers[sdpMLineIndex].iceTransport =
- pc.transceivers[0].iceTransport;
- pc.transceivers[sdpMLineIndex].dtlsTransport =
- pc.transceivers[0].dtlsTransport;
- if (pc.transceivers[sdpMLineIndex].rtpSender) {
- pc.transceivers[sdpMLineIndex].rtpSender.setTransport(
- pc.transceivers[0].dtlsTransport);
- }
- if (pc.transceivers[sdpMLineIndex].rtpReceiver) {
- pc.transceivers[sdpMLineIndex].rtpReceiver.setTransport(
- pc.transceivers[0].dtlsTransport);
- }
- }
- if (description.type === 'offer' && !rejected) {
- transceiver = pc.transceivers[sdpMLineIndex] ||
- pc._createTransceiver(kind);
- transceiver.mid = mid;
-
- if (!transceiver.iceGatherer) {
- transceiver.iceGatherer = pc._createIceGatherer(sdpMLineIndex,
- usingBundle);
- }
-
- if (cands.length && transceiver.iceTransport.state === 'new') {
- if (isComplete && (!usingBundle || sdpMLineIndex === 0)) {
- transceiver.iceTransport.setRemoteCandidates(cands);
- } else {
- cands.forEach(function(candidate) {
- maybeAddCandidate(transceiver.iceTransport, candidate);
- });
- }
- }
-
- localCapabilities = window.RTCRtpReceiver.getCapabilities(kind);
-
- // filter RTX until additional stuff needed for RTX is implemented
- // in adapter.js
- if (edgeVersion < 15019) {
- localCapabilities.codecs = localCapabilities.codecs.filter(
- function(codec) {
- return codec.name !== 'rtx';
- });
- }
-
- sendEncodingParameters = transceiver.sendEncodingParameters || [{
- ssrc: (2 * sdpMLineIndex + 2) * 1001
- }];
-
- // TODO: rewrite to use http://w3c.github.io/webrtc-pc/#set-associated-remote-streams
- var isNewTrack = false;
- if (direction === 'sendrecv' || direction === 'sendonly') {
- isNewTrack = !transceiver.rtpReceiver;
- rtpReceiver = transceiver.rtpReceiver ||
- new window.RTCRtpReceiver(transceiver.dtlsTransport, kind);
-
- if (isNewTrack) {
- var stream;
- track = rtpReceiver.track;
- // FIXME: does not work with Plan B.
- if (remoteMsid && remoteMsid.stream === '-') {
- // no-op. a stream id of '-' means: no associated stream.
- } else if (remoteMsid) {
- if (!streams[remoteMsid.stream]) {
- streams[remoteMsid.stream] = new window.MediaStream();
- Object.defineProperty(streams[remoteMsid.stream], 'id', {
- get: function() {
- return remoteMsid.stream;
- }
- });
- }
- Object.defineProperty(track, 'id', {
- get: function() {
- return remoteMsid.track;
- }
- });
- stream = streams[remoteMsid.stream];
- } else {
- if (!streams.default) {
- streams.default = new window.MediaStream();
- }
- stream = streams.default;
- }
- if (stream) {
- addTrackToStreamAndFireEvent(track, stream);
- transceiver.associatedRemoteMediaStreams.push(stream);
- }
- receiverList.push([track, rtpReceiver, stream]);
- }
- } else if (transceiver.rtpReceiver && transceiver.rtpReceiver.track) {
- transceiver.associatedRemoteMediaStreams.forEach(function(s) {
- var nativeTrack = s.getTracks().find(function(t) {
- return t.id === transceiver.rtpReceiver.track.id;
- });
- if (nativeTrack) {
- removeTrackFromStreamAndFireEvent(nativeTrack, s);
- }
- });
- transceiver.associatedRemoteMediaStreams = [];
- }
-
- transceiver.localCapabilities = localCapabilities;
- transceiver.remoteCapabilities = remoteCapabilities;
- transceiver.rtpReceiver = rtpReceiver;
- transceiver.rtcpParameters = rtcpParameters;
- transceiver.sendEncodingParameters = sendEncodingParameters;
- transceiver.recvEncodingParameters = recvEncodingParameters;
-
- // Start the RTCRtpReceiver now. The RTPSender is started in
- // setLocalDescription.
- pc._transceive(pc.transceivers[sdpMLineIndex],
- false,
- isNewTrack);
- } else if (description.type === 'answer' && !rejected) {
- transceiver = pc.transceivers[sdpMLineIndex];
- iceGatherer = transceiver.iceGatherer;
- iceTransport = transceiver.iceTransport;
- dtlsTransport = transceiver.dtlsTransport;
- rtpReceiver = transceiver.rtpReceiver;
- sendEncodingParameters = transceiver.sendEncodingParameters;
- localCapabilities = transceiver.localCapabilities;
-
- pc.transceivers[sdpMLineIndex].recvEncodingParameters =
- recvEncodingParameters;
- pc.transceivers[sdpMLineIndex].remoteCapabilities =
- remoteCapabilities;
- pc.transceivers[sdpMLineIndex].rtcpParameters = rtcpParameters;
-
- if (cands.length && iceTransport.state === 'new') {
- if ((isIceLite || isComplete) &&
- (!usingBundle || sdpMLineIndex === 0)) {
- iceTransport.setRemoteCandidates(cands);
- } else {
- cands.forEach(function(candidate) {
- maybeAddCandidate(transceiver.iceTransport, candidate);
- });
- }
- }
-
- if (!usingBundle || sdpMLineIndex === 0) {
- if (iceTransport.state === 'new') {
- iceTransport.start(iceGatherer, remoteIceParameters,
- 'controlling');
- }
- if (dtlsTransport.state === 'new') {
- dtlsTransport.start(remoteDtlsParameters);
- }
- }
-
- pc._transceive(transceiver,
- direction === 'sendrecv' || direction === 'recvonly',
- direction === 'sendrecv' || direction === 'sendonly');
-
- // TODO: rewrite to use http://w3c.github.io/webrtc-pc/#set-associated-remote-streams
- if (rtpReceiver &&
- (direction === 'sendrecv' || direction === 'sendonly')) {
- track = rtpReceiver.track;
- if (remoteMsid) {
- if (!streams[remoteMsid.stream]) {
- streams[remoteMsid.stream] = new window.MediaStream();
- }
- addTrackToStreamAndFireEvent(track, streams[remoteMsid.stream]);
- receiverList.push([track, rtpReceiver, streams[remoteMsid.stream]]);
- } else {
- if (!streams.default) {
- streams.default = new window.MediaStream();
- }
- addTrackToStreamAndFireEvent(track, streams.default);
- receiverList.push([track, rtpReceiver, streams.default]);
- }
- } else {
- // FIXME: actually the receiver should be created later.
- delete transceiver.rtpReceiver;
- }
- }
- });
-
- if (this._dtlsRole === undefined) {
- this._dtlsRole = description.type === 'offer' ? 'active' : 'passive';
- }
-
- this.remoteDescription = {
- type: description.type,
- sdp: description.sdp
- };
- switch (description.type) {
- case 'offer':
- this._updateSignalingState('have-remote-offer');
- break;
- case 'answer':
- this._updateSignalingState('stable');
- break;
- default:
- throw new TypeError('unsupported type "' + description.type +
- '"');
- }
- Object.keys(streams).forEach(function(sid) {
- var stream = streams[sid];
- if (stream.getTracks().length) {
- if (pc.remoteStreams.indexOf(stream) === -1) {
- pc.remoteStreams.push(stream);
- var event = new Event('addstream');
- event.stream = stream;
- window.setTimeout(function() {
- pc._dispatchEvent('addstream', event);
- });
- }
-
- receiverList.forEach(function(item) {
- var track = item[0];
- var receiver = item[1];
- if (stream.id !== item[2].id) {
- return;
- }
- fireAddTrack(pc, track, receiver, [stream]);
- });
- }
- });
- receiverList.forEach(function(item) {
- if (item[2]) {
- return;
- }
- fireAddTrack(pc, item[0], item[1], []);
- });
-
- // check whether addIceCandidate({}) was called within four seconds after
- // setRemoteDescription.
- window.setTimeout(function() {
- if (!(pc && pc.transceivers)) {
- return;
- }
- pc.transceivers.forEach(function(transceiver) {
- if (transceiver.iceTransport &&
- transceiver.iceTransport.state === 'new' &&
- transceiver.iceTransport.getRemoteCandidates().length > 0) {
- console.warn('Timeout for addRemoteCandidate. Consider sending ' +
- 'an end-of-candidates notification');
- transceiver.iceTransport.addRemoteCandidate({});
- }
- });
- }, 4000);
-
- return Promise.resolve();
- };
-
- RTCPeerConnection.prototype.close = function() {
- this.transceivers.forEach(function(transceiver) {
- /* not yet
- if (transceiver.iceGatherer) {
- transceiver.iceGatherer.close();
- }
- */
- if (transceiver.iceTransport) {
- transceiver.iceTransport.stop();
- }
- if (transceiver.dtlsTransport) {
- transceiver.dtlsTransport.stop();
- }
- if (transceiver.rtpSender) {
- transceiver.rtpSender.stop();
- }
- if (transceiver.rtpReceiver) {
- transceiver.rtpReceiver.stop();
- }
- });
- // FIXME: clean up tracks, local streams, remote streams, etc
- this._isClosed = true;
- this._updateSignalingState('closed');
- };
-
- // Update the signaling state.
- RTCPeerConnection.prototype._updateSignalingState = function(newState) {
- this.signalingState = newState;
- var event = new Event('signalingstatechange');
- this._dispatchEvent('signalingstatechange', event);
- };
-
- // Determine whether to fire the negotiationneeded event.
- RTCPeerConnection.prototype._maybeFireNegotiationNeeded = function() {
- var pc = this;
- if (this.signalingState !== 'stable' || this.needNegotiation === true) {
- return;
- }
- this.needNegotiation = true;
- window.setTimeout(function() {
- if (pc.needNegotiation === false) {
- return;
- }
- pc.needNegotiation = false;
- var event = new Event('negotiationneeded');
- pc._dispatchEvent('negotiationneeded', event);
- }, 0);
- };
-
- // Update the connection state.
- RTCPeerConnection.prototype._updateConnectionState = function() {
- var newState;
- var states = {
- 'new': 0,
- closed: 0,
- connecting: 0,
- checking: 0,
- connected: 0,
- completed: 0,
- disconnected: 0,
- failed: 0
- };
- this.transceivers.forEach(function(transceiver) {
- states[transceiver.iceTransport.state]++;
- states[transceiver.dtlsTransport.state]++;
- });
- // ICETransport.completed and connected are the same for this purpose.
- states.connected += states.completed;
-
- newState = 'new';
- if (states.failed > 0) {
- newState = 'failed';
- } else if (states.connecting > 0 || states.checking > 0) {
- newState = 'connecting';
- } else if (states.disconnected > 0) {
- newState = 'disconnected';
- } else if (states.new > 0) {
- newState = 'new';
- } else if (states.connected > 0 || states.completed > 0) {
- newState = 'connected';
- }
-
- if (newState !== this.iceConnectionState) {
- this.iceConnectionState = newState;
- var event = new Event('iceconnectionstatechange');
- this._dispatchEvent('iceconnectionstatechange', event);
- }
- };
-
- RTCPeerConnection.prototype.createOffer = function() {
- var pc = this;
-
- if (this._isClosed) {
- return Promise.reject(makeError('InvalidStateError',
- 'Can not call createOffer after close'));
- }
-
- var numAudioTracks = this.transceivers.filter(function(t) {
- return t.kind === 'audio';
- }).length;
- var numVideoTracks = this.transceivers.filter(function(t) {
- return t.kind === 'video';
- }).length;
-
- // Determine number of audio and video tracks we need to send/recv.
- var offerOptions = arguments[0];
- if (offerOptions) {
- // Reject Chrome legacy constraints.
- if (offerOptions.mandatory || offerOptions.optional) {
- throw new TypeError(
- 'Legacy mandatory/optional constraints not supported.');
- }
- if (offerOptions.offerToReceiveAudio !== undefined) {
- if (offerOptions.offerToReceiveAudio === true) {
- numAudioTracks = 1;
- } else if (offerOptions.offerToReceiveAudio === false) {
- numAudioTracks = 0;
- } else {
- numAudioTracks = offerOptions.offerToReceiveAudio;
- }
- }
- if (offerOptions.offerToReceiveVideo !== undefined) {
- if (offerOptions.offerToReceiveVideo === true) {
- numVideoTracks = 1;
- } else if (offerOptions.offerToReceiveVideo === false) {
- numVideoTracks = 0;
- } else {
- numVideoTracks = offerOptions.offerToReceiveVideo;
- }
- }
- }
-
- this.transceivers.forEach(function(transceiver) {
- if (transceiver.kind === 'audio') {
- numAudioTracks--;
- if (numAudioTracks < 0) {
- transceiver.wantReceive = false;
- }
- } else if (transceiver.kind === 'video') {
- numVideoTracks--;
- if (numVideoTracks < 0) {
- transceiver.wantReceive = false;
- }
- }
- });
-
- // Create M-lines for recvonly streams.
- while (numAudioTracks > 0 || numVideoTracks > 0) {
- if (numAudioTracks > 0) {
- this._createTransceiver('audio');
- numAudioTracks--;
- }
- if (numVideoTracks > 0) {
- this._createTransceiver('video');
- numVideoTracks--;
- }
- }
-
- var sdp = SDPUtils.writeSessionBoilerplate(this._sdpSessionId,
- this._sdpSessionVersion++);
- this.transceivers.forEach(function(transceiver, sdpMLineIndex) {
- // For each track, create an ice gatherer, ice transport,
- // dtls transport, potentially rtpsender and rtpreceiver.
- var track = transceiver.track;
- var kind = transceiver.kind;
- var mid = SDPUtils.generateIdentifier();
- transceiver.mid = mid;
-
- if (!transceiver.iceGatherer) {
- transceiver.iceGatherer = pc._createIceGatherer(sdpMLineIndex,
- pc.usingBundle);
- }
-
- var localCapabilities = window.RTCRtpSender.getCapabilities(kind);
- // filter RTX until additional stuff needed for RTX is implemented
- // in adapter.js
- if (edgeVersion < 15019) {
- localCapabilities.codecs = localCapabilities.codecs.filter(
- function(codec) {
- return codec.name !== 'rtx';
- });
- }
- localCapabilities.codecs.forEach(function(codec) {
- // work around https://bugs.chromium.org/p/webrtc/issues/detail?id=6552
- // by adding level-asymmetry-allowed=1
- if (codec.name === 'H264' &&
- codec.parameters['level-asymmetry-allowed'] === undefined) {
- codec.parameters['level-asymmetry-allowed'] = '1';
- }
- });
-
- // generate an ssrc now, to be used later in rtpSender.send
- var sendEncodingParameters = transceiver.sendEncodingParameters || [{
- ssrc: (2 * sdpMLineIndex + 1) * 1001
- }];
- if (track) {
- // add RTX
- if (edgeVersion >= 15019 && kind === 'video' &&
- !sendEncodingParameters[0].rtx) {
- sendEncodingParameters[0].rtx = {
- ssrc: sendEncodingParameters[0].ssrc + 1
- };
- }
- }
-
- if (transceiver.wantReceive) {
- transceiver.rtpReceiver = new window.RTCRtpReceiver(
- transceiver.dtlsTransport, kind);
- }
-
- transceiver.localCapabilities = localCapabilities;
- transceiver.sendEncodingParameters = sendEncodingParameters;
- });
-
- // always offer BUNDLE and dispose on return if not supported.
- if (this._config.bundlePolicy !== 'max-compat') {
- sdp += 'a=group:BUNDLE ' + this.transceivers.map(function(t) {
- return t.mid;
- }).join(' ') + '\r\n';
- }
- sdp += 'a=ice-options:trickle\r\n';
-
- this.transceivers.forEach(function(transceiver, sdpMLineIndex) {
- sdp += writeMediaSection(transceiver, transceiver.localCapabilities,
- 'offer', transceiver.stream, pc._dtlsRole);
- sdp += 'a=rtcp-rsize\r\n';
-
- if (transceiver.iceGatherer && pc.iceGatheringState !== 'new' &&
- (sdpMLineIndex === 0 || !pc.usingBundle)) {
- transceiver.iceGatherer.getLocalCandidates().forEach(function(cand) {
- cand.component = 1;
- sdp += 'a=' + SDPUtils.writeCandidate(cand) + '\r\n';
- });
-
- if (transceiver.iceGatherer.state === 'completed') {
- sdp += 'a=end-of-candidates\r\n';
- }
- }
- });
-
- var desc = new window.RTCSessionDescription({
- type: 'offer',
- sdp: sdp
- });
- return Promise.resolve(desc);
- };
-
- RTCPeerConnection.prototype.createAnswer = function() {
- var pc = this;
-
- if (this._isClosed) {
- return Promise.reject(makeError('InvalidStateError',
- 'Can not call createAnswer after close'));
- }
-
- var sdp = SDPUtils.writeSessionBoilerplate(this._sdpSessionId,
- this._sdpSessionVersion++);
- if (this.usingBundle) {
- sdp += 'a=group:BUNDLE ' + this.transceivers.map(function(t) {
- return t.mid;
- }).join(' ') + '\r\n';
- }
- var mediaSectionsInOffer = SDPUtils.splitSections(
- this.remoteDescription.sdp).length - 1;
- this.transceivers.forEach(function(transceiver, sdpMLineIndex) {
- if (sdpMLineIndex + 1 > mediaSectionsInOffer) {
- return;
- }
- if (transceiver.isDatachannel) {
- sdp += 'm=application 0 DTLS/SCTP 5000\r\n' +
- 'c=IN IP4 0.0.0.0\r\n' +
- 'a=mid:' + transceiver.mid + '\r\n';
- return;
- }
-
- // FIXME: look at direction.
- if (transceiver.stream) {
- var localTrack;
- if (transceiver.kind === 'audio') {
- localTrack = transceiver.stream.getAudioTracks()[0];
- } else if (transceiver.kind === 'video') {
- localTrack = transceiver.stream.getVideoTracks()[0];
- }
- if (localTrack) {
- // add RTX
- if (edgeVersion >= 15019 && transceiver.kind === 'video' &&
- !transceiver.sendEncodingParameters[0].rtx) {
- transceiver.sendEncodingParameters[0].rtx = {
- ssrc: transceiver.sendEncodingParameters[0].ssrc + 1
- };
- }
- }
- }
-
- // Calculate intersection of capabilities.
- var commonCapabilities = getCommonCapabilities(
- transceiver.localCapabilities,
- transceiver.remoteCapabilities);
-
- var hasRtx = commonCapabilities.codecs.filter(function(c) {
- return c.name.toLowerCase() === 'rtx';
- }).length;
- if (!hasRtx && transceiver.sendEncodingParameters[0].rtx) {
- delete transceiver.sendEncodingParameters[0].rtx;
- }
-
- sdp += writeMediaSection(transceiver, commonCapabilities,
- 'answer', transceiver.stream, pc._dtlsRole);
- if (transceiver.rtcpParameters &&
- transceiver.rtcpParameters.reducedSize) {
- sdp += 'a=rtcp-rsize\r\n';
- }
- });
-
- var desc = new window.RTCSessionDescription({
- type: 'answer',
- sdp: sdp
- });
- return Promise.resolve(desc);
- };
-
- RTCPeerConnection.prototype.addIceCandidate = function(candidate) {
- var sections;
- if (!candidate || candidate.candidate === '') {
- for (var j = 0; j < this.transceivers.length; j++) {
- if (this.transceivers[j].isDatachannel) {
- continue;
- }
- this.transceivers[j].iceTransport.addRemoteCandidate({});
- sections = SDPUtils.splitSections(this.remoteDescription.sdp);
- sections[j + 1] += 'a=end-of-candidates\r\n';
- this.remoteDescription.sdp = sections.join('');
- if (this.usingBundle) {
- break;
- }
- }
- } else if (!(candidate.sdpMLineIndex !== undefined || candidate.sdpMid)) {
- throw new TypeError('sdpMLineIndex or sdpMid required');
- } else if (!this.remoteDescription) {
- return Promise.reject(makeError('InvalidStateError',
- 'Can not add ICE candidate without a remote description'));
- } else {
- var sdpMLineIndex = candidate.sdpMLineIndex;
- if (candidate.sdpMid) {
- for (var i = 0; i < this.transceivers.length; i++) {
- if (this.transceivers[i].mid === candidate.sdpMid) {
- sdpMLineIndex = i;
- break;
- }
- }
- }
- var transceiver = this.transceivers[sdpMLineIndex];
- if (transceiver) {
- if (transceiver.isDatachannel) {
- return Promise.resolve();
- }
- var cand = Object.keys(candidate.candidate).length > 0 ?
- SDPUtils.parseCandidate(candidate.candidate) : {};
- // Ignore Chrome's invalid candidates since Edge does not like them.
- if (cand.protocol === 'tcp' && (cand.port === 0 || cand.port === 9)) {
- return Promise.resolve();
- }
- // Ignore RTCP candidates, we assume RTCP-MUX.
- if (cand.component && cand.component !== 1) {
- return Promise.resolve();
- }
- // when using bundle, avoid adding candidates to the wrong
- // ice transport. And avoid adding candidates added in the SDP.
- if (sdpMLineIndex === 0 || (sdpMLineIndex > 0 &&
- transceiver.iceTransport !== this.transceivers[0].iceTransport)) {
- if (!maybeAddCandidate(transceiver.iceTransport, cand)) {
- return Promise.reject(makeError('OperationError',
- 'Can not add ICE candidate'));
- }
- }
-
- // update the remoteDescription.
- var candidateString = candidate.candidate.trim();
- if (candidateString.indexOf('a=') === 0) {
- candidateString = candidateString.substr(2);
- }
- sections = SDPUtils.splitSections(this.remoteDescription.sdp);
- sections[sdpMLineIndex + 1] += 'a=' +
- (cand.type ? candidateString : 'end-of-candidates')
- + '\r\n';
- this.remoteDescription.sdp = sections.join('');
- } else {
- return Promise.reject(makeError('OperationError',
- 'Can not add ICE candidate'));
- }
- }
- return Promise.resolve();
- };
-
- RTCPeerConnection.prototype.getStats = function() {
- var promises = [];
- this.transceivers.forEach(function(transceiver) {
- ['rtpSender', 'rtpReceiver', 'iceGatherer', 'iceTransport',
- 'dtlsTransport'].forEach(function(method) {
- if (transceiver[method]) {
- promises.push(transceiver[method].getStats());
- }
- });
- });
- var fixStatsType = function(stat) {
- return {
- inboundrtp: 'inbound-rtp',
- outboundrtp: 'outbound-rtp',
- candidatepair: 'candidate-pair',
- localcandidate: 'local-candidate',
- remotecandidate: 'remote-candidate'
- }[stat.type] || stat.type;
- };
- return new Promise(function(resolve) {
- // shim getStats with maplike support
- var results = new Map();
- Promise.all(promises).then(function(res) {
- res.forEach(function(result) {
- Object.keys(result).forEach(function(id) {
- result[id].type = fixStatsType(result[id]);
- results.set(id, result[id]);
- });
- });
- resolve(results);
- });
- });
- };
-
- // legacy callback shims. Should be moved to adapter.js some days.
- var methods = ['createOffer', 'createAnswer'];
- methods.forEach(function(method) {
- var nativeMethod = RTCPeerConnection.prototype[method];
- RTCPeerConnection.prototype[method] = function() {
- var args = arguments;
- if (typeof args[0] === 'function' ||
- typeof args[1] === 'function') { // legacy
- return nativeMethod.apply(this, [arguments[2]])
- .then(function(description) {
- if (typeof args[0] === 'function') {
- args[0].apply(null, [description]);
- }
- }, function(error) {
- if (typeof args[1] === 'function') {
- args[1].apply(null, [error]);
- }
- });
- }
- return nativeMethod.apply(this, arguments);
- };
- });
-
- methods = ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate'];
- methods.forEach(function(method) {
- var nativeMethod = RTCPeerConnection.prototype[method];
- RTCPeerConnection.prototype[method] = function() {
- var args = arguments;
- if (typeof args[1] === 'function' ||
- typeof args[2] === 'function') { // legacy
- return nativeMethod.apply(this, arguments)
- .then(function() {
- if (typeof args[1] === 'function') {
- args[1].apply(null);
- }
- }, function(error) {
- if (typeof args[2] === 'function') {
- args[2].apply(null, [error]);
- }
- });
- }
- return nativeMethod.apply(this, arguments);
- };
- });
-
- // getStats is special. It doesn't have a spec legacy method yet we support
- // getStats(something, cb) without error callbacks.
- ['getStats'].forEach(function(method) {
- var nativeMethod = RTCPeerConnection.prototype[method];
- RTCPeerConnection.prototype[method] = function() {
- var args = arguments;
- if (typeof args[1] === 'function') {
- return nativeMethod.apply(this, arguments)
- .then(function() {
- if (typeof args[1] === 'function') {
- args[1].apply(null);
- }
- });
- }
- return nativeMethod.apply(this, arguments);
- };
- });
-
- return RTCPeerConnection;
-};
-
-},{"sdp":2}],2:[function(require,module,exports){
- /* eslint-env node */
-'use strict';
-
-// SDP helpers.
-var SDPUtils = {};
-
-// Generate an alphanumeric identifier for cname or mids.
-// TODO: use UUIDs instead? https://gist.github.com/jed/982883
-SDPUtils.generateIdentifier = function() {
- return Math.random().toString(36).substr(2, 10);
-};
-
-// The RTCP CNAME used by all peerconnections from the same JS.
-SDPUtils.localCName = SDPUtils.generateIdentifier();
-
-// Splits SDP into lines, dealing with both CRLF and LF.
-SDPUtils.splitLines = function(blob) {
- return blob.trim().split('\n').map(function(line) {
- return line.trim();
- });
-};
-// Splits SDP into sessionpart and mediasections. Ensures CRLF.
-SDPUtils.splitSections = function(blob) {
- var parts = blob.split('\nm=');
- return parts.map(function(part, index) {
- return (index > 0 ? 'm=' + part : part).trim() + '\r\n';
- });
-};
-
-// Returns lines that start with a certain prefix.
-SDPUtils.matchPrefix = function(blob, prefix) {
- return SDPUtils.splitLines(blob).filter(function(line) {
- return line.indexOf(prefix) === 0;
- });
-};
-
-// Parses an ICE candidate line. Sample input:
-// candidate:702786350 2 udp 41819902 8.8.8.8 60769 typ relay raddr 8.8.8.8
-// rport 55996"
-SDPUtils.parseCandidate = function(line) {
- var parts;
- // Parse both variants.
- if (line.indexOf('a=candidate:') === 0) {
- parts = line.substring(12).split(' ');
- } else {
- parts = line.substring(10).split(' ');
- }
-
- var candidate = {
- foundation: parts[0],
- component: parseInt(parts[1], 10),
- protocol: parts[2].toLowerCase(),
- priority: parseInt(parts[3], 10),
- ip: parts[4],
- port: parseInt(parts[5], 10),
- // skip parts[6] == 'typ'
- type: parts[7]
- };
-
- for (var i = 8; i < parts.length; i += 2) {
- switch (parts[i]) {
- case 'raddr':
- candidate.relatedAddress = parts[i + 1];
- break;
- case 'rport':
- candidate.relatedPort = parseInt(parts[i + 1], 10);
- break;
- case 'tcptype':
- candidate.tcpType = parts[i + 1];
- break;
- case 'ufrag':
- candidate.ufrag = parts[i + 1]; // for backward compability.
- candidate.usernameFragment = parts[i + 1];
- break;
- default: // extension handling, in particular ufrag
- candidate[parts[i]] = parts[i + 1];
- break;
- }
- }
- return candidate;
-};
-
-// Translates a candidate object into SDP candidate attribute.
-SDPUtils.writeCandidate = function(candidate) {
- var sdp = [];
- sdp.push(candidate.foundation);
- sdp.push(candidate.component);
- sdp.push(candidate.protocol.toUpperCase());
- sdp.push(candidate.priority);
- sdp.push(candidate.ip);
- sdp.push(candidate.port);
-
- var type = candidate.type;
- sdp.push('typ');
- sdp.push(type);
- if (type !== 'host' && candidate.relatedAddress &&
- candidate.relatedPort) {
- sdp.push('raddr');
- sdp.push(candidate.relatedAddress); // was: relAddr
- sdp.push('rport');
- sdp.push(candidate.relatedPort); // was: relPort
- }
- if (candidate.tcpType && candidate.protocol.toLowerCase() === 'tcp') {
- sdp.push('tcptype');
- sdp.push(candidate.tcpType);
- }
- if (candidate.ufrag) {
- sdp.push('ufrag');
- sdp.push(candidate.ufrag);
- }
- return 'candidate:' + sdp.join(' ');
-};
-
-// Parses an ice-options line, returns an array of option tags.
-// a=ice-options:foo bar
-SDPUtils.parseIceOptions = function(line) {
- return line.substr(14).split(' ');
-}
-
-// Parses an rtpmap line, returns RTCRtpCoddecParameters. Sample input:
-// a=rtpmap:111 opus/48000/2
-SDPUtils.parseRtpMap = function(line) {
- var parts = line.substr(9).split(' ');
- var parsed = {
- payloadType: parseInt(parts.shift(), 10) // was: id
- };
-
- parts = parts[0].split('/');
-
- parsed.name = parts[0];
- parsed.clockRate = parseInt(parts[1], 10); // was: clockrate
- // was: channels
- parsed.numChannels = parts.length === 3 ? parseInt(parts[2], 10) : 1;
- return parsed;
-};
-
-// Generate an a=rtpmap line from RTCRtpCodecCapability or
-// RTCRtpCodecParameters.
-SDPUtils.writeRtpMap = function(codec) {
- var pt = codec.payloadType;
- if (codec.preferredPayloadType !== undefined) {
- pt = codec.preferredPayloadType;
- }
- return 'a=rtpmap:' + pt + ' ' + codec.name + '/' + codec.clockRate +
- (codec.numChannels !== 1 ? '/' + codec.numChannels : '') + '\r\n';
-};
-
-// Parses an a=extmap line (headerextension from RFC 5285). Sample input:
-// a=extmap:2 urn:ietf:params:rtp-hdrext:toffset
-// a=extmap:2/sendonly urn:ietf:params:rtp-hdrext:toffset
-SDPUtils.parseExtmap = function(line) {
- var parts = line.substr(9).split(' ');
- return {
- id: parseInt(parts[0], 10),
- direction: parts[0].indexOf('/') > 0 ? parts[0].split('/')[1] : 'sendrecv',
- uri: parts[1]
- };
-};
-
-// Generates a=extmap line from RTCRtpHeaderExtensionParameters or
-// RTCRtpHeaderExtension.
-SDPUtils.writeExtmap = function(headerExtension) {
- return 'a=extmap:' + (headerExtension.id || headerExtension.preferredId) +
- (headerExtension.direction && headerExtension.direction !== 'sendrecv'
- ? '/' + headerExtension.direction
- : '') +
- ' ' + headerExtension.uri + '\r\n';
-};
-
-// Parses an ftmp line, returns dictionary. Sample input:
-// a=fmtp:96 vbr=on;cng=on
-// Also deals with vbr=on; cng=on
-SDPUtils.parseFmtp = function(line) {
- var parsed = {};
- var kv;
- var parts = line.substr(line.indexOf(' ') + 1).split(';');
- for (var j = 0; j < parts.length; j++) {
- kv = parts[j].trim().split('=');
- parsed[kv[0].trim()] = kv[1];
- }
- return parsed;
-};
-
-// Generates an a=ftmp line from RTCRtpCodecCapability or RTCRtpCodecParameters.
-SDPUtils.writeFmtp = function(codec) {
- var line = '';
- var pt = codec.payloadType;
- if (codec.preferredPayloadType !== undefined) {
- pt = codec.preferredPayloadType;
- }
- if (codec.parameters && Object.keys(codec.parameters).length) {
- var params = [];
- Object.keys(codec.parameters).forEach(function(param) {
- params.push(param + '=' + codec.parameters[param]);
- });
- line += 'a=fmtp:' + pt + ' ' + params.join(';') + '\r\n';
- }
- return line;
-};
-
-// Parses an rtcp-fb line, returns RTCPRtcpFeedback object. Sample input:
-// a=rtcp-fb:98 nack rpsi
-SDPUtils.parseRtcpFb = function(line) {
- var parts = line.substr(line.indexOf(' ') + 1).split(' ');
- return {
- type: parts.shift(),
- parameter: parts.join(' ')
- };
-};
-// Generate a=rtcp-fb lines from RTCRtpCodecCapability or RTCRtpCodecParameters.
-SDPUtils.writeRtcpFb = function(codec) {
- var lines = '';
- var pt = codec.payloadType;
- if (codec.preferredPayloadType !== undefined) {
- pt = codec.preferredPayloadType;
- }
- if (codec.rtcpFeedback && codec.rtcpFeedback.length) {
- // FIXME: special handling for trr-int?
- codec.rtcpFeedback.forEach(function(fb) {
- lines += 'a=rtcp-fb:' + pt + ' ' + fb.type +
- (fb.parameter && fb.parameter.length ? ' ' + fb.parameter : '') +
- '\r\n';
- });
- }
- return lines;
-};
-
-// Parses an RFC 5576 ssrc media attribute. Sample input:
-// a=ssrc:3735928559 cname:something
-SDPUtils.parseSsrcMedia = function(line) {
- var sp = line.indexOf(' ');
- var parts = {
- ssrc: parseInt(line.substr(7, sp - 7), 10)
- };
- var colon = line.indexOf(':', sp);
- if (colon > -1) {
- parts.attribute = line.substr(sp + 1, colon - sp - 1);
- parts.value = line.substr(colon + 1);
- } else {
- parts.attribute = line.substr(sp + 1);
- }
- return parts;
-};
-
-// Extracts the MID (RFC 5888) from a media section.
-// returns the MID or undefined if no mid line was found.
-SDPUtils.getMid = function(mediaSection) {
- var mid = SDPUtils.matchPrefix(mediaSection, 'a=mid:')[0];
- if (mid) {
- return mid.substr(6);
- }
-}
-
-SDPUtils.parseFingerprint = function(line) {
- var parts = line.substr(14).split(' ');
- return {
- algorithm: parts[0].toLowerCase(), // algorithm is case-sensitive in Edge.
- value: parts[1]
- };
-};
-
-// Extracts DTLS parameters from SDP media section or sessionpart.
-// FIXME: for consistency with other functions this should only
-// get the fingerprint line as input. See also getIceParameters.
-SDPUtils.getDtlsParameters = function(mediaSection, sessionpart) {
- var lines = SDPUtils.matchPrefix(mediaSection + sessionpart,
- 'a=fingerprint:');
- // Note: a=setup line is ignored since we use the 'auto' role.
- // Note2: 'algorithm' is not case sensitive except in Edge.
- return {
- role: 'auto',
- fingerprints: lines.map(SDPUtils.parseFingerprint)
- };
-};
-
-// Serializes DTLS parameters to SDP.
-SDPUtils.writeDtlsParameters = function(params, setupType) {
- var sdp = 'a=setup:' + setupType + '\r\n';
- params.fingerprints.forEach(function(fp) {
- sdp += 'a=fingerprint:' + fp.algorithm + ' ' + fp.value + '\r\n';
- });
- return sdp;
-};
-// Parses ICE information from SDP media section or sessionpart.
-// FIXME: for consistency with other functions this should only
-// get the ice-ufrag and ice-pwd lines as input.
-SDPUtils.getIceParameters = function(mediaSection, sessionpart) {
- var lines = SDPUtils.splitLines(mediaSection);
- // Search in session part, too.
- lines = lines.concat(SDPUtils.splitLines(sessionpart));
- var iceParameters = {
- usernameFragment: lines.filter(function(line) {
- return line.indexOf('a=ice-ufrag:') === 0;
- })[0].substr(12),
- password: lines.filter(function(line) {
- return line.indexOf('a=ice-pwd:') === 0;
- })[0].substr(10)
- };
- return iceParameters;
-};
-
-// Serializes ICE parameters to SDP.
-SDPUtils.writeIceParameters = function(params) {
- return 'a=ice-ufrag:' + params.usernameFragment + '\r\n' +
- 'a=ice-pwd:' + params.password + '\r\n';
-};
-
-// Parses the SDP media section and returns RTCRtpParameters.
-SDPUtils.parseRtpParameters = function(mediaSection) {
- var description = {
- codecs: [],
- headerExtensions: [],
- fecMechanisms: [],
- rtcp: []
- };
- var lines = SDPUtils.splitLines(mediaSection);
- var mline = lines[0].split(' ');
- for (var i = 3; i < mline.length; i++) { // find all codecs from mline[3..]
- var pt = mline[i];
- var rtpmapline = SDPUtils.matchPrefix(
- mediaSection, 'a=rtpmap:' + pt + ' ')[0];
- if (rtpmapline) {
- var codec = SDPUtils.parseRtpMap(rtpmapline);
- var fmtps = SDPUtils.matchPrefix(
- mediaSection, 'a=fmtp:' + pt + ' ');
- // Only the first a=fmtp: is considered.
- codec.parameters = fmtps.length ? SDPUtils.parseFmtp(fmtps[0]) : {};
- codec.rtcpFeedback = SDPUtils.matchPrefix(
- mediaSection, 'a=rtcp-fb:' + pt + ' ')
- .map(SDPUtils.parseRtcpFb);
- description.codecs.push(codec);
- // parse FEC mechanisms from rtpmap lines.
- switch (codec.name.toUpperCase()) {
- case 'RED':
- case 'ULPFEC':
- description.fecMechanisms.push(codec.name.toUpperCase());
- break;
- default: // only RED and ULPFEC are recognized as FEC mechanisms.
- break;
- }
- }
- }
- SDPUtils.matchPrefix(mediaSection, 'a=extmap:').forEach(function(line) {
- description.headerExtensions.push(SDPUtils.parseExtmap(line));
- });
- // FIXME: parse rtcp.
- return description;
-};
-
-// Generates parts of the SDP media section describing the capabilities /
-// parameters.
-SDPUtils.writeRtpDescription = function(kind, caps) {
- var sdp = '';
-
- // Build the mline.
- sdp += 'm=' + kind + ' ';
- sdp += caps.codecs.length > 0 ? '9' : '0'; // reject if no codecs.
- sdp += ' UDP/TLS/RTP/SAVPF ';
- sdp += caps.codecs.map(function(codec) {
- if (codec.preferredPayloadType !== undefined) {
- return codec.preferredPayloadType;
- }
- return codec.payloadType;
- }).join(' ') + '\r\n';
-
- sdp += 'c=IN IP4 0.0.0.0\r\n';
- sdp += 'a=rtcp:9 IN IP4 0.0.0.0\r\n';
-
- // Add a=rtpmap lines for each codec. Also fmtp and rtcp-fb.
- caps.codecs.forEach(function(codec) {
- sdp += SDPUtils.writeRtpMap(codec);
- sdp += SDPUtils.writeFmtp(codec);
- sdp += SDPUtils.writeRtcpFb(codec);
- });
- var maxptime = 0;
- caps.codecs.forEach(function(codec) {
- if (codec.maxptime > maxptime) {
- maxptime = codec.maxptime;
- }
- });
- if (maxptime > 0) {
- sdp += 'a=maxptime:' + maxptime + '\r\n';
- }
- sdp += 'a=rtcp-mux\r\n';
-
- caps.headerExtensions.forEach(function(extension) {
- sdp += SDPUtils.writeExtmap(extension);
- });
- // FIXME: write fecMechanisms.
- return sdp;
-};
-
-// Parses the SDP media section and returns an array of
-// RTCRtpEncodingParameters.
-SDPUtils.parseRtpEncodingParameters = function(mediaSection) {
- var encodingParameters = [];
- var description = SDPUtils.parseRtpParameters(mediaSection);
- var hasRed = description.fecMechanisms.indexOf('RED') !== -1;
- var hasUlpfec = description.fecMechanisms.indexOf('ULPFEC') !== -1;
-
- // filter a=ssrc:... cname:, ignore PlanB-msid
- var ssrcs = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:')
- .map(function(line) {
- return SDPUtils.parseSsrcMedia(line);
- })
- .filter(function(parts) {
- return parts.attribute === 'cname';
- });
- var primarySsrc = ssrcs.length > 0 && ssrcs[0].ssrc;
- var secondarySsrc;
-
- var flows = SDPUtils.matchPrefix(mediaSection, 'a=ssrc-group:FID')
- .map(function(line) {
- var parts = line.split(' ');
- parts.shift();
- return parts.map(function(part) {
- return parseInt(part, 10);
- });
- });
- if (flows.length > 0 && flows[0].length > 1 && flows[0][0] === primarySsrc) {
- secondarySsrc = flows[0][1];
- }
-
- description.codecs.forEach(function(codec) {
- if (codec.name.toUpperCase() === 'RTX' && codec.parameters.apt) {
- var encParam = {
- ssrc: primarySsrc,
- codecPayloadType: parseInt(codec.parameters.apt, 10),
- rtx: {
- ssrc: secondarySsrc
- }
- };
- encodingParameters.push(encParam);
- if (hasRed) {
- encParam = JSON.parse(JSON.stringify(encParam));
- encParam.fec = {
- ssrc: secondarySsrc,
- mechanism: hasUlpfec ? 'red+ulpfec' : 'red'
- };
- encodingParameters.push(encParam);
- }
- }
- });
- if (encodingParameters.length === 0 && primarySsrc) {
- encodingParameters.push({
- ssrc: primarySsrc
- });
- }
-
- // we support both b=AS and b=TIAS but interpret AS as TIAS.
- var bandwidth = SDPUtils.matchPrefix(mediaSection, 'b=');
- if (bandwidth.length) {
- if (bandwidth[0].indexOf('b=TIAS:') === 0) {
- bandwidth = parseInt(bandwidth[0].substr(7), 10);
- } else if (bandwidth[0].indexOf('b=AS:') === 0) {
- // use formula from JSEP to convert b=AS to TIAS value.
- bandwidth = parseInt(bandwidth[0].substr(5), 10) * 1000 * 0.95
- - (50 * 40 * 8);
- } else {
- bandwidth = undefined;
- }
- encodingParameters.forEach(function(params) {
- params.maxBitrate = bandwidth;
- });
- }
- return encodingParameters;
-};
-
-// parses http://draft.ortc.org/#rtcrtcpparameters*
-SDPUtils.parseRtcpParameters = function(mediaSection) {
- var rtcpParameters = {};
-
- var cname;
- // Gets the first SSRC. Note that with RTX there might be multiple
- // SSRCs.
- var remoteSsrc = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:')
- .map(function(line) {
- return SDPUtils.parseSsrcMedia(line);
- })
- .filter(function(obj) {
- return obj.attribute === 'cname';
- })[0];
- if (remoteSsrc) {
- rtcpParameters.cname = remoteSsrc.value;
- rtcpParameters.ssrc = remoteSsrc.ssrc;
- }
-
- // Edge uses the compound attribute instead of reducedSize
- // compound is !reducedSize
- var rsize = SDPUtils.matchPrefix(mediaSection, 'a=rtcp-rsize');
- rtcpParameters.reducedSize = rsize.length > 0;
- rtcpParameters.compound = rsize.length === 0;
-
- // parses the rtcp-mux attrŃ–bute.
- // Note that Edge does not support unmuxed RTCP.
- var mux = SDPUtils.matchPrefix(mediaSection, 'a=rtcp-mux');
- rtcpParameters.mux = mux.length > 0;
-
- return rtcpParameters;
-};
-
-// parses either a=msid: or a=ssrc:... msid lines and returns
-// the id of the MediaStream and MediaStreamTrack.
-SDPUtils.parseMsid = function(mediaSection) {
- var parts;
- var spec = SDPUtils.matchPrefix(mediaSection, 'a=msid:');
- if (spec.length === 1) {
- parts = spec[0].substr(7).split(' ');
- return {stream: parts[0], track: parts[1]};
- }
- var planB = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:')
- .map(function(line) {
- return SDPUtils.parseSsrcMedia(line);
- })
- .filter(function(parts) {
- return parts.attribute === 'msid';
- });
- if (planB.length > 0) {
- parts = planB[0].value.split(' ');
- return {stream: parts[0], track: parts[1]};
- }
-};
-
-// Generate a session ID for SDP.
-// https://tools.ietf.org/html/draft-ietf-rtcweb-jsep-20#section-5.2.1
-// recommends using a cryptographically random +ve 64-bit value
-// but right now this should be acceptable and within the right range
-SDPUtils.generateSessionId = function() {
- return Math.random().toString().substr(2, 21);
-};
-
-// Write boilder plate for start of SDP
-// sessId argument is optional - if not supplied it will
-// be generated randomly
-// sessVersion is optional and defaults to 2
-SDPUtils.writeSessionBoilerplate = function(sessId, sessVer) {
- var sessionId;
- var version = sessVer !== undefined ? sessVer : 2;
- if (sessId) {
- sessionId = sessId;
- } else {
- sessionId = SDPUtils.generateSessionId();
- }
- // FIXME: sess-id should be an NTP timestamp.
- return 'v=0\r\n' +
- 'o=thisisadapterortc ' + sessionId + ' ' + version + ' IN IP4 127.0.0.1\r\n' +
- 's=-\r\n' +
- 't=0 0\r\n';
-};
-
-SDPUtils.writeMediaSection = function(transceiver, caps, type, stream) {
- var sdp = SDPUtils.writeRtpDescription(transceiver.kind, caps);
-
- // Map ICE parameters (ufrag, pwd) to SDP.
- sdp += SDPUtils.writeIceParameters(
- transceiver.iceGatherer.getLocalParameters());
-
- // Map DTLS parameters to SDP.
- sdp += SDPUtils.writeDtlsParameters(
- transceiver.dtlsTransport.getLocalParameters(),
- type === 'offer' ? 'actpass' : 'active');
-
- sdp += 'a=mid:' + transceiver.mid + '\r\n';
-
- if (transceiver.direction) {
- sdp += 'a=' + transceiver.direction + '\r\n';
- } else if (transceiver.rtpSender && transceiver.rtpReceiver) {
- sdp += 'a=sendrecv\r\n';
- } else if (transceiver.rtpSender) {
- sdp += 'a=sendonly\r\n';
- } else if (transceiver.rtpReceiver) {
- sdp += 'a=recvonly\r\n';
- } else {
- sdp += 'a=inactive\r\n';
- }
-
- if (transceiver.rtpSender) {
- // spec.
- var msid = 'msid:' + stream.id + ' ' +
- transceiver.rtpSender.track.id + '\r\n';
- sdp += 'a=' + msid;
-
- // for Chrome.
- sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].ssrc +
- ' ' + msid;
- if (transceiver.sendEncodingParameters[0].rtx) {
- sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].rtx.ssrc +
- ' ' + msid;
- sdp += 'a=ssrc-group:FID ' +
- transceiver.sendEncodingParameters[0].ssrc + ' ' +
- transceiver.sendEncodingParameters[0].rtx.ssrc +
- '\r\n';
- }
- }
- // FIXME: this should be written by writeRtpDescription.
- sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].ssrc +
- ' cname:' + SDPUtils.localCName + '\r\n';
- if (transceiver.rtpSender && transceiver.sendEncodingParameters[0].rtx) {
- sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].rtx.ssrc +
- ' cname:' + SDPUtils.localCName + '\r\n';
- }
- return sdp;
-};
-
-// Gets the direction from the mediaSection or the sessionpart.
-SDPUtils.getDirection = function(mediaSection, sessionpart) {
- // Look for sendrecv, sendonly, recvonly, inactive, default to sendrecv.
- var lines = SDPUtils.splitLines(mediaSection);
- for (var i = 0; i < lines.length; i++) {
- switch (lines[i]) {
- case 'a=sendrecv':
- case 'a=sendonly':
- case 'a=recvonly':
- case 'a=inactive':
- return lines[i].substr(2);
- default:
- // FIXME: What should happen here?
- }
- }
- if (sessionpart) {
- return SDPUtils.getDirection(sessionpart);
- }
- return 'sendrecv';
-};
-
-SDPUtils.getKind = function(mediaSection) {
- var lines = SDPUtils.splitLines(mediaSection);
- var mline = lines[0].split(' ');
- return mline[0].substr(2);
-};
-
-SDPUtils.isRejected = function(mediaSection) {
- return mediaSection.split(' ', 2)[1] === '0';
-};
-
-SDPUtils.parseMLine = function(mediaSection) {
- var lines = SDPUtils.splitLines(mediaSection);
- var mline = lines[0].split(' ');
- return {
- kind: mline[0].substr(2),
- port: parseInt(mline[1], 10),
- protocol: mline[2],
- fmt: mline.slice(3).join(' ')
- };
-};
-
-// Expose public methods.
-if (typeof module === 'object') {
- module.exports = SDPUtils;
-}
-
-},{}],3:[function(require,module,exports){
-(function (global){
-/*
- * Copyright (c) 2016 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.
- */
- /* eslint-env node */
-
-'use strict';
-
-var adapterFactory = require('./adapter_factory.js');
-module.exports = adapterFactory({window: global.window});
-
-}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-},{"./adapter_factory.js":4}],4:[function(require,module,exports){
-/*
- * Copyright (c) 2016 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.
- */
- /* eslint-env node */
-
-'use strict';
-
-var utils = require('./utils');
-// Shimming starts here.
-module.exports = function(dependencies, opts) {
- var window = dependencies && dependencies.window;
-
- var options = {
- shimChrome: true,
- shimFirefox: true,
- shimEdge: true,
- shimSafari: true,
- };
-
- for (var key in opts) {
- if (hasOwnProperty.call(opts, key)) {
- options[key] = opts[key];
- }
- }
-
- // Utils.
- var logging = utils.log;
- var browserDetails = utils.detectBrowser(window);
-
- // Uncomment the line below if you want logging to occur, including logging
- // for the switch statement below. Can also be turned on in the browser via
- // adapter.disableLog(false), but then logging from the switch statement below
- // will not appear.
- // require('./utils').disableLog(false);
-
- // Browser shims.
- var chromeShim = require('./chrome/chrome_shim') || null;
- var edgeShim = require('./edge/edge_shim') || null;
- var firefoxShim = require('./firefox/firefox_shim') || null;
- var safariShim = require('./safari/safari_shim') || null;
- var commonShim = require('./common_shim') || null;
-
- // Export to the adapter global object visible in the browser.
- var adapter = {
- browserDetails: browserDetails,
- commonShim: commonShim,
- extractVersion: utils.extractVersion,
- disableLog: utils.disableLog,
- disableWarnings: utils.disableWarnings
- };
-
- // Shim browser if found.
- switch (browserDetails.browser) {
- case 'chrome':
- if (!chromeShim || !chromeShim.shimPeerConnection ||
- !options.shimChrome) {
- logging('Chrome shim is not included in this adapter release.');
- return adapter;
- }
- logging('adapter.js shimming chrome.');
- // Export to the adapter global object visible in the browser.
- adapter.browserShim = chromeShim;
- commonShim.shimCreateObjectURL(window);
-
- chromeShim.shimGetUserMedia(window);
- chromeShim.shimMediaStream(window);
- chromeShim.shimSourceObject(window);
- chromeShim.shimPeerConnection(window);
- chromeShim.shimOnTrack(window);
- chromeShim.shimAddTrackRemoveTrack(window);
- chromeShim.shimGetSendersWithDtmf(window);
-
- commonShim.shimRTCIceCandidate(window);
- commonShim.shimMaxMessageSize(window);
- commonShim.shimSendThrowTypeError(window);
- break;
- case 'firefox':
- if (!firefoxShim || !firefoxShim.shimPeerConnection ||
- !options.shimFirefox) {
- logging('Firefox shim is not included in this adapter release.');
- return adapter;
- }
- logging('adapter.js shimming firefox.');
- // Export to the adapter global object visible in the browser.
- adapter.browserShim = firefoxShim;
- commonShim.shimCreateObjectURL(window);
-
- firefoxShim.shimGetUserMedia(window);
- firefoxShim.shimSourceObject(window);
- firefoxShim.shimPeerConnection(window);
- firefoxShim.shimOnTrack(window);
- firefoxShim.shimRemoveStream(window);
-
- commonShim.shimRTCIceCandidate(window);
- commonShim.shimMaxMessageSize(window);
- commonShim.shimSendThrowTypeError(window);
- break;
- case 'edge':
- if (!edgeShim || !edgeShim.shimPeerConnection || !options.shimEdge) {
- logging('MS edge shim is not included in this adapter release.');
- return adapter;
- }
- logging('adapter.js shimming edge.');
- // Export to the adapter global object visible in the browser.
- adapter.browserShim = edgeShim;
- commonShim.shimCreateObjectURL(window);
-
- edgeShim.shimGetUserMedia(window);
- edgeShim.shimPeerConnection(window);
- edgeShim.shimReplaceTrack(window);
-
- // the edge shim implements the full RTCIceCandidate object.
-
- commonShim.shimMaxMessageSize(window);
- commonShim.shimSendThrowTypeError(window);
- break;
- case 'safari':
- if (!safariShim || !options.shimSafari) {
- logging('Safari shim is not included in this adapter release.');
- return adapter;
- }
- logging('adapter.js shimming safari.');
- // Export to the adapter global object visible in the browser.
- adapter.browserShim = safariShim;
- commonShim.shimCreateObjectURL(window);
-
- safariShim.shimRTCIceServerUrls(window);
- safariShim.shimCallbacksAPI(window);
- safariShim.shimLocalStreamsAPI(window);
- safariShim.shimRemoteStreamsAPI(window);
- safariShim.shimTrackEventTransceiver(window);
- safariShim.shimGetUserMedia(window);
- safariShim.shimCreateOfferLegacy(window);
-
- commonShim.shimRTCIceCandidate(window);
- commonShim.shimMaxMessageSize(window);
- commonShim.shimSendThrowTypeError(window);
- break;
- default:
- logging('Unsupported browser!');
- break;
- }
-
- return adapter;
-};
-
-},{"./chrome/chrome_shim":5,"./common_shim":7,"./edge/edge_shim":8,"./firefox/firefox_shim":10,"./safari/safari_shim":12,"./utils":13}],5:[function(require,module,exports){
-
-/*
- * Copyright (c) 2016 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.
- */
- /* eslint-env node */
-'use strict';
-var utils = require('../utils.js');
-var logging = utils.log;
-
-module.exports = {
- shimGetUserMedia: require('./getusermedia'),
- shimMediaStream: function(window) {
- window.MediaStream = window.MediaStream || window.webkitMediaStream;
- },
-
- shimOnTrack: function(window) {
- if (typeof window === 'object' && window.RTCPeerConnection && !('ontrack' in
- window.RTCPeerConnection.prototype)) {
- Object.defineProperty(window.RTCPeerConnection.prototype, 'ontrack', {
- get: function() {
- return this._ontrack;
- },
- set: function(f) {
- if (this._ontrack) {
- this.removeEventListener('track', this._ontrack);
- }
- this.addEventListener('track', this._ontrack = f);
- }
- });
- var origSetRemoteDescription =
- window.RTCPeerConnection.prototype.setRemoteDescription;
- window.RTCPeerConnection.prototype.setRemoteDescription = function() {
- var pc = this;
- if (!pc._ontrackpoly) {
- pc._ontrackpoly = function(e) {
- // onaddstream does not fire when a track is added to an existing
- // stream. But stream.onaddtrack is implemented so we use that.
- e.stream.addEventListener('addtrack', function(te) {
- var receiver;
- if (window.RTCPeerConnection.prototype.getReceivers) {
- receiver = pc.getReceivers().find(function(r) {
- return r.track && r.track.id === te.track.id;
- });
- } else {
- receiver = {track: te.track};
- }
-
- var event = new Event('track');
- event.track = te.track;
- event.receiver = receiver;
- event.transceiver = {receiver: receiver};
- event.streams = [e.stream];
- pc.dispatchEvent(event);
- });
- e.stream.getTracks().forEach(function(track) {
- var receiver;
- if (window.RTCPeerConnection.prototype.getReceivers) {
- receiver = pc.getReceivers().find(function(r) {
- return r.track && r.track.id === track.id;
- });
- } else {
- receiver = {track: track};
- }
- var event = new Event('track');
- event.track = track;
- event.receiver = receiver;
- event.transceiver = {receiver: receiver};
- event.streams = [e.stream];
- pc.dispatchEvent(event);
- });
- };
- pc.addEventListener('addstream', pc._ontrackpoly);
- }
- return origSetRemoteDescription.apply(pc, arguments);
- };
- } else if (!('RTCRtpTransceiver' in window)) {
- utils.wrapPeerConnectionEvent(window, 'track', function(e) {
- if (!e.transceiver) {
- e.transceiver = {receiver: e.receiver};
- }
- return e;
- });
- }
- },
-
- shimGetSendersWithDtmf: function(window) {
- // Overrides addTrack/removeTrack, depends on shimAddTrackRemoveTrack.
- if (typeof window === 'object' && window.RTCPeerConnection &&
- !('getSenders' in window.RTCPeerConnection.prototype) &&
- 'createDTMFSender' in window.RTCPeerConnection.prototype) {
- var shimSenderWithDtmf = function(pc, track) {
- return {
- track: track,
- get dtmf() {
- if (this._dtmf === undefined) {
- if (track.kind === 'audio') {
- this._dtmf = pc.createDTMFSender(track);
- } else {
- this._dtmf = null;
- }
- }
- return this._dtmf;
- },
- _pc: pc
- };
- };
-
- // augment addTrack when getSenders is not available.
- if (!window.RTCPeerConnection.prototype.getSenders) {
- window.RTCPeerConnection.prototype.getSenders = function() {
- this._senders = this._senders || [];
- return this._senders.slice(); // return a copy of the internal state.
- };
- var origAddTrack = window.RTCPeerConnection.prototype.addTrack;
- window.RTCPeerConnection.prototype.addTrack = function(track, stream) {
- var pc = this;
- var sender = origAddTrack.apply(pc, arguments);
- if (!sender) {
- sender = shimSenderWithDtmf(pc, track);
- pc._senders.push(sender);
- }
- return sender;
- };
-
- var origRemoveTrack = window.RTCPeerConnection.prototype.removeTrack;
- window.RTCPeerConnection.prototype.removeTrack = function(sender) {
- var pc = this;
- origRemoveTrack.apply(pc, arguments);
- var idx = pc._senders.indexOf(sender);
- if (idx !== -1) {
- pc._senders.splice(idx, 1);
- }
- };
- }
- var origAddStream = window.RTCPeerConnection.prototype.addStream;
- window.RTCPeerConnection.prototype.addStream = function(stream) {
- var pc = this;
- pc._senders = pc._senders || [];
- origAddStream.apply(pc, [stream]);
- stream.getTracks().forEach(function(track) {
- pc._senders.push(shimSenderWithDtmf(pc, track));
- });
- };
-
- var origRemoveStream = window.RTCPeerConnection.prototype.removeStream;
- window.RTCPeerConnection.prototype.removeStream = function(stream) {
- var pc = this;
- pc._senders = pc._senders || [];
- origRemoveStream.apply(pc, [stream]);
-
- stream.getTracks().forEach(function(track) {
- var sender = pc._senders.find(function(s) {
- return s.track === track;
- });
- if (sender) {
- pc._senders.splice(pc._senders.indexOf(sender), 1); // remove sender
- }
- });
- };
- } else if (typeof window === 'object' && window.RTCPeerConnection &&
- 'getSenders' in window.RTCPeerConnection.prototype &&
- 'createDTMFSender' in window.RTCPeerConnection.prototype &&
- window.RTCRtpSender &&
- !('dtmf' in window.RTCRtpSender.prototype)) {
- var origGetSenders = window.RTCPeerConnection.prototype.getSenders;
- window.RTCPeerConnection.prototype.getSenders = function() {
- var pc = this;
- var senders = origGetSenders.apply(pc, []);
- senders.forEach(function(sender) {
- sender._pc = pc;
- });
- return senders;
- };
-
- Object.defineProperty(window.RTCRtpSender.prototype, 'dtmf', {
- get: function() {
- if (this._dtmf === undefined) {
- if (this.track.kind === 'audio') {
- this._dtmf = this._pc.createDTMFSender(this.track);
- } else {
- this._dtmf = null;
- }
- }
- return this._dtmf;
- }
- });
- }
- },
-
- shimSourceObject: function(window) {
- var URL = window && window.URL;
-
- 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() {
- return this._srcObject;
- },
- set: function(stream) {
- var self = this;
- // Use _srcObject as a private property for this shim
- this._srcObject = stream;
- if (this.src) {
- URL.revokeObjectURL(this.src);
- }
-
- if (!stream) {
- this.src = '';
- return undefined;
- }
- this.src = URL.createObjectURL(stream);
- // We need to recreate the blob url when a track is added or
- // removed. Doing it manually since we want to avoid a recursion.
- stream.addEventListener('addtrack', function() {
- if (self.src) {
- URL.revokeObjectURL(self.src);
- }
- self.src = URL.createObjectURL(stream);
- });
- stream.addEventListener('removetrack', function() {
- if (self.src) {
- URL.revokeObjectURL(self.src);
- }
- self.src = URL.createObjectURL(stream);
- });
- }
- });
- }
- }
- },
-
- shimAddTrackRemoveTrackWithNative: function(window) {
- // shim addTrack/removeTrack with native variants in order to make
- // the interactions with legacy getLocalStreams behave as in other browsers.
- // Keeps a mapping stream.id => [stream, rtpsenders...]
- window.RTCPeerConnection.prototype.getLocalStreams = function() {
- var pc = this;
- this._shimmedLocalStreams = this._shimmedLocalStreams || {};
- return Object.keys(this._shimmedLocalStreams).map(function(streamId) {
- return pc._shimmedLocalStreams[streamId][0];
- });
- };
-
- var origAddTrack = window.RTCPeerConnection.prototype.addTrack;
- window.RTCPeerConnection.prototype.addTrack = function(track, stream) {
- if (!stream) {
- return origAddTrack.apply(this, arguments);
- }
- this._shimmedLocalStreams = this._shimmedLocalStreams || {};
-
- var sender = origAddTrack.apply(this, arguments);
- if (!this._shimmedLocalStreams[stream.id]) {
- this._shimmedLocalStreams[stream.id] = [stream, sender];
- } else if (this._shimmedLocalStreams[stream.id].indexOf(sender) === -1) {
- this._shimmedLocalStreams[stream.id].push(sender);
- }
- return sender;
- };
-
- var origAddStream = window.RTCPeerConnection.prototype.addStream;
- window.RTCPeerConnection.prototype.addStream = function(stream) {
- var pc = this;
- this._shimmedLocalStreams = this._shimmedLocalStreams || {};
-
- stream.getTracks().forEach(function(track) {
- var alreadyExists = pc.getSenders().find(function(s) {
- return s.track === track;
- });
- if (alreadyExists) {
- throw new DOMException('Track already exists.',
- 'InvalidAccessError');
- }
- });
- var existingSenders = pc.getSenders();
- origAddStream.apply(this, arguments);
- var newSenders = pc.getSenders().filter(function(newSender) {
- return existingSenders.indexOf(newSender) === -1;
- });
- this._shimmedLocalStreams[stream.id] = [stream].concat(newSenders);
- };
-
- var origRemoveStream = window.RTCPeerConnection.prototype.removeStream;
- window.RTCPeerConnection.prototype.removeStream = function(stream) {
- this._shimmedLocalStreams = this._shimmedLocalStreams || {};
- delete this._shimmedLocalStreams[stream.id];
- return origRemoveStream.apply(this, arguments);
- };
-
- var origRemoveTrack = window.RTCPeerConnection.prototype.removeTrack;
- window.RTCPeerConnection.prototype.removeTrack = function(sender) {
- var pc = this;
- this._shimmedLocalStreams = this._shimmedLocalStreams || {};
- if (sender) {
- Object.keys(this._shimmedLocalStreams).forEach(function(streamId) {
- var idx = pc._shimmedLocalStreams[streamId].indexOf(sender);
- if (idx !== -1) {
- pc._shimmedLocalStreams[streamId].splice(idx, 1);
- }
- if (pc._shimmedLocalStreams[streamId].length === 1) {
- delete pc._shimmedLocalStreams[streamId];
- }
- });
- }
- return origRemoveTrack.apply(this, arguments);
- };
- },
-
- shimAddTrackRemoveTrack: function(window) {
- var browserDetails = utils.detectBrowser(window);
- // shim addTrack and removeTrack.
- if (window.RTCPeerConnection.prototype.addTrack &&
- browserDetails.version >= 65) {
- return this.shimAddTrackRemoveTrackWithNative(window);
- }
-
- // also shim pc.getLocalStreams when addTrack is shimmed
- // to return the original streams.
- var origGetLocalStreams = window.RTCPeerConnection.prototype
- .getLocalStreams;
- window.RTCPeerConnection.prototype.getLocalStreams = function() {
- var pc = this;
- var nativeStreams = origGetLocalStreams.apply(this);
- pc._reverseStreams = pc._reverseStreams || {};
- return nativeStreams.map(function(stream) {
- return pc._reverseStreams[stream.id];
- });
- };
-
- var origAddStream = window.RTCPeerConnection.prototype.addStream;
- window.RTCPeerConnection.prototype.addStream = function(stream) {
- var pc = this;
- pc._streams = pc._streams || {};
- pc._reverseStreams = pc._reverseStreams || {};
-
- stream.getTracks().forEach(function(track) {
- var alreadyExists = pc.getSenders().find(function(s) {
- return s.track === track;
- });
- if (alreadyExists) {
- throw new DOMException('Track already exists.',
- 'InvalidAccessError');
- }
- });
- // Add identity mapping for consistency with addTrack.
- // Unless this is being used with a stream from addTrack.
- if (!pc._reverseStreams[stream.id]) {
- var newStream = new window.MediaStream(stream.getTracks());
- pc._streams[stream.id] = newStream;
- pc._reverseStreams[newStream.id] = stream;
- stream = newStream;
- }
- origAddStream.apply(pc, [stream]);
- };
-
- var origRemoveStream = window.RTCPeerConnection.prototype.removeStream;
- window.RTCPeerConnection.prototype.removeStream = function(stream) {
- var pc = this;
- pc._streams = pc._streams || {};
- pc._reverseStreams = pc._reverseStreams || {};
-
- origRemoveStream.apply(pc, [(pc._streams[stream.id] || stream)]);
- delete pc._reverseStreams[(pc._streams[stream.id] ?
- pc._streams[stream.id].id : stream.id)];
- delete pc._streams[stream.id];
- };
-
- window.RTCPeerConnection.prototype.addTrack = function(track, stream) {
- var pc = this;
- if (pc.signalingState === 'closed') {
- throw new DOMException(
- 'The RTCPeerConnection\'s signalingState is \'closed\'.',
- 'InvalidStateError');
- }
- var streams = [].slice.call(arguments, 1);
- if (streams.length !== 1 ||
- !streams[0].getTracks().find(function(t) {
- return t === track;
- })) {
- // this is not fully correct but all we can manage without
- // [[associated MediaStreams]] internal slot.
- throw new DOMException(
- 'The adapter.js addTrack polyfill only supports a single ' +
- ' stream which is associated with the specified track.',
- 'NotSupportedError');
- }
-
- var alreadyExists = pc.getSenders().find(function(s) {
- return s.track === track;
- });
- if (alreadyExists) {
- throw new DOMException('Track already exists.',
- 'InvalidAccessError');
- }
-
- pc._streams = pc._streams || {};
- pc._reverseStreams = pc._reverseStreams || {};
- var oldStream = pc._streams[stream.id];
- if (oldStream) {
- // this is using odd Chrome behaviour, use with caution:
- // https://bugs.chromium.org/p/webrtc/issues/detail?id=7815
- // Note: we rely on the high-level addTrack/dtmf shim to
- // create the sender with a dtmf sender.
- oldStream.addTrack(track);
-
- // Trigger ONN async.
- Promise.resolve().then(function() {
- pc.dispatchEvent(new Event('negotiationneeded'));
- });
- } else {
- var newStream = new window.MediaStream([track]);
- pc._streams[stream.id] = newStream;
- pc._reverseStreams[newStream.id] = stream;
- pc.addStream(newStream);
- }
- return pc.getSenders().find(function(s) {
- return s.track === track;
- });
- };
-
- // replace the internal stream id with the external one and
- // vice versa.
- function replaceInternalStreamId(pc, description) {
- var sdp = description.sdp;
- Object.keys(pc._reverseStreams || []).forEach(function(internalId) {
- var externalStream = pc._reverseStreams[internalId];
- var internalStream = pc._streams[externalStream.id];
- sdp = sdp.replace(new RegExp(internalStream.id, 'g'),
- externalStream.id);
- });
- return new RTCSessionDescription({
- type: description.type,
- sdp: sdp
- });
- }
- function replaceExternalStreamId(pc, description) {
- var sdp = description.sdp;
- Object.keys(pc._reverseStreams || []).forEach(function(internalId) {
- var externalStream = pc._reverseStreams[internalId];
- var internalStream = pc._streams[externalStream.id];
- sdp = sdp.replace(new RegExp(externalStream.id, 'g'),
- internalStream.id);
- });
- return new RTCSessionDescription({
- type: description.type,
- sdp: sdp
- });
- }
- ['createOffer', 'createAnswer'].forEach(function(method) {
- var nativeMethod = window.RTCPeerConnection.prototype[method];
- window.RTCPeerConnection.prototype[method] = function() {
- var pc = this;
- var args = arguments;
- var isLegacyCall = arguments.length &&
- typeof arguments[0] === 'function';
- if (isLegacyCall) {
- return nativeMethod.apply(pc, [
- function(description) {
- var desc = replaceInternalStreamId(pc, description);
- args[0].apply(null, [desc]);
- },
- function(err) {
- if (args[1]) {
- args[1].apply(null, err);
- }
- }, arguments[2]
- ]);
- }
- return nativeMethod.apply(pc, arguments)
- .then(function(description) {
- return replaceInternalStreamId(pc, description);
- });
- };
- });
-
- var origSetLocalDescription =
- window.RTCPeerConnection.prototype.setLocalDescription;
- window.RTCPeerConnection.prototype.setLocalDescription = function() {
- var pc = this;
- if (!arguments.length || !arguments[0].type) {
- return origSetLocalDescription.apply(pc, arguments);
- }
- arguments[0] = replaceExternalStreamId(pc, arguments[0]);
- return origSetLocalDescription.apply(pc, arguments);
- };
-
- // TODO: mangle getStats: https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamstats-streamidentifier
-
- var origLocalDescription = Object.getOwnPropertyDescriptor(
- window.RTCPeerConnection.prototype, 'localDescription');
- Object.defineProperty(window.RTCPeerConnection.prototype,
- 'localDescription', {
- get: function() {
- var pc = this;
- var description = origLocalDescription.get.apply(this);
- if (description.type === '') {
- return description;
- }
- return replaceInternalStreamId(pc, description);
- }
- });
-
- window.RTCPeerConnection.prototype.removeTrack = function(sender) {
- var pc = this;
- if (pc.signalingState === 'closed') {
- throw new DOMException(
- 'The RTCPeerConnection\'s signalingState is \'closed\'.',
- 'InvalidStateError');
- }
- // We can not yet check for sender instanceof RTCRtpSender
- // since we shim RTPSender. So we check if sender._pc is set.
- if (!sender._pc) {
- throw new DOMException('Argument 1 of RTCPeerConnection.removeTrack ' +
- 'does not implement interface RTCRtpSender.', 'TypeError');
- }
- var isLocal = sender._pc === pc;
- if (!isLocal) {
- throw new DOMException('Sender was not created by this connection.',
- 'InvalidAccessError');
- }
-
- // Search for the native stream the senders track belongs to.
- pc._streams = pc._streams || {};
- var stream;
- Object.keys(pc._streams).forEach(function(streamid) {
- var hasTrack = pc._streams[streamid].getTracks().find(function(track) {
- return sender.track === track;
- });
- if (hasTrack) {
- stream = pc._streams[streamid];
- }
- });
-
- if (stream) {
- if (stream.getTracks().length === 1) {
- // if this is the last track of the stream, remove the stream. This
- // takes care of any shimmed _senders.
- pc.removeStream(pc._reverseStreams[stream.id]);
- } else {
- // relying on the same odd chrome behaviour as above.
- stream.removeTrack(sender.track);
- }
- pc.dispatchEvent(new Event('negotiationneeded'));
- }
- };
- },
-
- shimPeerConnection: function(window) {
- var browserDetails = utils.detectBrowser(window);
-
- // The RTCPeerConnection object.
- if (!window.RTCPeerConnection && window.webkitRTCPeerConnection) {
- window.RTCPeerConnection = function(pcConfig, pcConstraints) {
- // Translate iceTransportPolicy to iceTransports,
- // see https://code.google.com/p/webrtc/issues/detail?id=4869
- // this was fixed in M56 along with unprefixing RTCPeerConnection.
- logging('PeerConnection');
- if (pcConfig && pcConfig.iceTransportPolicy) {
- pcConfig.iceTransports = pcConfig.iceTransportPolicy;
- }
-
- return new window.webkitRTCPeerConnection(pcConfig, pcConstraints);
- };
- window.RTCPeerConnection.prototype =
- window.webkitRTCPeerConnection.prototype;
- // wrap static methods. Currently just generateCertificate.
- if (window.webkitRTCPeerConnection.generateCertificate) {
- Object.defineProperty(window.RTCPeerConnection, 'generateCertificate', {
- get: function() {
- return window.webkitRTCPeerConnection.generateCertificate;
- }
- });
- }
- } else {
- // migrate from non-spec RTCIceServer.url to RTCIceServer.urls
- var OrigPeerConnection = window.RTCPeerConnection;
- window.RTCPeerConnection = function(pcConfig, pcConstraints) {
- if (pcConfig && pcConfig.iceServers) {
- var newIceServers = [];
- for (var i = 0; i < pcConfig.iceServers.length; i++) {
- var server = pcConfig.iceServers[i];
- if (!server.hasOwnProperty('urls') &&
- server.hasOwnProperty('url')) {
- utils.deprecated('RTCIceServer.url', 'RTCIceServer.urls');
- server = JSON.parse(JSON.stringify(server));
- server.urls = server.url;
- newIceServers.push(server);
- } else {
- newIceServers.push(pcConfig.iceServers[i]);
- }
- }
- pcConfig.iceServers = newIceServers;
- }
- return new OrigPeerConnection(pcConfig, pcConstraints);
- };
- window.RTCPeerConnection.prototype = OrigPeerConnection.prototype;
- // wrap static methods. Currently just generateCertificate.
- Object.defineProperty(window.RTCPeerConnection, 'generateCertificate', {
- get: function() {
- return OrigPeerConnection.generateCertificate;
- }
- });
- }
-
- var origGetStats = window.RTCPeerConnection.prototype.getStats;
- window.RTCPeerConnection.prototype.getStats = function(selector,
- successCallback, errorCallback) {
- var pc = 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.apply(this, arguments);
- }
-
- // When spec-style getStats is supported, return those when called with
- // either no arguments or the selector argument is null.
- if (origGetStats.length === 0 && (arguments.length === 0 ||
- typeof arguments[0] !== 'function')) {
- return origGetStats.apply(this, []);
- }
-
- var fixChromeStats_ = function(response) {
- var standardReport = {};
- var reports = response.result();
- reports.forEach(function(report) {
- var standardStats = {
- id: report.id,
- timestamp: report.timestamp,
- type: {
- localcandidate: 'local-candidate',
- remotecandidate: 'remote-candidate'
- }[report.type] || report.type
- };
- report.names().forEach(function(name) {
- standardStats[name] = report.stat(name);
- });
- standardReport[standardStats.id] = standardStats;
- });
-
- return standardReport;
- };
-
- // shim getStats with maplike support
- var makeMapStats = function(stats) {
- return new Map(Object.keys(stats).map(function(key) {
- return [key, stats[key]];
- }));
- };
-
- if (arguments.length >= 2) {
- var successCallbackWrapper_ = function(response) {
- args[1](makeMapStats(fixChromeStats_(response)));
- };
-
- return origGetStats.apply(this, [successCallbackWrapper_,
- arguments[0]]);
- }
-
- // promise-support
- return new Promise(function(resolve, reject) {
- origGetStats.apply(pc, [
- function(response) {
- resolve(makeMapStats(fixChromeStats_(response)));
- }, reject]);
- }).then(successCallback, errorCallback);
- };
-
- // add promise support -- natively available in Chrome 51
- if (browserDetails.version < 51) {
- ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate']
- .forEach(function(method) {
- var nativeMethod = window.RTCPeerConnection.prototype[method];
- window.RTCPeerConnection.prototype[method] = function() {
- var args = arguments;
- var pc = this;
- var promise = new Promise(function(resolve, reject) {
- nativeMethod.apply(pc, [args[0], resolve, reject]);
- });
- if (args.length < 2) {
- return promise;
- }
- return promise.then(function() {
- args[1].apply(null, []);
- },
- function(err) {
- if (args.length >= 3) {
- args[2].apply(null, [err]);
- }
- });
- };
- });
- }
-
- // promise support for createOffer and createAnswer. Available (without
- // bugs) since M52: crbug/619289
- if (browserDetails.version < 52) {
- ['createOffer', 'createAnswer'].forEach(function(method) {
- var nativeMethod = window.RTCPeerConnection.prototype[method];
- window.RTCPeerConnection.prototype[method] = function() {
- var pc = 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(pc, [resolve, reject, opts]);
- });
- }
- return nativeMethod.apply(this, arguments);
- };
- });
- }
-
- // shim implicit creation of RTCSessionDescription/RTCIceCandidate
- ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate']
- .forEach(function(method) {
- var nativeMethod = window.RTCPeerConnection.prototype[method];
- window.RTCPeerConnection.prototype[method] = function() {
- arguments[0] = new ((method === 'addIceCandidate') ?
- window.RTCIceCandidate :
- window.RTCSessionDescription)(arguments[0]);
- return nativeMethod.apply(this, arguments);
- };
- });
-
- // support for addIceCandidate(null or undefined)
- var nativeAddIceCandidate =
- window.RTCPeerConnection.prototype.addIceCandidate;
- window.RTCPeerConnection.prototype.addIceCandidate = function() {
- if (!arguments[0]) {
- if (arguments[1]) {
- arguments[1].apply(null);
- }
- return Promise.resolve();
- }
- return nativeAddIceCandidate.apply(this, arguments);
- };
- }
-};
-
-},{"../utils.js":13,"./getusermedia":6}],6:[function(require,module,exports){
-/*
- * Copyright (c) 2016 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.
- */
- /* eslint-env node */
-'use strict';
-var utils = require('../utils.js');
-var logging = utils.log;
-
-// Expose public methods.
-module.exports = function(window) {
- var browserDetails = utils.detectBrowser(window);
- var navigator = window && window.navigator;
-
- 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;
- };
-
- var shimConstraints_ = function(constraints, func) {
- if (browserDetails.version >= 61) {
- return func(constraints);
- }
- constraints = JSON.parse(JSON.stringify(constraints));
- if (constraints && typeof constraints.audio === 'object') {
- var remap = function(obj, a, b) {
- if (a in obj && !(b in obj)) {
- obj[b] = obj[a];
- delete obj[a];
- }
- };
- constraints = JSON.parse(JSON.stringify(constraints));
- remap(constraints.audio, 'autoGainControl', 'googAutoGainControl');
- remap(constraints.audio, 'noiseSuppression', 'googNoiseSuppression');
- constraints.audio = constraintsToChrome_(constraints.audio);
- }
- if (constraints && typeof constraints.video === 'object') {
- // Shim facingMode for mobile & surface pro.
- var face = constraints.video.facingMode;
- face = face && ((typeof face === 'object') ? face : {ideal: face});
- var getSupportedFacingModeLies = browserDetails.version < 66;
-
- if ((face && (face.exact === 'user' || face.exact === 'environment' ||
- face.ideal === 'user' || face.ideal === 'environment')) &&
- !(navigator.mediaDevices.getSupportedConstraints &&
- navigator.mediaDevices.getSupportedConstraints().facingMode &&
- !getSupportedFacingModeLies)) {
- delete constraints.video.facingMode;
- var matches;
- if (face.exact === 'environment' || face.ideal === 'environment') {
- matches = ['back', 'rear'];
- } else if (face.exact === 'user' || face.ideal === 'user') {
- matches = ['front'];
- }
- if (matches) {
- // Look for matches in label, or use last cam for back (typical).
- return navigator.mediaDevices.enumerateDevices()
- .then(function(devices) {
- devices = devices.filter(function(d) {
- return d.kind === 'videoinput';
- });
- var dev = devices.find(function(d) {
- return matches.some(function(match) {
- return d.label.toLowerCase().indexOf(match) !== -1;
- });
- });
- if (!dev && devices.length && matches.indexOf('back') !== -1) {
- dev = devices[devices.length - 1]; // more likely the back cam
- }
- if (dev) {
- constraints.video.deviceId = face.exact ? {exact: dev.deviceId} :
- {ideal: dev.deviceId};
- }
- constraints.video = constraintsToChrome_(constraints.video);
- logging('chrome: ' + JSON.stringify(constraints));
- return func(constraints);
- });
- }
- }
- constraints.video = constraintsToChrome_(constraints.video);
- }
- logging('chrome: ' + JSON.stringify(constraints));
- return func(constraints);
- };
-
- var shimError_ = function(e) {
- return {
- name: {
- PermissionDeniedError: 'NotAllowedError',
- InvalidStateError: 'NotReadableError',
- DevicesNotFoundError: 'NotFoundError',
- ConstraintNotSatisfiedError: 'OverconstrainedError',
- TrackStartError: 'NotReadableError',
- MediaDeviceFailedDueToShutdown: 'NotReadableError',
- MediaDeviceKillSwitchOn: 'NotReadableError'
- }[e.name] || e.name,
- message: e.message,
- constraint: e.constraintName,
- toString: function() {
- return this.name + (this.message && ': ') + this.message;
- }
- };
- };
-
- var getUserMedia_ = function(constraints, onSuccess, onError) {
- shimConstraints_(constraints, function(c) {
- navigator.webkitGetUserMedia(c, onSuccess, function(e) {
- if (onError) {
- onError(shimError_(e));
- }
- });
- });
- };
-
- navigator.getUserMedia = getUserMedia_;
-
- // Returns the result of getUserMedia as a Promise.
- var getUserMediaPromise_ = function(constraints) {
- return new Promise(function(resolve, reject) {
- navigator.getUserMedia(constraints, resolve, reject);
- });
- };
-
- if (!navigator.mediaDevices) {
- navigator.mediaDevices = {
- getUserMedia: getUserMediaPromise_,
- enumerateDevices: function() {
- return new Promise(function(resolve) {
- var kinds = {audio: 'audioinput', video: 'videoinput'};
- return window.MediaStreamTrack.getSources(function(devices) {
- resolve(devices.map(function(device) {
- return {label: device.label,
- kind: kinds[device.kind],
- deviceId: device.id,
- groupId: ''};
- }));
- });
- });
- },
- getSupportedConstraints: function() {
- return {
- deviceId: true, echoCancellation: true, facingMode: true,
- frameRate: true, height: true, width: true
- };
- }
- };
- }
-
- // 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 getUserMediaPromise_(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(cs) {
- return shimConstraints_(cs, function(c) {
- return origGetUserMedia(c).then(function(stream) {
- if (c.audio && !stream.getAudioTracks().length ||
- c.video && !stream.getVideoTracks().length) {
- stream.getTracks().forEach(function(track) {
- track.stop();
- });
- throw new DOMException('', 'NotFoundError');
- }
- return stream;
- }, function(e) {
- return Promise.reject(shimError_(e));
- });
- });
- };
- }
-
- // Dummy devicechange event methods.
- // TODO(KaptenJansson) remove once implemented in Chrome stable.
- if (typeof navigator.mediaDevices.addEventListener === 'undefined') {
- navigator.mediaDevices.addEventListener = function() {
- logging('Dummy mediaDevices.addEventListener called.');
- };
- }
- if (typeof navigator.mediaDevices.removeEventListener === 'undefined') {
- navigator.mediaDevices.removeEventListener = function() {
- logging('Dummy mediaDevices.removeEventListener called.');
- };
- }
-};
-
-},{"../utils.js":13}],7:[function(require,module,exports){
-/*
- * Copyright (c) 2017 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.
- */
- /* eslint-env node */
-'use strict';
-
-var SDPUtils = require('sdp');
-var utils = require('./utils');
-
-module.exports = {
- shimRTCIceCandidate: function(window) {
- // foundation is arbitrarily chosen as an indicator for full support for
- // https://w3c.github.io/webrtc-pc/#rtcicecandidate-interface
- if (window.RTCIceCandidate && 'foundation' in
- window.RTCIceCandidate.prototype) {
- return;
- }
-
- var NativeRTCIceCandidate = window.RTCIceCandidate;
- window.RTCIceCandidate = function(args) {
- // Remove the a= which shouldn't be part of the candidate string.
- if (typeof args === 'object' && args.candidate &&
- args.candidate.indexOf('a=') === 0) {
- args = JSON.parse(JSON.stringify(args));
- args.candidate = args.candidate.substr(2);
- }
-
- // Augment the native candidate with the parsed fields.
- var nativeCandidate = new NativeRTCIceCandidate(args);
- var parsedCandidate = SDPUtils.parseCandidate(args.candidate);
- var augmentedCandidate = Object.assign(nativeCandidate,
- parsedCandidate);
-
- // Add a serializer that does not serialize the extra attributes.
- augmentedCandidate.toJSON = function() {
- return {
- candidate: augmentedCandidate.candidate,
- sdpMid: augmentedCandidate.sdpMid,
- sdpMLineIndex: augmentedCandidate.sdpMLineIndex,
- usernameFragment: augmentedCandidate.usernameFragment,
- };
- };
- return augmentedCandidate;
- };
-
- // Hook up the augmented candidate in onicecandidate and
- // addEventListener('icecandidate', ...)
- utils.wrapPeerConnectionEvent(window, 'icecandidate', function(e) {
- if (e.candidate) {
- Object.defineProperty(e, 'candidate', {
- value: new window.RTCIceCandidate(e.candidate),
- writable: 'false'
- });
- }
- return e;
- });
- },
-
- // shimCreateObjectURL must be called before shimSourceObject to avoid loop.
-
- shimCreateObjectURL: function(window) {
- var URL = window && window.URL;
-
- if (!(typeof window === 'object' && window.HTMLMediaElement &&
- 'srcObject' in window.HTMLMediaElement.prototype &&
- URL.createObjectURL && URL.revokeObjectURL)) {
- // Only shim CreateObjectURL using srcObject if srcObject exists.
- return undefined;
- }
-
- var nativeCreateObjectURL = URL.createObjectURL.bind(URL);
- var nativeRevokeObjectURL = URL.revokeObjectURL.bind(URL);
- var streams = new Map(), newId = 0;
-
- URL.createObjectURL = function(stream) {
- if ('getTracks' in stream) {
- var url = 'polyblob:' + (++newId);
- streams.set(url, stream);
- utils.deprecated('URL.createObjectURL(stream)',
- 'elem.srcObject = stream');
- return url;
- }
- return nativeCreateObjectURL(stream);
- };
- URL.revokeObjectURL = function(url) {
- nativeRevokeObjectURL(url);
- streams.delete(url);
- };
-
- var dsc = Object.getOwnPropertyDescriptor(window.HTMLMediaElement.prototype,
- 'src');
- Object.defineProperty(window.HTMLMediaElement.prototype, 'src', {
- get: function() {
- return dsc.get.apply(this);
- },
- set: function(url) {
- this.srcObject = streams.get(url) || null;
- return dsc.set.apply(this, [url]);
- }
- });
-
- var nativeSetAttribute = window.HTMLMediaElement.prototype.setAttribute;
- window.HTMLMediaElement.prototype.setAttribute = function() {
- if (arguments.length === 2 &&
- ('' + arguments[0]).toLowerCase() === 'src') {
- this.srcObject = streams.get(arguments[1]) || null;
- }
- return nativeSetAttribute.apply(this, arguments);
- };
- },
-
- shimMaxMessageSize: function(window) {
- if (window.RTCSctpTransport || !window.RTCPeerConnection) {
- return;
- }
- var browserDetails = utils.detectBrowser(window);
-
- if (!('sctp' in window.RTCPeerConnection.prototype)) {
- Object.defineProperty(window.RTCPeerConnection.prototype, 'sctp', {
- get: function() {
- return typeof this._sctp === 'undefined' ? null : this._sctp;
- }
- });
- }
-
- var sctpInDescription = function(description) {
- var sections = SDPUtils.splitSections(description.sdp);
- sections.shift();
- return sections.some(function(mediaSection) {
- var mLine = SDPUtils.parseMLine(mediaSection);
- return mLine && mLine.kind === 'application'
- && mLine.protocol.indexOf('SCTP') !== -1;
- });
- };
-
- var getRemoteFirefoxVersion = function(description) {
- // TODO: Is there a better solution for detecting Firefox?
- var match = description.sdp.match(/mozilla...THIS_IS_SDPARTA-(\d+)/);
- if (match === null || match.length < 2) {
- return -1;
- }
- var version = parseInt(match[1], 10);
- // Test for NaN (yes, this is ugly)
- return version !== version ? -1 : version;
- };
-
- var getCanSendMaxMessageSize = function(remoteIsFirefox) {
- // Every implementation we know can send at least 64 KiB.
- // Note: Although Chrome is technically able to send up to 256 KiB, the
- // data does not reach the other peer reliably.
- // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=8419
- var canSendMaxMessageSize = 65536;
- if (browserDetails.browser === 'firefox') {
- if (browserDetails.version < 57) {
- if (remoteIsFirefox === -1) {
- // FF < 57 will send in 16 KiB chunks using the deprecated PPID
- // fragmentation.
- canSendMaxMessageSize = 16384;
- } else {
- // However, other FF (and RAWRTC) can reassemble PPID-fragmented
- // messages. Thus, supporting ~2 GiB when sending.
- canSendMaxMessageSize = 2147483637;
- }
- } else {
- // Currently, all FF >= 57 will reset the remote maximum message size
- // to the default value when a data channel is created at a later
- // stage. :(
- // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1426831
- canSendMaxMessageSize =
- browserDetails.version === 57 ? 65535 : 65536;
- }
- }
- return canSendMaxMessageSize;
- };
-
- var getMaxMessageSize = function(description, remoteIsFirefox) {
- // Note: 65536 bytes is the default value from the SDP spec. Also,
- // every implementation we know supports receiving 65536 bytes.
- var maxMessageSize = 65536;
-
- // FF 57 has a slightly incorrect default remote max message size, so
- // we need to adjust it here to avoid a failure when sending.
- // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1425697
- if (browserDetails.browser === 'firefox'
- && browserDetails.version === 57) {
- maxMessageSize = 65535;
- }
-
- var match = SDPUtils.matchPrefix(description.sdp, 'a=max-message-size:');
- if (match.length > 0) {
- maxMessageSize = parseInt(match[0].substr(19), 10);
- } else if (browserDetails.browser === 'firefox' &&
- remoteIsFirefox !== -1) {
- // If the maximum message size is not present in the remote SDP and
- // both local and remote are Firefox, the remote peer can receive
- // ~2 GiB.
- maxMessageSize = 2147483637;
- }
- return maxMessageSize;
- };
-
- var origSetRemoteDescription =
- window.RTCPeerConnection.prototype.setRemoteDescription;
- window.RTCPeerConnection.prototype.setRemoteDescription = function() {
- var pc = this;
- pc._sctp = null;
-
- if (sctpInDescription(arguments[0])) {
- // Check if the remote is FF.
- var isFirefox = getRemoteFirefoxVersion(arguments[0]);
-
- // Get the maximum message size the local peer is capable of sending
- var canSendMMS = getCanSendMaxMessageSize(isFirefox);
-
- // Get the maximum message size of the remote peer.
- var remoteMMS = getMaxMessageSize(arguments[0], isFirefox);
-
- // Determine final maximum message size
- var maxMessageSize;
- if (canSendMMS === 0 && remoteMMS === 0) {
- maxMessageSize = Number.POSITIVE_INFINITY;
- } else if (canSendMMS === 0 || remoteMMS === 0) {
- maxMessageSize = Math.max(canSendMMS, remoteMMS);
- } else {
- maxMessageSize = Math.min(canSendMMS, remoteMMS);
- }
-
- // Create a dummy RTCSctpTransport object and the 'maxMessageSize'
- // attribute.
- var sctp = {};
- Object.defineProperty(sctp, 'maxMessageSize', {
- get: function() {
- return maxMessageSize;
- }
- });
- pc._sctp = sctp;
- }
-
- return origSetRemoteDescription.apply(pc, arguments);
- };
- },
-
- shimSendThrowTypeError: function(window) {
- // Note: Although Firefox >= 57 has a native implementation, the maximum
- // message size can be reset for all data channels at a later stage.
- // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1426831
-
- var origCreateDataChannel =
- window.RTCPeerConnection.prototype.createDataChannel;
- window.RTCPeerConnection.prototype.createDataChannel = function() {
- var pc = this;
- var dataChannel = origCreateDataChannel.apply(pc, arguments);
- var origDataChannelSend = dataChannel.send;
-
- // Patch 'send' method
- dataChannel.send = function() {
- var dc = this;
- var data = arguments[0];
- var length = data.length || data.size || data.byteLength;
- if (length > pc.sctp.maxMessageSize) {
- throw new DOMException('Message too large (can send a maximum of ' +
- pc.sctp.maxMessageSize + ' bytes)', 'TypeError');
- }
- return origDataChannelSend.apply(dc, arguments);
- };
-
- return dataChannel;
- };
- }
-};
-
-},{"./utils":13,"sdp":2}],8:[function(require,module,exports){
-/*
- * Copyright (c) 2016 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.
- */
- /* eslint-env node */
-'use strict';
-
-var utils = require('../utils');
-var shimRTCPeerConnection = require('rtcpeerconnection-shim');
-
-module.exports = {
- shimGetUserMedia: require('./getusermedia'),
- shimPeerConnection: function(window) {
- var browserDetails = utils.detectBrowser(window);
-
- if (window.RTCIceGatherer) {
- // ORTC defines an RTCIceCandidate object but no constructor.
- // Not implemented in Edge.
- if (!window.RTCIceCandidate) {
- window.RTCIceCandidate = function(args) {
- return args;
- };
- }
- // ORTC does not have a session description object but
- // other browsers (i.e. Chrome) that will support both PC and ORTC
- // in the future might have this defined already.
- if (!window.RTCSessionDescription) {
- window.RTCSessionDescription = function(args) {
- return args;
- };
- }
- // this adds an additional event listener to MediaStrackTrack that signals
- // when a tracks enabled property was changed. Workaround for a bug in
- // addStream, see below. No longer required in 15025+
- if (browserDetails.version < 15025) {
- var origMSTEnabled = Object.getOwnPropertyDescriptor(
- window.MediaStreamTrack.prototype, 'enabled');
- Object.defineProperty(window.MediaStreamTrack.prototype, 'enabled', {
- set: function(value) {
- origMSTEnabled.set.call(this, value);
- var ev = new Event('enabled');
- ev.enabled = value;
- this.dispatchEvent(ev);
- }
- });
- }
- }
-
- // ORTC defines the DTMF sender a bit different.
- // https://github.com/w3c/ortc/issues/714
- if (window.RTCRtpSender && !('dtmf' in window.RTCRtpSender.prototype)) {
- Object.defineProperty(window.RTCRtpSender.prototype, 'dtmf', {
- get: function() {
- if (this._dtmf === undefined) {
- if (this.track.kind === 'audio') {
- this._dtmf = new window.RTCDtmfSender(this);
- } else if (this.track.kind === 'video') {
- this._dtmf = null;
- }
- }
- return this._dtmf;
- }
- });
- }
-
- window.RTCPeerConnection =
- shimRTCPeerConnection(window, browserDetails.version);
- },
- shimReplaceTrack: function(window) {
- // ORTC has replaceTrack -- https://github.com/w3c/ortc/issues/614
- if (window.RTCRtpSender &&
- !('replaceTrack' in window.RTCRtpSender.prototype)) {
- window.RTCRtpSender.prototype.replaceTrack =
- window.RTCRtpSender.prototype.setTrack;
- }
- }
-};
-
-},{"../utils":13,"./getusermedia":9,"rtcpeerconnection-shim":1}],9:[function(require,module,exports){
-/*
- * Copyright (c) 2016 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.
- */
- /* eslint-env node */
-'use strict';
-
-// Expose public methods.
-module.exports = function(window) {
- var navigator = window && window.navigator;
-
- var shimError_ = function(e) {
- return {
- name: {PermissionDeniedError: 'NotAllowedError'}[e.name] || e.name,
- message: e.message,
- constraint: e.constraint,
- toString: function() {
- return this.name;
- }
- };
- };
-
- // getUserMedia error shim.
- var origGetUserMedia = navigator.mediaDevices.getUserMedia.
- bind(navigator.mediaDevices);
- navigator.mediaDevices.getUserMedia = function(c) {
- return origGetUserMedia(c).catch(function(e) {
- return Promise.reject(shimError_(e));
- });
- };
-};
-
-},{}],10:[function(require,module,exports){
-/*
- * Copyright (c) 2016 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.
- */
- /* eslint-env node */
-'use strict';
-
-var utils = require('../utils');
-
-module.exports = {
- shimGetUserMedia: require('./getusermedia'),
- shimOnTrack: function(window) {
- if (typeof window === 'object' && window.RTCPeerConnection && !('ontrack' in
- window.RTCPeerConnection.prototype)) {
- Object.defineProperty(window.RTCPeerConnection.prototype, 'ontrack', {
- get: function() {
- return this._ontrack;
- },
- set: function(f) {
- if (this._ontrack) {
- this.removeEventListener('track', this._ontrack);
- this.removeEventListener('addstream', this._ontrackpoly);
- }
- this.addEventListener('track', this._ontrack = f);
- this.addEventListener('addstream', this._ontrackpoly = function(e) {
- e.stream.getTracks().forEach(function(track) {
- var event = new Event('track');
- event.track = track;
- event.receiver = {track: track};
- event.transceiver = {receiver: event.receiver};
- event.streams = [e.stream];
- this.dispatchEvent(event);
- }.bind(this));
- }.bind(this));
- }
- });
- }
- if (typeof window === 'object' && window.RTCTrackEvent &&
- ('receiver' in window.RTCTrackEvent.prototype) &&
- !('transceiver' in window.RTCTrackEvent.prototype)) {
- Object.defineProperty(window.RTCTrackEvent.prototype, 'transceiver', {
- get: function() {
- return {receiver: this.receiver};
- }
- });
- }
- },
-
- shimSourceObject: function(window) {
- // Firefox has supported mozSrcObject since FF22, unprefixed in 42.
- 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() {
- return this.mozSrcObject;
- },
- set: function(stream) {
- this.mozSrcObject = stream;
- }
- });
- }
- }
- },
-
- shimPeerConnection: function(window) {
- var browserDetails = utils.detectBrowser(window);
-
- if (typeof window !== 'object' || !(window.RTCPeerConnection ||
- window.mozRTCPeerConnection)) {
- return; // probably media.peerconnection.enabled=false in about:config
- }
- // The RTCPeerConnection object.
- if (!window.RTCPeerConnection) {
- window.RTCPeerConnection = function(pcConfig, pcConstraints) {
- if (browserDetails.version < 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 window.mozRTCPeerConnection(pcConfig, pcConstraints);
- };
- window.RTCPeerConnection.prototype =
- window.mozRTCPeerConnection.prototype;
-
- // wrap static methods. Currently just generateCertificate.
- if (window.mozRTCPeerConnection.generateCertificate) {
- Object.defineProperty(window.RTCPeerConnection, 'generateCertificate', {
- get: function() {
- return window.mozRTCPeerConnection.generateCertificate;
- }
- });
- }
-
- window.RTCSessionDescription = window.mozRTCSessionDescription;
- window.RTCIceCandidate = window.mozRTCIceCandidate;
- }
-
- // shim away need for obsolete RTCIceCandidate/RTCSessionDescription.
- ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate']
- .forEach(function(method) {
- var nativeMethod = window.RTCPeerConnection.prototype[method];
- window.RTCPeerConnection.prototype[method] = function() {
- arguments[0] = new ((method === 'addIceCandidate') ?
- window.RTCIceCandidate :
- window.RTCSessionDescription)(arguments[0]);
- return nativeMethod.apply(this, arguments);
- };
- });
-
- // support for addIceCandidate(null or undefined)
- var nativeAddIceCandidate =
- window.RTCPeerConnection.prototype.addIceCandidate;
- window.RTCPeerConnection.prototype.addIceCandidate = function() {
- if (!arguments[0]) {
- if (arguments[1]) {
- arguments[1].apply(null);
- }
- return Promise.resolve();
- }
- return nativeAddIceCandidate.apply(this, arguments);
- };
-
- // shim getStats with maplike support
- var makeMapStats = function(stats) {
- var map = new Map();
- Object.keys(stats).forEach(function(key) {
- map.set(key, stats[key]);
- map[key] = stats[key];
- });
- return map;
- };
-
- var modernStatsTypes = {
- inboundrtp: 'inbound-rtp',
- outboundrtp: 'outbound-rtp',
- candidatepair: 'candidate-pair',
- localcandidate: 'local-candidate',
- remotecandidate: 'remote-candidate'
- };
-
- var nativeGetStats = window.RTCPeerConnection.prototype.getStats;
- window.RTCPeerConnection.prototype.getStats = function(
- selector,
- onSucc,
- onErr
- ) {
- return nativeGetStats.apply(this, [selector || null])
- .then(function(stats) {
- if (browserDetails.version < 48) {
- stats = makeMapStats(stats);
- }
- if (browserDetails.version < 53 && !onSucc) {
- // Shim only promise getStats with spec-hyphens in type names
- // Leave callback version alone; misc old uses of forEach before Map
- try {
- stats.forEach(function(stat) {
- stat.type = modernStatsTypes[stat.type] || stat.type;
- });
- } catch (e) {
- if (e.name !== 'TypeError') {
- throw e;
- }
- // Avoid TypeError: "type" is read-only, in old versions. 34-43ish
- stats.forEach(function(stat, i) {
- stats.set(i, Object.assign({}, stat, {
- type: modernStatsTypes[stat.type] || stat.type
- }));
- });
- }
- }
- return stats;
- })
- .then(onSucc, onErr);
- };
- },
-
- shimRemoveStream: function(window) {
- if (!window.RTCPeerConnection ||
- 'removeStream' in window.RTCPeerConnection.prototype) {
- return;
- }
- window.RTCPeerConnection.prototype.removeStream = function(stream) {
- var pc = this;
- utils.deprecated('removeStream', 'removeTrack');
- this.getSenders().forEach(function(sender) {
- if (sender.track && stream.getTracks().indexOf(sender.track) !== -1) {
- pc.removeTrack(sender);
- }
- });
- };
- }
-};
-
-},{"../utils":13,"./getusermedia":11}],11:[function(require,module,exports){
-/*
- * Copyright (c) 2016 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.
- */
- /* eslint-env node */
-'use strict';
-
-var utils = require('../utils');
-var logging = utils.log;
-
-// Expose public methods.
-module.exports = function(window) {
- var browserDetails = utils.detectBrowser(window);
- var navigator = window && window.navigator;
- var MediaStreamTrack = window && window.MediaStreamTrack;
-
- var shimError_ = function(e) {
- return {
- name: {
- InternalError: 'NotReadableError',
- NotSupportedError: 'TypeError',
- PermissionDeniedError: 'NotAllowedError',
- SecurityError: 'NotAllowedError'
- }[e.name] || e.name,
- message: {
- 'The operation is insecure.': 'The request is not allowed by the ' +
- 'user agent or the platform in the current context.'
- }[e.message] || e.message,
- constraint: e.constraint,
- toString: function() {
- return this.name + (this.message && ': ') + this.message;
- }
- };
- };
-
- // getUserMedia constraints shim.
- var 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;
- };
- constraints = JSON.parse(JSON.stringify(constraints));
- if (browserDetails.version < 38) {
- logging('spec: ' + JSON.stringify(constraints));
- if (constraints.audio) {
- constraints.audio = constraintsToFF37_(constraints.audio);
- }
- if (constraints.video) {
- constraints.video = constraintsToFF37_(constraints.video);
- }
- logging('ff37: ' + JSON.stringify(constraints));
- }
- return navigator.mozGetUserMedia(constraints, onSuccess, function(e) {
- onError(shimError_(e));
- });
- };
-
- // Returns the result of getUserMedia as a Promise.
- var getUserMediaPromise_ = function(constraints) {
- return new Promise(function(resolve, reject) {
- getUserMedia_(constraints, resolve, reject);
- });
- };
-
- // Shim for mediaDevices on older versions.
- if (!navigator.mediaDevices) {
- navigator.mediaDevices = {getUserMedia: getUserMediaPromise_,
- 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 (browserDetails.version < 41) {
- // Work around http://bugzil.la/1169665
- var orgEnumerateDevices =
- navigator.mediaDevices.enumerateDevices.bind(navigator.mediaDevices);
- navigator.mediaDevices.enumerateDevices = function() {
- return orgEnumerateDevices().then(undefined, function(e) {
- if (e.name === 'NotFoundError') {
- return [];
- }
- throw e;
- });
- };
- }
- if (browserDetails.version < 49) {
- var origGetUserMedia = navigator.mediaDevices.getUserMedia.
- bind(navigator.mediaDevices);
- navigator.mediaDevices.getUserMedia = function(c) {
- return origGetUserMedia(c).then(function(stream) {
- // Work around https://bugzil.la/802326
- if (c.audio && !stream.getAudioTracks().length ||
- c.video && !stream.getVideoTracks().length) {
- stream.getTracks().forEach(function(track) {
- track.stop();
- });
- throw new DOMException('The object can not be found here.',
- 'NotFoundError');
- }
- return stream;
- }, function(e) {
- return Promise.reject(shimError_(e));
- });
- };
- }
- if (!(browserDetails.version > 55 &&
- 'autoGainControl' in navigator.mediaDevices.getSupportedConstraints())) {
- var remap = function(obj, a, b) {
- if (a in obj && !(b in obj)) {
- obj[b] = obj[a];
- delete obj[a];
- }
- };
-
- var nativeGetUserMedia = navigator.mediaDevices.getUserMedia.
- bind(navigator.mediaDevices);
- navigator.mediaDevices.getUserMedia = function(c) {
- if (typeof c === 'object' && typeof c.audio === 'object') {
- c = JSON.parse(JSON.stringify(c));
- remap(c.audio, 'autoGainControl', 'mozAutoGainControl');
- remap(c.audio, 'noiseSuppression', 'mozNoiseSuppression');
- }
- return nativeGetUserMedia(c);
- };
-
- if (MediaStreamTrack && MediaStreamTrack.prototype.getSettings) {
- var nativeGetSettings = MediaStreamTrack.prototype.getSettings;
- MediaStreamTrack.prototype.getSettings = function() {
- var obj = nativeGetSettings.apply(this, arguments);
- remap(obj, 'mozAutoGainControl', 'autoGainControl');
- remap(obj, 'mozNoiseSuppression', 'noiseSuppression');
- return obj;
- };
- }
-
- if (MediaStreamTrack && MediaStreamTrack.prototype.applyConstraints) {
- var nativeApplyConstraints = MediaStreamTrack.prototype.applyConstraints;
- MediaStreamTrack.prototype.applyConstraints = function(c) {
- if (this.kind === 'audio' && typeof c === 'object') {
- c = JSON.parse(JSON.stringify(c));
- remap(c, 'autoGainControl', 'mozAutoGainControl');
- remap(c, 'noiseSuppression', 'mozNoiseSuppression');
- }
- return nativeApplyConstraints.apply(this, [c]);
- };
- }
- }
- navigator.getUserMedia = function(constraints, onSuccess, onError) {
- if (browserDetails.version < 44) {
- return getUserMedia_(constraints, onSuccess, onError);
- }
- // Replace Firefox 44+'s deprecation warning with unprefixed version.
- utils.deprecated('navigator.getUserMedia',
- 'navigator.mediaDevices.getUserMedia');
- navigator.mediaDevices.getUserMedia(constraints).then(onSuccess, onError);
- };
-};
-
-},{"../utils":13}],12:[function(require,module,exports){
-/*
- * Copyright (c) 2016 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.
- */
-'use strict';
-var utils = require('../utils');
-
-module.exports = {
- shimLocalStreamsAPI: function(window) {
- if (typeof window !== 'object' || !window.RTCPeerConnection) {
- return;
- }
- if (!('getLocalStreams' in window.RTCPeerConnection.prototype)) {
- window.RTCPeerConnection.prototype.getLocalStreams = function() {
- if (!this._localStreams) {
- this._localStreams = [];
- }
- return this._localStreams;
- };
- }
- if (!('getStreamById' in window.RTCPeerConnection.prototype)) {
- window.RTCPeerConnection.prototype.getStreamById = function(id) {
- var result = null;
- if (this._localStreams) {
- this._localStreams.forEach(function(stream) {
- if (stream.id === id) {
- result = stream;
- }
- });
- }
- if (this._remoteStreams) {
- this._remoteStreams.forEach(function(stream) {
- if (stream.id === id) {
- result = stream;
- }
- });
- }
- return result;
- };
- }
- if (!('addStream' in window.RTCPeerConnection.prototype)) {
- var _addTrack = window.RTCPeerConnection.prototype.addTrack;
- window.RTCPeerConnection.prototype.addStream = function(stream) {
- if (!this._localStreams) {
- this._localStreams = [];
- }
- if (this._localStreams.indexOf(stream) === -1) {
- this._localStreams.push(stream);
- }
- var pc = this;
- stream.getTracks().forEach(function(track) {
- _addTrack.call(pc, track, stream);
- });
- };
-
- window.RTCPeerConnection.prototype.addTrack = function(track, stream) {
- if (stream) {
- if (!this._localStreams) {
- this._localStreams = [stream];
- } else if (this._localStreams.indexOf(stream) === -1) {
- this._localStreams.push(stream);
- }
- }
- return _addTrack.call(this, track, stream);
- };
- }
- if (!('removeStream' in window.RTCPeerConnection.prototype)) {
- window.RTCPeerConnection.prototype.removeStream = function(stream) {
- if (!this._localStreams) {
- this._localStreams = [];
- }
- var index = this._localStreams.indexOf(stream);
- if (index === -1) {
- return;
- }
- this._localStreams.splice(index, 1);
- var pc = this;
- var tracks = stream.getTracks();
- this.getSenders().forEach(function(sender) {
- if (tracks.indexOf(sender.track) !== -1) {
- pc.removeTrack(sender);
- }
- });
- };
- }
- },
- shimRemoteStreamsAPI: function(window) {
- if (typeof window !== 'object' || !window.RTCPeerConnection) {
- return;
- }
- if (!('getRemoteStreams' in window.RTCPeerConnection.prototype)) {
- window.RTCPeerConnection.prototype.getRemoteStreams = function() {
- return this._remoteStreams ? this._remoteStreams : [];
- };
- }
- if (!('onaddstream' in window.RTCPeerConnection.prototype)) {
- Object.defineProperty(window.RTCPeerConnection.prototype, 'onaddstream', {
- get: function() {
- return this._onaddstream;
- },
- set: function(f) {
- var pc = this;
- if (this._onaddstream) {
- this.removeEventListener('addstream', this._onaddstream);
- this.removeEventListener('track', this._onaddstreampoly);
- }
- this.addEventListener('addstream', this._onaddstream = f);
- this.addEventListener('track', this._onaddstreampoly = function(e) {
- e.streams.forEach(function(stream) {
- if (!pc._remoteStreams) {
- pc._remoteStreams = [];
- }
- if (pc._remoteStreams.indexOf(stream) >= 0) {
- return;
- }
- pc._remoteStreams.push(stream);
- var event = new Event('addstream');
- event.stream = stream;
- pc.dispatchEvent(event);
- });
- });
- }
- });
- }
- },
- shimCallbacksAPI: function(window) {
- if (typeof window !== 'object' || !window.RTCPeerConnection) {
- return;
- }
- var prototype = window.RTCPeerConnection.prototype;
- var createOffer = prototype.createOffer;
- var createAnswer = prototype.createAnswer;
- var setLocalDescription = prototype.setLocalDescription;
- var setRemoteDescription = prototype.setRemoteDescription;
- var addIceCandidate = prototype.addIceCandidate;
-
- prototype.createOffer = function(successCallback, failureCallback) {
- var options = (arguments.length >= 2) ? arguments[2] : arguments[0];
- var promise = createOffer.apply(this, [options]);
- if (!failureCallback) {
- return promise;
- }
- promise.then(successCallback, failureCallback);
- return Promise.resolve();
- };
-
- prototype.createAnswer = function(successCallback, failureCallback) {
- var options = (arguments.length >= 2) ? arguments[2] : arguments[0];
- var promise = createAnswer.apply(this, [options]);
- if (!failureCallback) {
- return promise;
- }
- promise.then(successCallback, failureCallback);
- return Promise.resolve();
- };
-
- var withCallback = function(description, successCallback, failureCallback) {
- var promise = setLocalDescription.apply(this, [description]);
- if (!failureCallback) {
- return promise;
- }
- promise.then(successCallback, failureCallback);
- return Promise.resolve();
- };
- prototype.setLocalDescription = withCallback;
-
- withCallback = function(description, successCallback, failureCallback) {
- var promise = setRemoteDescription.apply(this, [description]);
- if (!failureCallback) {
- return promise;
- }
- promise.then(successCallback, failureCallback);
- return Promise.resolve();
- };
- prototype.setRemoteDescription = withCallback;
-
- withCallback = function(candidate, successCallback, failureCallback) {
- var promise = addIceCandidate.apply(this, [candidate]);
- if (!failureCallback) {
- return promise;
- }
- promise.then(successCallback, failureCallback);
- return Promise.resolve();
- };
- prototype.addIceCandidate = withCallback;
- },
- shimGetUserMedia: function(window) {
- var navigator = window && window.navigator;
-
- if (!navigator.getUserMedia) {
- if (navigator.webkitGetUserMedia) {
- navigator.getUserMedia = navigator.webkitGetUserMedia.bind(navigator);
- } else if (navigator.mediaDevices &&
- navigator.mediaDevices.getUserMedia) {
- navigator.getUserMedia = function(constraints, cb, errcb) {
- navigator.mediaDevices.getUserMedia(constraints)
- .then(cb, errcb);
- }.bind(navigator);
- }
- }
- },
- shimRTCIceServerUrls: function(window) {
- // migrate from non-spec RTCIceServer.url to RTCIceServer.urls
- var OrigPeerConnection = window.RTCPeerConnection;
- window.RTCPeerConnection = function(pcConfig, pcConstraints) {
- if (pcConfig && pcConfig.iceServers) {
- var newIceServers = [];
- for (var i = 0; i < pcConfig.iceServers.length; i++) {
- var server = pcConfig.iceServers[i];
- if (!server.hasOwnProperty('urls') &&
- server.hasOwnProperty('url')) {
- utils.deprecated('RTCIceServer.url', 'RTCIceServer.urls');
- server = JSON.parse(JSON.stringify(server));
- server.urls = server.url;
- delete server.url;
- newIceServers.push(server);
- } else {
- newIceServers.push(pcConfig.iceServers[i]);
- }
- }
- pcConfig.iceServers = newIceServers;
- }
- return new OrigPeerConnection(pcConfig, pcConstraints);
- };
- window.RTCPeerConnection.prototype = OrigPeerConnection.prototype;
- // wrap static methods. Currently just generateCertificate.
- if ('generateCertificate' in window.RTCPeerConnection) {
- Object.defineProperty(window.RTCPeerConnection, 'generateCertificate', {
- get: function() {
- return OrigPeerConnection.generateCertificate;
- }
- });
- }
- },
- shimTrackEventTransceiver: function(window) {
- // Add event.transceiver member over deprecated event.receiver
- if (typeof window === 'object' && window.RTCPeerConnection &&
- ('receiver' in window.RTCTrackEvent.prototype) &&
- // can't check 'transceiver' in window.RTCTrackEvent.prototype, as it is
- // defined for some reason even when window.RTCTransceiver is not.
- !window.RTCTransceiver) {
- Object.defineProperty(window.RTCTrackEvent.prototype, 'transceiver', {
- get: function() {
- return {receiver: this.receiver};
- }
- });
- }
- },
-
- shimCreateOfferLegacy: function(window) {
- var origCreateOffer = window.RTCPeerConnection.prototype.createOffer;
- window.RTCPeerConnection.prototype.createOffer = function(offerOptions) {
- var pc = this;
- if (offerOptions) {
- var audioTransceiver = pc.getTransceivers().find(function(transceiver) {
- return transceiver.sender.track &&
- transceiver.sender.track.kind === 'audio';
- });
- if (offerOptions.offerToReceiveAudio === false && audioTransceiver) {
- if (audioTransceiver.direction === 'sendrecv') {
- if (audioTransceiver.setDirection) {
- audioTransceiver.setDirection('sendonly');
- } else {
- audioTransceiver.direction = 'sendonly';
- }
- } else if (audioTransceiver.direction === 'recvonly') {
- if (audioTransceiver.setDirection) {
- audioTransceiver.setDirection('inactive');
- } else {
- audioTransceiver.direction = 'inactive';
- }
- }
- } else if (offerOptions.offerToReceiveAudio === true &&
- !audioTransceiver) {
- pc.addTransceiver('audio');
- }
-
- var videoTransceiver = pc.getTransceivers().find(function(transceiver) {
- return transceiver.sender.track &&
- transceiver.sender.track.kind === 'video';
- });
- if (offerOptions.offerToReceiveVideo === false && videoTransceiver) {
- if (videoTransceiver.direction === 'sendrecv') {
- videoTransceiver.setDirection('sendonly');
- } else if (videoTransceiver.direction === 'recvonly') {
- videoTransceiver.setDirection('inactive');
- }
- } else if (offerOptions.offerToReceiveVideo === true &&
- !videoTransceiver) {
- pc.addTransceiver('video');
- }
- }
- return origCreateOffer.apply(pc, arguments);
- };
- }
-};
-
-},{"../utils":13}],13:[function(require,module,exports){
-/*
- * Copyright (c) 2016 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.
- */
- /* eslint-env node */
-'use strict';
-
-var logDisabled_ = true;
-var deprecationWarnings_ = true;
-
-/**
- * Extract browser version out of the provided user agent string.
- *
- * @param {!string} uastring userAgent string.
- * @param {!string} expr Regular expression used as match criteria.
- * @param {!number} pos position in the version string to be returned.
- * @return {!number} browser version.
- */
-function extractVersion(uastring, expr, pos) {
- var match = uastring.match(expr);
- return match && match.length >= pos && parseInt(match[pos], 10);
-}
-
-// Wraps the peerconnection event eventNameToWrap in a function
-// which returns the modified event object.
-function wrapPeerConnectionEvent(window, eventNameToWrap, wrapper) {
- if (!window.RTCPeerConnection) {
- return;
- }
- var proto = window.RTCPeerConnection.prototype;
- var nativeAddEventListener = proto.addEventListener;
- proto.addEventListener = function(nativeEventName, cb) {
- if (nativeEventName !== eventNameToWrap) {
- return nativeAddEventListener.apply(this, arguments);
- }
- var wrappedCallback = function(e) {
- cb(wrapper(e));
- };
- this._eventMap = this._eventMap || {};
- this._eventMap[cb] = wrappedCallback;
- return nativeAddEventListener.apply(this, [nativeEventName,
- wrappedCallback]);
- };
-
- var nativeRemoveEventListener = proto.removeEventListener;
- proto.removeEventListener = function(nativeEventName, cb) {
- if (nativeEventName !== eventNameToWrap || !this._eventMap
- || !this._eventMap[cb]) {
- return nativeRemoveEventListener.apply(this, arguments);
- }
- var unwrappedCb = this._eventMap[cb];
- delete this._eventMap[cb];
- return nativeRemoveEventListener.apply(this, [nativeEventName,
- unwrappedCb]);
- };
-
- Object.defineProperty(proto, 'on' + eventNameToWrap, {
- get: function() {
- return this['_on' + eventNameToWrap];
- },
- set: function(cb) {
- if (this['_on' + eventNameToWrap]) {
- this.removeEventListener(eventNameToWrap,
- this['_on' + eventNameToWrap]);
- delete this['_on' + eventNameToWrap];
- }
- if (cb) {
- this.addEventListener(eventNameToWrap,
- this['_on' + eventNameToWrap] = cb);
- }
- }
- });
-}
-
-// Utility methods.
-module.exports = {
- extractVersion: extractVersion,
- wrapPeerConnectionEvent: wrapPeerConnectionEvent,
- disableLog: function(bool) {
- if (typeof bool !== 'boolean') {
- return new Error('Argument type: ' + typeof bool +
- '. Please use a boolean.');
- }
- logDisabled_ = bool;
- return (bool) ? 'adapter.js logging disabled' :
- 'adapter.js logging enabled';
- },
-
- /**
- * Disable or enable deprecation warnings
- * @param {!boolean} bool set to true to disable warnings.
- */
- disableWarnings: function(bool) {
- if (typeof bool !== 'boolean') {
- return new Error('Argument type: ' + typeof bool +
- '. Please use a boolean.');
- }
- deprecationWarnings_ = !bool;
- return 'adapter.js deprecation warnings ' + (bool ? 'disabled' : 'enabled');
- },
-
- log: function() {
- if (typeof window === 'object') {
- if (logDisabled_) {
- return;
- }
- if (typeof console !== 'undefined' && typeof console.log === 'function') {
- console.log.apply(console, arguments);
- }
- }
- },
-
- /**
- * Shows a deprecation warning suggesting the modern and spec-compatible API.
- */
- deprecated: function(oldMethod, newMethod) {
- if (!deprecationWarnings_) {
- return;
- }
- console.warn(oldMethod + ' is deprecated, please use ' + newMethod +
- ' instead.');
- },
-
- /**
- * Browser detector.
- *
- * @return {object} result containing browser and version
- * properties.
- */
- detectBrowser: function(window) {
- var navigator = window && window.navigator;
-
- // Returned result object.
- var result = {};
- result.browser = null;
- result.version = null;
-
- // Fail early if it's not a browser
- if (typeof window === 'undefined' || !window.navigator) {
- result.browser = 'Not a browser.';
- return result;
- }
-
- if (navigator.mozGetUserMedia) { // Firefox.
- result.browser = 'firefox';
- result.version = extractVersion(navigator.userAgent,
- /Firefox\/(\d+)\./, 1);
- } else if (navigator.webkitGetUserMedia) {
- // Chrome, Chromium, Webview, Opera.
- // Version matches Chrome/WebRTC version.
- result.browser = 'chrome';
- result.version = extractVersion(navigator.userAgent,
- /Chrom(e|ium)\/(\d+)\./, 2);
- } else if (navigator.mediaDevices &&
- navigator.userAgent.match(/Edge\/(\d+).(\d+)$/)) { // Edge.
- result.browser = 'edge';
- result.version = extractVersion(navigator.userAgent,
- /Edge\/(\d+).(\d+)$/, 2);
- } else if (navigator.mediaDevices &&
- navigator.userAgent.match(/AppleWebKit\/(\d+)\./)) { // Safari.
- result.browser = 'safari';
- result.version = extractVersion(navigator.userAgent,
- /AppleWebKit\/(\d+)\./, 1);
- } else { // Default fallthrough: not supported.
- result.browser = 'Not a supported browser.';
- return result;
- }
-
- return result;
- }
-};
-
-},{}]},{},[3])(3)
-});
\ No newline at end of file
+(function($){function findLine(sdpLines,prefix,substr){return findLineInRange(sdpLines,0,-1,prefix,substr);}
+function findLineInRange(sdpLines,startLine,endLine,prefix,substr){var realEndLine=(endLine!=-1)?endLine:sdpLines.length;for(var i=startLine;i=0;if(iOS){self.options.useVideo.setAttribute("playsinline",true);}}
+var element=self.options.useAudio;console.log("REMOTE STREAM",stream,element);FSRTCattachMediaStream(element,stream);self.remoteStream=stream;onRemoteStreamSuccess(self,stream);}
+function onOfferSDP(self,sdp){self.mediaData.SDP=self.stereoHack(sdp.sdp);console.log("Offer SDP");doCallback(self,"onOfferSDP");}
+$.FSRTC.prototype.answer=function(sdp,onSuccess,onError){this.peer.addAnswerSDP({type:"answer",sdp:sdp},onSuccess,onError);};$.FSRTC.prototype.stopPeer=function(){if(self.peer){console.log("stopping peer");self.peer.stop();}}
+$.FSRTC.prototype.stop=function(){var self=this;if(self.options.useVideo){self.options.useVideo.style.display='none';self.options.useVideo['src']='';}
+if(self.localStream&&!self.options.useStream){if(typeof self.localStream.stop=='function'){self.localStream.stop();}else{if(self.localStream.active){var tracks=self.localStream.getTracks();console.log(tracks);tracks.forEach(function(track,index){console.log(track);track.stop();})}}
+self.localStream=null;}
+if(self.options.localVideo){deactivateLocalVideo(self.options.localVideo);}
+if(self.options.localVideoStream&&!self.options.useStream){if(typeof self.options.localVideoStream.stop=='function'){self.options.localVideoStream.stop();}else{if(self.options.localVideoStream.active){var tracks=self.options.localVideoStream.getTracks();console.log(tracks);tracks.forEach(function(track,index){console.log(track);track.stop();})}}}
+if(self.peer){console.log("stopping peer");self.peer.stop();}};$.FSRTC.prototype.getMute=function(){var self=this;return self.audioEnabled;}
+$.FSRTC.prototype.setMute=function(what){var self=this;if(!self.localStream){return false;}
+var audioTracks=self.localStream.getAudioTracks();for(var i=0,len=audioTracks.length;i=w&&$.FSRTC.validRes[i][1]>=h){w=$.FSRTC.validRes[i][0];h=$.FSRTC.validRes[i][1];}}
+return[w,h];}
+var resList=[[160,120],[320,180],[320,240],[640,360],[640,480],[1280,720],[1920,1080]];var resI=0;var ttl=0;var checkRes=function(cam,func){if(resI>=resList.length){var res={'validRes':$.FSRTC.validRes,'bestResSupported':$.FSRTC.bestResSupported()};localStorage.setItem("res_"+cam,$.toJSON(res));if(func)return func(res);return;}
+w=resList[resI][0];h=resList[resI][1];resI++;var video={width:{exact:w},height:{exact:h}};if(cam!=="any"){video=assignMediaIdToConstraint(cam,video);}
+getUserMedia({constraints:{audio:ttl++==0,video:video},onsuccess:function(e){e.getTracks().forEach(function(track){track.stop();});console.info(w+"x"+h+" supported.");$.FSRTC.validRes.push([w,h]);checkRes(cam,func);},onerror:function(e){console.warn(w+"x"+h+" not supported.");checkRes(cam,func);}});}
+$.FSRTC.getValidRes=function(cam,func){var used=[];var cached=localStorage.getItem("res_"+cam);if(cached){var cache=$.parseJSON(cached);if(cache){$.FSRTC.validRes=cache.validRes;console.log("CACHED RES FOR CAM "+cam,cache);}else{console.error("INVALID CACHE");}
+return func?func(cache):null;}
+$.FSRTC.validRes=[];resI=0;checkRes(cam,func);}
+$.FSRTC.checkPerms=function(runtime,check_audio,check_video){getUserMedia({constraints:{audio:check_audio,video:check_video,},onsuccess:function(e){e.getTracks().forEach(function(track){track.stop();});console.info("media perm init complete");if(runtime){setTimeout(runtime,100,true);}},onerror:function(e){if(check_video&&check_audio){console.error("error, retesting with audio params only");return $.FSRTC.checkPerms(runtime,check_audio,false);}
+console.error("media perm init error");if(runtime){runtime(false)}}});}})(jQuery);(function($){$.JsonRpcClient=function(options){var self=this;this.options=$.extend({ajaxUrl:null,socketUrl:null,onmessage:null,login:null,passwd:null,sessid:null,loginParams:null,userVariables:null,getSocket:function(onmessage_cb){return self._getSocket(onmessage_cb);}},options);self.ws_cnt=0;this.wsOnMessage=function(event){self._wsOnMessage(event);};};$.JsonRpcClient.prototype._ws_socket=null;$.JsonRpcClient.prototype._ws_callbacks={};$.JsonRpcClient.prototype._current_id=1;$.JsonRpcClient.prototype.speedTest=function(bytes,cb){var socket=this.options.getSocket(this.wsOnMessage);if(socket!==null){this.speedCB=cb;this.speedBytes=bytes;socket.send("#SPU "+bytes);var loops=bytes/1024;var rem=bytes%1024;var i;var data=new Array(1024).join(".");for(i=0;i1){return false;}
+return true;};$.JsonRpcClient.prototype.closeSocket=function(){var self=this;if(self.socketReady()){self._ws_socket.onclose=function(w){console.log("Closing Socket");};self._ws_socket.close();}};$.JsonRpcClient.prototype.loginData=function(params){var self=this;self.options.login=params.login;self.options.passwd=params.passwd;self.options.loginParams=params.loginParams;self.options.userVariables=params.userVariables;};$.JsonRpcClient.prototype.connectSocket=function(onmessage_cb){var self=this;if(self.to){clearTimeout(self.to);}
+if(!self.socketReady()){self.authing=false;if(self._ws_socket){delete self._ws_socket;}
+self._ws_socket=new WebSocket(self.options.socketUrl);if(self._ws_socket){self._ws_socket.onmessage=onmessage_cb;self._ws_socket.onclose=function(w){if(!self.ws_sleep){self.ws_sleep=1000;}
+if(self.options.onWSClose){self.options.onWSClose(self);}
+if(self.ws_cnt>10&&self.options.wsFallbackURL){self.options.socketUrl=self.options.wsFallbackURL;}
+console.error("Websocket Lost "+self.ws_cnt+" sleep: "+self.ws_sleep+"msec");self.to=setTimeout(function(){console.log("Attempting Reconnection....");self.connectSocket(onmessage_cb);},self.ws_sleep);self.ws_cnt++;if(self.ws_sleep<3000&&(self.ws_cnt%10)===0){self.ws_sleep+=1000;}};self._ws_socket.onopen=function(){if(self.to){clearTimeout(self.to);}
+self.ws_sleep=1000;self.ws_cnt=0;if(self.options.onWSConnect){self.options.onWSConnect(self);}
+var req;while((req=$.JsonRpcClient.q.pop())){self._ws_socket.send(req);}};}}
+return self._ws_socket?true:false;};$.JsonRpcClient.prototype.stopRetrying=function(){if(self.to)
+clearTimeout(self.to);}
+$.JsonRpcClient.prototype._getSocket=function(onmessage_cb){if(this.options.socketUrl===null||!("WebSocket"in window))return null;this.connectSocket(onmessage_cb);return this._ws_socket;};$.JsonRpcClient.q=[];$.JsonRpcClient.prototype._wsCall=function(socket,request,success_cb,error_cb){var request_json=$.toJSON(request);if(socket.readyState<1){self=this;$.JsonRpcClient.q.push(request_json);}else{socket.send(request_json);}
+if('id'in request&&typeof success_cb!=='undefined'){this._ws_callbacks[request.id]={request:request_json,request_obj:request,success_cb:success_cb,error_cb:error_cb};}};$.JsonRpcClient.prototype._wsOnMessage=function(event){var response;if(event.data[0]=="#"&&event.data[1]=="S"&&event.data[2]=="P"){if(event.data[3]=="U"){this.up_dur=parseInt(event.data.substring(4));}else if(this.speedCB&&event.data[3]=="D"){this.down_dur=parseInt(event.data.substring(4));var up_kps=(((this.speedBytes*8)/(this.up_dur/1000))/1024).toFixed(0);var down_kps=(((this.speedBytes*8)/(this.down_dur/1000))/1024).toFixed(0);console.info("Speed Test: Up: "+up_kps+" Down: "+down_kps);var cb=this.speedCB;this.speedCB=null;cb(event,{upDur:this.up_dur,downDur:this.down_dur,upKPS:up_kps,downKPS:down_kps});}
+return;}
+try{response=$.parseJSON(event.data);if(typeof response==='object'&&'jsonrpc'in response&&response.jsonrpc==='2.0'){if('result'in response&&this._ws_callbacks[response.id]){var success_cb=this._ws_callbacks[response.id].success_cb;delete this._ws_callbacks[response.id];success_cb(response.result,this);return;}else if('error'in response&&this._ws_callbacks[response.id]){var error_cb=this._ws_callbacks[response.id].error_cb;var orig_req=this._ws_callbacks[response.id].request;if(!self.authing&&response.error.code==-32000&&self.options.login&&self.options.passwd){self.authing=true;this.call("login",{login:self.options.login,passwd:self.options.passwd,loginParams:self.options.loginParams,userVariables:self.options.userVariables},this._ws_callbacks[response.id].request_obj.method=="login"?function(e){self.authing=false;console.log("logged in");delete self._ws_callbacks[response.id];if(self.options.onWSLogin){self.options.onWSLogin(true,self);}}:function(e){self.authing=false;console.log("logged in, resending request id: "+response.id);var socket=self.options.getSocket(self.wsOnMessage);if(socket!==null){socket.send(orig_req);}
+if(self.options.onWSLogin){self.options.onWSLogin(true,self);}},function(e){console.log("error logging in, request id:",response.id);delete self._ws_callbacks[response.id];error_cb(response.error,this);if(self.options.onWSLogin){self.options.onWSLogin(false,self);}});return;}
+delete this._ws_callbacks[response.id];error_cb(response.error,this);return;}}}catch(err){console.log("ERROR: "+err);return;}
+if(typeof this.options.onmessage==='function'){event.eventData=response;if(!event.eventData){event.eventData={};}
+var reply=this.options.onmessage(event);if(reply&&typeof reply==="object"&&event.eventData.id){var msg={jsonrpc:"2.0",id:event.eventData.id,result:reply};var socket=self.options.getSocket(self.wsOnMessage);if(socket!==null){socket.send($.toJSON(msg));}}}};$.JsonRpcClient._batchObject=function(jsonrpcclient,all_done_cb,error_cb){this._requests=[];this.jsonrpcclient=jsonrpcclient;this.all_done_cb=all_done_cb;this.error_cb=typeof error_cb==='function'?error_cb:function(){};};$.JsonRpcClient._batchObject.prototype.call=function(method,params,success_cb,error_cb){if(!params){params={};}
+if(this.options.sessid){params.sessid=this.options.sessid;}
+if(!success_cb){success_cb=function(e){console.log("Success: ",e);};}
+if(!error_cb){error_cb=function(e){console.log("Error: ",e);};}
+this._requests.push({request:{jsonrpc:'2.0',method:method,params:params,id:this.jsonrpcclient._current_id++},success_cb:success_cb,error_cb:error_cb});};$.JsonRpcClient._batchObject.prototype.notify=function(method,params){if(this.options.sessid){params.sessid=this.options.sessid;}
+this._requests.push({request:{jsonrpc:'2.0',method:method,params:params}});};$.JsonRpcClient._batchObject.prototype._execute=function(){var self=this;if(this._requests.length===0)return;var batch_request=[];var handlers={};var i=0;var call;var success_cb;var error_cb;var socket=self.jsonrpcclient.options.getSocket(self.jsonrpcclient.wsOnMessage);if(socket!==null){for(i=0;i0){data.params.useVideo=true;}
+if(data.params.sdp&&data.params.sdp.indexOf("stereo=1")>0){data.params.useStereo=true;}
+dialog=new $.verto.dialog($.verto.enum.direction.inbound,verto,data.params);dialog.setState($.verto.enum.state.recovering);break;case'verto.invite':if(data.params.sdp&&data.params.sdp.indexOf("m=video")>0){data.params.wantVideo=true;}
+if(data.params.sdp&&data.params.sdp.indexOf("stereo=1")>0){data.params.useStereo=true;}
+dialog=new $.verto.dialog($.verto.enum.direction.inbound,verto,data.params);break;default:console.debug("INVALID METHOD OR NON-EXISTANT CALL REFERENCE IGNORED");break;}}
+return{method:data.method};}else{switch(data.method){case'verto.punt':verto.purge();verto.logout();break;case'verto.event':var list=null;var key=null;if(data.params){key=data.params.eventChannel;}
+if(key){list=verto.eventSUBS[key];if(!list){list=verto.eventSUBS[key.split(".")[0]];}}
+if(!list&&key&&key===verto.sessid){if(verto.callbacks.onMessage){verto.callbacks.onMessage(verto,null,$.verto.enum.message.pvtEvent,data.params);}}else if(!list&&key&&verto.dialogs[key]){verto.dialogs[key].sendMessage($.verto.enum.message.pvtEvent,data.params);}else if(!list){if(!key){key="UNDEFINED";}
+console.error("UNSUBBED or invalid EVENT "+key+" IGNORED");}else{for(var i in list){var sub=list[i];if(!sub||!sub.ready){console.error("invalid EVENT for "+key+" IGNORED");}else if(sub.handler){sub.handler(verto,data.params,sub.userData);}else if(verto.callbacks.onEvent){verto.callbacks.onEvent(verto,data.params,sub.userData);}else{console.log("EVENT:",data.params);}}}
+break;case"verto.info":if(verto.callbacks.onMessage){verto.callbacks.onMessage(verto,null,$.verto.enum.message.info,data.params.msg);}
+console.debug("MESSAGE from: "+data.params.msg.from,data.params.msg.body);break;case'verto.clientReady':if(verto.callbacks.onMessage){verto.callbacks.onMessage(verto,null,$.verto.enum.message.clientReady,data.params);}
+console.debug("CLIENT READY",data.params);break;default:console.error("INVALID METHOD OR NON-EXISTANT CALL REFERENCE IGNORED",data.method);break;}}};var del_array=function(array,name){var r=[];var len=array.length;for(var i=0;i=array.length){array.push(name);}else{var x=0;var n=[];var len=array.length;for(var i=0;i":"\n");});return str;};};$.verto.liveArray=function(verto,context,name,config){var la=this;var lastSerno=0;var binding=null;var user_obj=config.userObj;var local=false;hashArray.call(la);la._add=la.add;la._del=la.del;la._reorder=la.reorder;la._clear=la.clear;la.context=context;la.name=name;la.user_obj=user_obj;la.verto=verto;la.broadcast=function(channel,obj){verto.broadcast(channel,obj);};la.errs=0;la.clear=function(){la._clear();lastSerno=0;if(la.onChange){la.onChange(la,{action:"clear"});}};la.checkSerno=function(serno){if(serno<0){return true;}
+if(lastSerno>0&&serno!=(lastSerno+1)){if(la.onErr){la.onErr(la,{lastSerno:lastSerno,serno:serno});}
+la.errs++;console.debug(la.errs);if(la.errs<3){la.bootstrap(la.user_obj);}
+return false;}else{lastSerno=serno;return true;}};la.reorder=function(serno,a){if(la.checkSerno(serno)){la._reorder(a);if(la.onChange){la.onChange(la,{serno:serno,action:"reorder"});}}};la.init=function(serno,val,key,index){if(key===null||key===undefined){key=serno;}
+if(la.checkSerno(serno)){if(la.onChange){la.onChange(la,{serno:serno,action:"init",index:index,key:key,data:val});}}};la.bootObj=function(serno,val){if(la.checkSerno(serno)){for(var i in val){la._add(val[i][0],val[i][1]);}
+if(la.onChange){la.onChange(la,{serno:serno,action:"bootObj",data:val,redraw:true});}}};la.add=function(serno,val,key,index){if(key===null||key===undefined){key=serno;}
+if(la.checkSerno(serno)){var redraw=la._add(key,val,index);if(la.onChange){la.onChange(la,{serno:serno,action:"add",index:index,key:key,data:val,redraw:redraw});}}};la.modify=function(serno,val,key,index){if(key===null||key===undefined){key=serno;}
+if(la.checkSerno(serno)){la._add(key,val,index);if(la.onChange){la.onChange(la,{serno:serno,action:"modify",key:key,data:val,index:index});}}};la.del=function(serno,key,index){if(key===null||key===undefined){key=serno;}
+if(la.checkSerno(serno)){if(index===null||index<0||index===undefined){index=la.indexOf(key);}
+var ok=la._del(key);if(ok&&la.onChange){la.onChange(la,{serno:serno,action:"del",key:key,index:index});}}};var eventHandler=function(v,e,la){var packet=e.data;if(packet.name!=la.name){return;}
+switch(packet.action){case"init":la.init(packet.wireSerno,packet.data,packet.hashKey,packet.arrIndex);break;case"bootObj":la.bootObj(packet.wireSerno,packet.data);break;case"add":la.add(packet.wireSerno,packet.data,packet.hashKey,packet.arrIndex);break;case"modify":if(!(packet.arrIndex||packet.hashKey)){console.error("Invalid Packet",packet);}else{la.modify(packet.wireSerno,packet.data,packet.hashKey,packet.arrIndex);}
+break;case"del":if(!(packet.arrIndex||packet.hashKey)){console.error("Invalid Packet",packet);}else{la.del(packet.wireSerno,packet.hashKey,packet.arrIndex);}
+break;case"clear":la.clear();break;case"reorder":la.reorder(packet.wireSerno,packet.order);break;default:if(la.checkSerno(packet.wireSerno)){if(la.onChange){la.onChange(la,{serno:packet.wireSerno,action:packet.action,data:packet.data});}}
+break;}};if(la.context){binding=la.verto.subscribe(la.context,{handler:eventHandler,userData:la,subParams:config.subParams});}
+la.destroy=function(){la._clear();la.verto.unsubscribe(binding);};la.sendCommand=function(cmd,obj){var self=la;self.broadcast(self.context,{liveArray:{command:cmd,context:self.context,name:self.name,obj:obj}});};la.bootstrap=function(obj){var self=la;la.sendCommand("bootstrap",obj);};la.changepage=function(obj){var self=la;self.clear();self.broadcast(self.context,{liveArray:{command:"changepage",context:la.context,name:la.name,obj:obj}});};la.heartbeat=function(obj){var self=la;var callback=function(){self.heartbeat.call(self,obj);};self.broadcast(self.context,{liveArray:{command:"heartbeat",context:self.context,name:self.name,obj:obj}});self.hb_pid=setTimeout(callback,30000);};la.bootstrap(la.user_obj);};$.verto.liveTable=function(verto,context,name,jq,config){var dt;var la=new $.verto.liveArray(verto,context,name,{subParams:config.subParams});var lt=this;lt.liveArray=la;lt.dataTable=dt;lt.verto=verto;lt.destroy=function(){if(dt){dt.fnDestroy();}
+if(la){la.destroy();}
+dt=null;la=null;};la.onErr=function(obj,args){console.error("Error: ",obj,args);};function genRow(data){if(typeof(data[4])==="string"&&data[4].indexOf("{")>-1){var tmp=$.parseJSON(data[4]);data[4]=tmp.oldStatus;data[5]=null;}
+return data;}
+function genArray(obj){var data=obj.asArray();for(var i in data){data[i]=genRow(data[i]);}
+return data;}
+la.onChange=function(obj,args){var index=0;var iserr=0;if(!dt){if(!config.aoColumns){if(args.action!="init"){return;}
+config.aoColumns=[];for(var i in args.data){config.aoColumns.push({"sTitle":args.data[i]});}}
+dt=jq.dataTable(config);}
+if(dt&&(args.action=="del"||args.action=="modify")){index=args.index;if(index===undefined&&args.key){index=la.indexOf(args.key);}
+if(index===undefined){console.error("INVALID PACKET Missing INDEX\n",args);return;}}
+if(config.onChange){config.onChange(obj,args);}
+try{switch(args.action){case"bootObj":if(!args.data){console.error("missing data");return;}
+dt.fnClearTable();dt.fnAddData(genArray(obj));dt.fnAdjustColumnSizing();break;case"add":if(!args.data){console.error("missing data");return;}
+if(args.redraw>-1){dt.fnClearTable();dt.fnAddData(genArray(obj));}else{dt.fnAddData(genRow(args.data));}
+dt.fnAdjustColumnSizing();break;case"modify":if(!args.data){return;}
+dt.fnUpdate(genRow(args.data),index);dt.fnAdjustColumnSizing();break;case"del":dt.fnDeleteRow(index);dt.fnAdjustColumnSizing();break;case"clear":dt.fnClearTable();break;case"reorder":dt.fnClearTable();dt.fnAddData(genArray(obj));break;case"hide":jq.hide();break;case"show":jq.show();break;}}catch(err){console.error("ERROR: "+err);iserr++;}
+if(iserr){obj.errs++;if(obj.errs<3){obj.bootstrap(obj.user_obj);}}else{obj.errs=0;}};la.onChange(la,{action:"init"});};var CONFMAN_SERNO=1;$.verto.conf=function(verto,params){var conf=this;conf.params=$.extend({dialog:null,hasVid:false,laData:null,onBroadcast:null,onLaChange:null,onLaRow:null},params);conf.verto=verto;conf.serno=CONFMAN_SERNO++;createMainModeratorMethods();verto.subscribe(conf.params.laData.modChannel,{handler:function(v,e){if(conf.params.onBroadcast){conf.params.onBroadcast(verto,conf,e.data);}}});verto.subscribe(conf.params.laData.infoChannel,{handler:function(v,e){if(typeof(conf.params.infoCallback)==="function"){conf.params.infoCallback(v,e);}}});verto.subscribe(conf.params.laData.chatChannel,{handler:function(v,e){if(typeof(conf.params.chatCallback)==="function"){conf.params.chatCallback(v,e);}}});};$.verto.conf.prototype.modCommand=function(cmd,id,value){var conf=this;conf.verto.rpcClient.call("verto.broadcast",{"eventChannel":conf.params.laData.modChannel,"data":{"application":"conf-control","command":cmd,"id":id,"value":value}});};$.verto.conf.prototype.destroy=function(){var conf=this;conf.destroyed=true;conf.params.onBroadcast(conf.verto,conf,'destroy');if(conf.params.laData.modChannel){conf.verto.unsubscribe(conf.params.laData.modChannel);}
+if(conf.params.laData.chatChannel){conf.verto.unsubscribe(conf.params.laData.chatChannel);}
+if(conf.params.laData.infoChannel){conf.verto.unsubscribe(conf.params.laData.infoChannel);}};function createMainModeratorMethods(){$.verto.conf.prototype.listVideoLayouts=function(){this.modCommand("list-videoLayouts",null,null);};$.verto.conf.prototype.play=function(file){this.modCommand("play",null,file);};$.verto.conf.prototype.stop=function(){this.modCommand("stop",null,"all");};$.verto.conf.prototype.deaf=function(memberID){this.modCommand("deaf",parseInt(memberID));};$.verto.conf.prototype.undeaf=function(memberID){this.modCommand("undeaf",parseInt(memberID));};$.verto.conf.prototype.record=function(file){this.modCommand("recording",null,["start",file]);};$.verto.conf.prototype.stopRecord=function(){this.modCommand("recording",null,["stop","all"]);};$.verto.conf.prototype.snapshot=function(file){if(!this.params.hasVid){throw'Conference has no video';}
+this.modCommand("vid-write-png",null,file);};$.verto.conf.prototype.setVideoLayout=function(layout,canvasID){if(!this.params.hasVid){throw'Conference has no video';}
+if(canvasID){this.modCommand("vid-layout",null,[layout,canvasID]);}else{this.modCommand("vid-layout",null,layout);}};$.verto.conf.prototype.kick=function(memberID){this.modCommand("kick",parseInt(memberID));};$.verto.conf.prototype.muteMic=function(memberID){this.modCommand("tmute",parseInt(memberID));};$.verto.conf.prototype.muteVideo=function(memberID){if(!this.params.hasVid){throw'Conference has no video';}
+this.modCommand("tvmute",parseInt(memberID));};$.verto.conf.prototype.presenter=function(memberID){if(!this.params.hasVid){throw'Conference has no video';}
+this.modCommand("vid-res-id",parseInt(memberID),"presenter");};$.verto.conf.prototype.videoFloor=function(memberID){if(!this.params.hasVid){throw'Conference has no video';}
+this.modCommand("vid-floor",parseInt(memberID),"force");};$.verto.conf.prototype.banner=function(memberID,text){if(!this.params.hasVid){throw'Conference has no video';}
+this.modCommand("vid-banner",parseInt(memberID),escape(text));};$.verto.conf.prototype.volumeDown=function(memberID){this.modCommand("volume_out",parseInt(memberID),"down");};$.verto.conf.prototype.volumeUp=function(memberID){this.modCommand("volume_out",parseInt(memberID),"up");};$.verto.conf.prototype.gainDown=function(memberID){this.modCommand("volume_in",parseInt(memberID),"down");};$.verto.conf.prototype.gainUp=function(memberID){this.modCommand("volume_in",parseInt(memberID),"up");};$.verto.conf.prototype.transfer=function(memberID,exten){this.modCommand("transfer",parseInt(memberID),exten);};$.verto.conf.prototype.sendChat=function(message,type){var conf=this;conf.verto.rpcClient.call("verto.broadcast",{"eventChannel":conf.params.laData.chatChannel,"data":{"action":"send","message":message,"type":type}});};}
+$.verto.modfuncs={};$.verto.confMan=function(verto,params){var confMan=this;confMan.params=$.extend({tableID:null,statusID:null,mainModID:null,dialog:null,hasVid:false,laData:null,onBroadcast:null,onLaChange:null,onLaRow:null},params);confMan.verto=verto;confMan.serno=CONFMAN_SERNO++;confMan.canvasCount=confMan.params.laData.canvasCount;function genMainMod(jq){var play_id="play_"+confMan.serno;var stop_id="stop_"+confMan.serno;var recording_id="recording_"+confMan.serno;var snapshot_id="snapshot_"+confMan.serno;var rec_stop_id="recording_stop"+confMan.serno;var div_id="confman_"+confMan.serno;var html=" "+"Play "+"Stop "+"Record "+"Record Stop "+
+(confMan.params.hasVid?"PNG Snapshot ":"")+"
";jq.html(html);$.verto.modfuncs.change_video_layout=function(id,canvas_id){var val=$("#"+id+" option:selected").text();if(val!=="none"){confMan.modCommand("vid-layout",null,[val,canvas_id]);}};if(confMan.params.hasVid){for(var j=0;j "+"Video Layout Canvas "+(j+1)+" "+" ";jq.append(vlhtml);}
+$("#"+snapshot_id).click(function(){var file=prompt("Please enter file name","");if(file){confMan.modCommand("vid-write-png",null,file);}});}
+$("#"+play_id).click(function(){var file=prompt("Please enter file name","");if(file){confMan.modCommand("play",null,file);}});$("#"+stop_id).click(function(){confMan.modCommand("stop",null,"all");});$("#"+recording_id).click(function(){var file=prompt("Please enter file name","");if(file){confMan.modCommand("recording",null,["start",file]);}});$("#"+rec_stop_id).click(function(){confMan.modCommand("recording",null,["stop","all"]);});}
+function genControls(jq,rowid){var x=parseInt(rowid);var kick_id="kick_"+x;var canvas_in_next_id="canvas_in_next_"+x;var canvas_in_prev_id="canvas_in_prev_"+x;var canvas_out_next_id="canvas_out_next_"+x;var canvas_out_prev_id="canvas_out_prev_"+x;var canvas_in_set_id="canvas_in_set_"+x;var canvas_out_set_id="canvas_out_set_"+x;var layer_set_id="layer_set_"+x;var layer_next_id="layer_next_"+x;var layer_prev_id="layer_prev_"+x;var tmute_id="tmute_"+x;var tvmute_id="tvmute_"+x;var vbanner_id="vbanner_"+x;var tvpresenter_id="tvpresenter_"+x;var tvfloor_id="tvfloor_"+x;var box_id="box_"+x;var gainup_id="gain_in_up"+x;var gaindn_id="gain_in_dn"+x;var volup_id="vol_in_up"+x;var voldn_id="vol_in_dn"+x;var transfer_id="transfer"+x;var html="";html+="General Controls
";html+="Kick "+"Mute "+"Gain - "+"Gain + "+"Vol - "+"Vol + "+"Transfer ";if(confMan.params.hasVid){html+="Video Controls ";html+="VMute "+"Presenter "+"Vid Floor "+"Banner ";if(confMan.canvasCount>1){html+="Canvas Controls "+"Set Input Canvas "+"Prev Input Canvas "+"Next Input Canvas "+" "+"Set Watching Canvas "+"Prev Watching Canvas "+"Next Watching Canvas ";}
+html+=" "+"Set Layer "+"Prev Layer "+"Next Layer "+"";}
+jq.html(html);if(!jq.data("mouse")){$("#"+box_id).hide();}
+jq.mouseover(function(e){jq.data({"mouse":true});$("#"+box_id).show();});jq.mouseout(function(e){jq.data({"mouse":false});$("#"+box_id).hide();});$("#"+transfer_id).click(function(){var xten=prompt("Enter Extension");if(xten){confMan.modCommand("transfer",x,xten);}});$("#"+kick_id).click(function(){confMan.modCommand("kick",x);});$("#"+layer_set_id).click(function(){var cid=prompt("Please enter layer ID","");if(cid){confMan.modCommand("vid-layer",x,cid);}});$("#"+layer_next_id).click(function(){confMan.modCommand("vid-layer",x,"next");});$("#"+layer_prev_id).click(function(){confMan.modCommand("vid-layer",x,"prev");});$("#"+canvas_in_set_id).click(function(){var cid=prompt("Please enter canvas ID","");if(cid){confMan.modCommand("vid-canvas",x,cid);}});$("#"+canvas_out_set_id).click(function(){var cid=prompt("Please enter canvas ID","");if(cid){confMan.modCommand("vid-watching-canvas",x,cid);}});$("#"+canvas_in_next_id).click(function(){confMan.modCommand("vid-canvas",x,"next");});$("#"+canvas_in_prev_id).click(function(){confMan.modCommand("vid-canvas",x,"prev");});$("#"+canvas_out_next_id).click(function(){confMan.modCommand("vid-watching-canvas",x,"next");});$("#"+canvas_out_prev_id).click(function(){confMan.modCommand("vid-watching-canvas",x,"prev");});$("#"+tmute_id).click(function(){confMan.modCommand("tmute",x);});if(confMan.params.hasVid){$("#"+tvmute_id).click(function(){confMan.modCommand("tvmute",x);});$("#"+tvpresenter_id).click(function(){confMan.modCommand("vid-res-id",x,"presenter");});$("#"+tvfloor_id).click(function(){confMan.modCommand("vid-floor",x,"force");});$("#"+vbanner_id).click(function(){var text=prompt("Please enter text","");if(text){confMan.modCommand("vid-banner",x,escape(text));}});}
+$("#"+gainup_id).click(function(){confMan.modCommand("volume_in",x,"up");});$("#"+gaindn_id).click(function(){confMan.modCommand("volume_in",x,"down");});$("#"+volup_id).click(function(){confMan.modCommand("volume_out",x,"up");});$("#"+voldn_id).click(function(){confMan.modCommand("volume_out",x,"down");});return html;}
+var atitle="";var awidth=0;verto.subscribe(confMan.params.laData.infoChannel,{handler:function(v,e){if(typeof(confMan.params.infoCallback)==="function"){confMan.params.infoCallback(v,e);}}});verto.subscribe(confMan.params.laData.chatChannel,{handler:function(v,e){if(typeof(confMan.params.chatCallback)==="function"){confMan.params.chatCallback(v,e);}}});if(confMan.params.laData.role==="moderator"){atitle="Action";awidth=600;if(confMan.params.mainModID){genMainMod($(confMan.params.mainModID));$(confMan.params.displayID).html("Moderator Controls Ready ");}else{$(confMan.params.mainModID).html("");}
+verto.subscribe(confMan.params.laData.modChannel,{handler:function(v,e){if(confMan.params.onBroadcast){confMan.params.onBroadcast(verto,confMan,e.data);}
+if(e.data["conf-command"]==="list-videoLayouts"){for(var j=0;jb)?1:-1));});for(var i in options){$(vlselect_id).append(new Option(options[i],options[i]));x++;}}
+if(x){$(vlselect_id).selectmenu('refresh',true);}else{$(vlayout_id).hide();}}}else{if(!confMan.destroyed&&confMan.params.displayID){$(confMan.params.displayID).html(e.data.response+" ");if(confMan.lastTimeout){clearTimeout(confMan.lastTimeout);confMan.lastTimeout=0;}
+confMan.lastTimeout=setTimeout(function(){$(confMan.params.displayID).html(confMan.destroyed?"":"Moderator Controls Ready ");},4000);}}}});if(confMan.params.hasVid){confMan.modCommand("list-videoLayouts",null,null);}}
+var row_callback=null;if(confMan.params.laData.role==="moderator"){row_callback=function(nRow,aData,iDisplayIndex,iDisplayIndexFull){if(!aData[5]){var $row=$('td:eq(5)',nRow);genControls($row,aData);if(confMan.params.onLaRow){confMan.params.onLaRow(verto,confMan,$row,aData);}}};}
+confMan.lt=new $.verto.liveTable(verto,confMan.params.laData.laChannel,confMan.params.laData.laName,$(confMan.params.tableID),{subParams:{callID:confMan.params.dialog?confMan.params.dialog.callID:null},"onChange":function(obj,args){$(confMan.params.statusID).text("Conference Members: "+" ("+obj.arrayLen()+" Total)");if(confMan.params.onLaChange){confMan.params.onLaChange(verto,confMan,$.verto.enum.confEvent.laChange,obj,args);}},"aaData":[],"aoColumns":[{"sTitle":"ID","sWidth":"50"},{"sTitle":"Number","sWidth":"250"},{"sTitle":"Name","sWidth":"250"},{"sTitle":"Codec","sWidth":"100"},{"sTitle":"Status","sWidth":confMan.params.hasVid?"200px":"150px"},{"sTitle":atitle,"sWidth":awidth,}],"bAutoWidth":true,"bDestroy":true,"bSort":false,"bInfo":false,"bFilter":false,"bLengthChange":false,"bPaginate":false,"iDisplayLength":1400,"oLanguage":{"sEmptyTable":"The Conference is Empty....."},"fnRowCallback":row_callback});};$.verto.confMan.prototype.modCommand=function(cmd,id,value){var confMan=this;confMan.verto.rpcClient.call("verto.broadcast",{"eventChannel":confMan.params.laData.modChannel,"data":{"application":"conf-control","command":cmd,"id":id,"value":value}});};$.verto.confMan.prototype.sendChat=function(message,type){var confMan=this;confMan.verto.rpcClient.call("verto.broadcast",{"eventChannel":confMan.params.laData.chatChannel,"data":{"action":"send","message":message,"type":type}});};$.verto.confMan.prototype.destroy=function(){var confMan=this;confMan.destroyed=true;if(confMan.lt){confMan.lt.destroy();}
+if(confMan.params.laData.chatChannel){confMan.verto.unsubscribe(confMan.params.laData.chatChannel);}
+if(confMan.params.laData.modChannel){confMan.verto.unsubscribe(confMan.params.laData.modChannel);}
+if(confMan.params.mainModID){$(confMan.params.mainModID).html("");}};$.verto.dialog=function(direction,verto,params){var dialog=this;dialog.params=$.extend({useVideo:verto.options.useVideo,useStereo:verto.options.useStereo,screenShare:false,useCamera:false,useMic:verto.options.deviceParams.useMic,useMicLabel:verto.options.deviceParams.useMicLabel,useSpeak:verto.options.deviceParams.useSpeak,tag:verto.options.tag,localTag:verto.options.localTag,login:verto.options.login,videoParams:verto.options.videoParams,useStream:verto.options.useStream,},params);if(!dialog.params.screenShare){dialog.params.useCamera=verto.options.deviceParams.useCamera;dialog.params.useCameraLabel=verto.options.deviceParams.useCameraLabel;}
+dialog.verto=verto;dialog.direction=direction;dialog.lastState=null;dialog.state=dialog.lastState=$.verto.enum.state.new;dialog.callbacks=verto.callbacks;dialog.answered=false;dialog.attach=params.attach||false;dialog.screenShare=params.screenShare||false;dialog.useCamera=dialog.params.useCamera;dialog.useCameraLabel=dialog.params.useCameraLabel;dialog.useMic=dialog.params.useMic;dialog.useMicLabel=dialog.params.useMicLabel;dialog.useSpeak=dialog.params.useSpeak;if(dialog.params.callID){dialog.callID=dialog.params.callID;}else{dialog.callID=dialog.params.callID=generateGUID();}
+if(typeof(dialog.params.tag)==="function"){dialog.params.tag=dialog.params.tag();}
+if(dialog.params.tag){dialog.audioStream=document.getElementById(dialog.params.tag);if(dialog.params.useVideo){dialog.videoStream=dialog.audioStream;}}
+if(dialog.params.localTag){dialog.localVideo=document.getElementById(dialog.params.localTag);}
+dialog.verto.dialogs[dialog.callID]=dialog;var RTCcallbacks={};if(dialog.direction==$.verto.enum.direction.inbound){if(dialog.params.display_direction==="outbound"){dialog.params.remote_caller_id_name=dialog.params.caller_id_name;dialog.params.remote_caller_id_number=dialog.params.caller_id_number;}else{dialog.params.remote_caller_id_name=dialog.params.callee_id_name;dialog.params.remote_caller_id_number=dialog.params.callee_id_number;}
+if(!dialog.params.remote_caller_id_name){dialog.params.remote_caller_id_name="Nobody";}
+if(!dialog.params.remote_caller_id_number){dialog.params.remote_caller_id_number="UNKNOWN";}
+RTCcallbacks.onMessage=function(rtc,msg){console.debug(msg);};RTCcallbacks.onAnswerSDP=function(rtc,sdp){console.error("answer sdp",sdp);};}else{dialog.params.remote_caller_id_name="Outbound Call";dialog.params.remote_caller_id_number=dialog.params.destination_number;}
+RTCcallbacks.onICESDP=function(rtc){console.log("RECV "+rtc.type+" SDP",rtc.mediaData.SDP);if(dialog.state==$.verto.enum.state.requesting||dialog.state==$.verto.enum.state.answering||dialog.state==$.verto.enum.state.active){location.reload();return;}
+if(rtc.type=="offer"){if(dialog.state==$.verto.enum.state.active){dialog.setState($.verto.enum.state.requesting);dialog.sendMethod("verto.attach",{sdp:rtc.mediaData.SDP});}else{dialog.setState($.verto.enum.state.requesting);dialog.sendMethod("verto.invite",{sdp:rtc.mediaData.SDP});}}else{dialog.setState($.verto.enum.state.answering);dialog.sendMethod(dialog.attach?"verto.attach":"verto.answer",{sdp:dialog.rtc.mediaData.SDP});}};RTCcallbacks.onICE=function(rtc){if(rtc.type=="offer"){console.log("offer",rtc.mediaData.candidate);return;}};RTCcallbacks.onStream=function(rtc,stream){if(dialog.callbacks.permissionCallback&&typeof dialog.callbacks.permissionCallback.onGranted==='function'){dialog.callbacks.permissionCallback.onGranted(stream);}
+else if(dialog.verto.options.permissionCallback&&typeof dialog.verto.options.permissionCallback.onGranted==='function'){dialog.verto.options.permissionCallback.onGranted(stream);}
+console.log("stream started");};RTCcallbacks.onRemoteStream=function(rtc,stream){if(typeof dialog.callbacks.onRemoteStream==='function'){dialog.callbacks.onRemoteStream(stream,dialog);}
+console.log("remote stream started");};RTCcallbacks.onError=function(e){if(dialog.callbacks.permissionCallback&&typeof dialog.callbacks.permissionCallback.onDenied==='function'){dialog.callbacks.permissionCallback.onDenied();}
+else if(dialog.verto.options.permissionCallback&&typeof dialog.verto.options.permissionCallback.onDenied==='function'){dialog.verto.options.permissionCallback.onDenied();}
+console.error("ERROR:",e);dialog.hangup({cause:"Device or Permission Error"});};dialog.rtc=new $.FSRTC({callbacks:RTCcallbacks,localVideo:dialog.screenShare?null:dialog.localVideo,useVideo:dialog.params.useVideo?dialog.videoStream:null,useAudio:dialog.audioStream,useStereo:dialog.params.useStereo,videoParams:dialog.params.videoParams,audioParams:verto.options.audioParams,iceServers:verto.options.iceServers,screenShare:dialog.screenShare,useCamera:dialog.useCamera,useCameraLabel:dialog.useCameraLabel,useMic:dialog.useMic,useMicLabel:dialog.useMicLabel,useSpeak:dialog.useSpeak,turnServer:verto.options.turnServer,useStream:dialog.params.useStream});dialog.rtc.verto=dialog.verto;if(dialog.direction==$.verto.enum.direction.inbound){if(dialog.attach){dialog.answer();}else{dialog.ring();}}};$.verto.dialog.prototype.invite=function(){var dialog=this;dialog.rtc.call();};$.verto.dialog.prototype.sendMethod=function(method,obj){var dialog=this;obj.dialogParams={};for(var i in dialog.params){if(i=="sdp"&&method!="verto.invite"&&method!="verto.attach"){continue;}
+if((obj.noDialogParams&&i!="callID")){continue;}
+obj.dialogParams[i]=dialog.params[i];}
+delete obj.noDialogParams;dialog.verto.rpcClient.call(method,obj,function(e){dialog.processReply(method,true,e);},function(e){dialog.processReply(method,false,e);});};function checkStateChange(oldS,newS){if(newS==$.verto.enum.state.purge||$.verto.enum.states[oldS.name][newS.name]){return true;}
+return false;}
+function find_name(id){for(var i in $.verto.audioOutDevices){var source=$.verto.audioOutDevices[i];if(source.id===id){return(source.label);}}
+return id;}
+$.verto.dialog.prototype.setAudioPlaybackDevice=function(sinkId,callback,arg){var dialog=this;var element=dialog.audioStream;if(typeof element.sinkId!=='undefined'){var devname=find_name(sinkId);console.info("Dialog: "+dialog.callID+" Setting speaker:",element,devname);element.setSinkId(sinkId).then(function(){console.log("Dialog: "+dialog.callID+' Success, audio output device attached: '+sinkId);if(callback){callback(true,devname,arg);}}).catch(function(error){var errorMessage=error;if(error.name==='SecurityError'){errorMessage="Dialog: "+dialog.callID+' You need to use HTTPS for selecting audio output '+'device: '+error;}
+if(callback){callback(false,null,arg);}
+console.error(errorMessage);});}else{console.warn("Dialog: "+dialog.callID+' Browser does not support output device selection.');if(callback){callback(false,null,arg);}}}
+$.verto.dialog.prototype.setState=function(state){var dialog=this;if(dialog.state==$.verto.enum.state.ringing){dialog.stopRinging();}
+if(dialog.state==state||!checkStateChange(dialog.state,state)){console.error("Dialog "+dialog.callID+": INVALID state change from "+dialog.state.name+" to "+state.name);dialog.hangup();return false;}
+console.log("Dialog "+dialog.callID+": state change from "+dialog.state.name+" to "+state.name);dialog.lastState=dialog.state;dialog.state=state;if(dialog.callbacks.onDialogState){dialog.callbacks.onDialogState(this);}
+switch(dialog.state){case $.verto.enum.state.early:case $.verto.enum.state.active:var speaker=dialog.useSpeak;console.info("Using Speaker: ",speaker);if(speaker&&speaker!=="any"&&speaker!=="none"){setTimeout(function(){dialog.setAudioPlaybackDevice(speaker);},500);}
+break;case $.verto.enum.state.trying:setTimeout(function(){if(dialog.state==$.verto.enum.state.trying){dialog.setState($.verto.enum.state.hangup);}},30000);break;case $.verto.enum.state.purge:dialog.setState($.verto.enum.state.destroy);break;case $.verto.enum.state.hangup:if(dialog.lastState.val>$.verto.enum.state.requesting.val&&dialog.lastState.val<$.verto.enum.state.hangup.val){dialog.sendMethod("verto.bye",{});}
+dialog.setState($.verto.enum.state.destroy);break;case $.verto.enum.state.destroy:if(typeof(dialog.verto.options.tag)==="function"){$('#'+dialog.params.tag).remove();}
+delete dialog.verto.dialogs[dialog.callID];if(dialog.params.screenShare){dialog.rtc.stopPeer();}else{dialog.rtc.stop();}
+break;}
+return true;};$.verto.dialog.prototype.processReply=function(method,success,e){var dialog=this;switch(method){case"verto.answer":case"verto.attach":if(success){dialog.setState($.verto.enum.state.active);}else{dialog.hangup();}
+break;case"verto.invite":if(success){dialog.setState($.verto.enum.state.trying);}else{dialog.setState($.verto.enum.state.destroy);}
+break;case"verto.bye":dialog.hangup();break;case"verto.modify":if(e.holdState){if(e.holdState=="held"){if(dialog.state!=$.verto.enum.state.held){dialog.setState($.verto.enum.state.held);}}else if(e.holdState=="active"){if(dialog.state!=$.verto.enum.state.active){dialog.setState($.verto.enum.state.active);}}}
+if(success){}
+break;default:break;}};$.verto.dialog.prototype.hangup=function(params){var dialog=this;if(params){if(params.causeCode){dialog.causeCode=params.causeCode;}
+if(params.cause){dialog.cause=params.cause;}}
+if(!dialog.cause&&!dialog.causeCode){dialog.cause="NORMAL_CLEARING";}
+if(dialog.state.val>=$.verto.enum.state.new.val&&dialog.state.val<$.verto.enum.state.hangup.val){dialog.setState($.verto.enum.state.hangup);}else if(dialog.state.val<$.verto.enum.state.destroy){dialog.setState($.verto.enum.state.destroy);}};$.verto.dialog.prototype.stopRinging=function(){var dialog=this;if(dialog.verto.ringer){dialog.verto.ringer.stop();}};$.verto.dialog.prototype.indicateRing=function(){var dialog=this;if(dialog.verto.ringer){dialog.verto.ringer.attr("src",dialog.verto.options.ringFile)[0].play();setTimeout(function(){dialog.stopRinging();if(dialog.state==$.verto.enum.state.ringing){dialog.indicateRing();}},dialog.verto.options.ringSleep);}};$.verto.dialog.prototype.ring=function(){var dialog=this;dialog.setState($.verto.enum.state.ringing);dialog.indicateRing();};$.verto.dialog.prototype.useVideo=function(on){var dialog=this;dialog.params.useVideo=on;if(on){dialog.videoStream=dialog.audioStream;}else{dialog.videoStream=null;}
+dialog.rtc.useVideo(dialog.videoStream,dialog.localVideo);};$.verto.dialog.prototype.setMute=function(what){var dialog=this;return dialog.rtc.setMute(what);};$.verto.dialog.prototype.getMute=function(){var dialog=this;return dialog.rtc.getMute();};$.verto.dialog.prototype.setVideoMute=function(what){var dialog=this;return dialog.rtc.setVideoMute(what);};$.verto.dialog.prototype.getVideoMute=function(){var dialog=this;return dialog.rtc.getVideoMute();};$.verto.dialog.prototype.useStereo=function(on){var dialog=this;dialog.params.useStereo=on;dialog.rtc.useStereo(on);};$.verto.dialog.prototype.dtmf=function(digits){var dialog=this;if(digits){dialog.sendMethod("verto.info",{dtmf:digits});}};$.verto.dialog.prototype.rtt=function(obj){var dialog=this;var pobj={};if(!obj){return false;}
+pobj.code=obj.code;pobj.chars=obj.chars;if(pobj.chars||pobj.code){dialog.sendMethod("verto.info",{txt:obj,noDialogParams:true});}};$.verto.dialog.prototype.transfer=function(dest,params){var dialog=this;if(dest){dialog.sendMethod("verto.modify",{action:"transfer",destination:dest,params:params});}};$.verto.dialog.prototype.replace=function(replaceCallID,params){var dialog=this;if(replaceCallID){dialog.sendMethod("verto.modify",{action:"replace",replaceCallID:replaceCallID,params:params});}};$.verto.dialog.prototype.hold=function(params){var dialog=this;dialog.sendMethod("verto.modify",{action:"hold",params:params});};$.verto.dialog.prototype.unhold=function(params){var dialog=this;dialog.sendMethod("verto.modify",{action:"unhold",params:params});};$.verto.dialog.prototype.toggleHold=function(params){var dialog=this;dialog.sendMethod("verto.modify",{action:"toggleHold",params:params});};$.verto.dialog.prototype.message=function(msg){var dialog=this;var err=0;msg.from=dialog.params.login;if(!msg.to){console.error("Missing To");err++;}
+if(!msg.body){console.error("Missing Body");err++;}
+if(err){return false;}
+dialog.sendMethod("verto.info",{msg:msg});return true;};$.verto.dialog.prototype.answer=function(params){var dialog=this;if(!dialog.answered){if(!params){params={};}
+params.sdp=dialog.params.sdp;if(params){if(params.useVideo){dialog.useVideo(true);}
+dialog.params.callee_id_name=params.callee_id_name;dialog.params.callee_id_number=params.callee_id_number;if(params.useCamera){dialog.useCamera=params.useCamera;dialog.useCameraLabel=params.useCameraLabel;}
+if(params.useMic){dialog.useMic=params.useMic;dialog.useMic=params.useMicLabel;}
+if(params.useSpeak){dialog.useSpeak=params.useSpeak;}}
+dialog.rtc.createAnswer(params);dialog.answered=true;}};$.verto.dialog.prototype.handleAnswer=function(params){var dialog=this;dialog.gotAnswer=true;if(dialog.state.val>=$.verto.enum.state.active.val){return;}
+if(dialog.state.val>=$.verto.enum.state.early.val){dialog.setState($.verto.enum.state.active);}else{if(dialog.gotEarly){console.log("Dialog "+dialog.callID+" Got answer while still establishing early media, delaying...");}else{console.log("Dialog "+dialog.callID+" Answering Channel");dialog.rtc.answer(params.sdp,function(){dialog.setState($.verto.enum.state.active);},function(e){console.error(e);dialog.hangup();});console.log("Dialog "+dialog.callID+"ANSWER SDP",params.sdp);}}};$.verto.dialog.prototype.cidString=function(enc){var dialog=this;var party=dialog.params.remote_caller_id_name+(enc?" <":" <")+dialog.params.remote_caller_id_number+(enc?">":">");return party;};$.verto.dialog.prototype.sendMessage=function(msg,params){var dialog=this;if(dialog.callbacks.onMessage){dialog.callbacks.onMessage(dialog.verto,dialog,msg,params);}};$.verto.dialog.prototype.handleInfo=function(params){var dialog=this;dialog.sendMessage($.verto.enum.message.info,params);};$.verto.dialog.prototype.handleDisplay=function(params){var dialog=this;if(params.display_name){dialog.params.remote_caller_id_name=params.display_name;}
+if(params.display_number){dialog.params.remote_caller_id_number=params.display_number;}
+dialog.sendMessage($.verto.enum.message.display,{});};$.verto.dialog.prototype.handleMedia=function(params){var dialog=this;if(dialog.state.val>=$.verto.enum.state.early.val){return;}
+dialog.gotEarly=true;dialog.rtc.answer(params.sdp,function(){console.log("Dialog "+dialog.callID+"Establishing early media");dialog.setState($.verto.enum.state.early);if(dialog.gotAnswer){console.log("Dialog "+dialog.callID+"Answering Channel");dialog.setState($.verto.enum.state.active);}},function(e){console.error(e);dialog.hangup();});console.log("Dialog "+dialog.callID+"EARLY SDP",params.sdp);};$.verto.ENUM=function(s){var i=0,o={};s.split(" ").map(function(x){o[x]={name:x,val:i++};});return Object.freeze(o);};$.verto.enum={};$.verto.enum.states=Object.freeze({new:{requesting:1,recovering:1,ringing:1,destroy:1,answering:1,hangup:1},requesting:{trying:1,hangup:1,active:1},recovering:{answering:1,hangup:1},trying:{active:1,early:1,hangup:1},ringing:{answering:1,hangup:1},answering:{active:1,hangup:1},active:{answering:1,requesting:1,hangup:1,held:1},held:{hangup:1,active:1},early:{hangup:1,active:1},hangup:{destroy:1},destroy:{},purge:{destroy:1}});$.verto.enum.state=$.verto.ENUM("new requesting trying recovering ringing answering early active held hangup destroy purge");$.verto.enum.direction=$.verto.ENUM("inbound outbound");$.verto.enum.message=$.verto.ENUM("display info pvtEvent clientReady");$.verto.enum=Object.freeze($.verto.enum);$.verto.saved=[];$.verto.unloadJobs=[];var unloadEventName='beforeunload';var iOS=['iPad','iPhone','iPod'].indexOf(navigator.platform)>=0;if(iOS){unloadEventName='pagehide';}
+$(window).bind(unloadEventName,function(){for(var f in $.verto.unloadJobs){$.verto.unloadJobs[f]();}
+if($.verto.haltClosure)
+return $.verto.haltClosure();for(var i in $.verto.saved){var verto=$.verto.saved[i];if(verto){verto.purge();verto.logout();}}
+return $.verto.warnOnUnload;});$.verto.videoDevices=[];$.verto.audioInDevices=[];$.verto.audioOutDevices=[];var checkDevices=function(runtime){console.info("enumerating devices");var aud_in=[],aud_out=[],vid=[];var has_video=0,has_audio=0;var Xstream;function gotDevices(deviceInfos){for(var i=0;i!==deviceInfos.length;++i){var deviceInfo=deviceInfos[i];var text="";console.log(deviceInfo);console.log(deviceInfo.kind+": "+deviceInfo.label+" id = "+deviceInfo.deviceId);if(deviceInfo.kind==='audioinput'){text=deviceInfo.label||'microphone '+(aud_in.length+1);aud_in.push({id:deviceInfo.deviceId,kind:"audio_in",label:text});}else if(deviceInfo.kind==='audiooutput'){text=deviceInfo.label||'speaker '+(aud_out.length+1);aud_out.push({id:deviceInfo.deviceId,kind:"audio_out",label:text});}else if(deviceInfo.kind==='videoinput'){text=deviceInfo.label||'camera '+(vid.length+1);vid.push({id:deviceInfo.deviceId,kind:"video",label:text});}else{console.log('Some other kind of source/device: ',deviceInfo);}}
+$.verto.videoDevices=vid;$.verto.audioInDevices=aud_in;$.verto.audioOutDevices=aud_out;console.info("Audio IN Devices",$.verto.audioInDevices);console.info("Audio Out Devices",$.verto.audioOutDevices);console.info("Video Devices",$.verto.videoDevices);if(Xstream){Xstream.getTracks().forEach(function(track){track.stop();});}
+if(runtime){runtime(true);}}
+function handleError(error){console.log('device enumeration error: ',error);if(runtime)runtime(false);}
+function checkTypes(devs){for(var i=0;i!==devs.length;++i){if(devs[i].kind==='audioinput'){has_audio++;}else if(devs[i].kind==='videoinput'){has_video++;}}
+navigator.getUserMedia({audio:(has_audio>0?true:false),video:(has_video>0?true:false)},function(stream){Xstream=stream;navigator.mediaDevices.enumerateDevices().then(gotDevices).catch(handleError);},function(err){console.log("The following error occurred: "+err.name);});}
+navigator.mediaDevices.enumerateDevices().then(checkTypes).catch(handleError);};$.verto.refreshDevices=function(runtime){checkDevices(runtime);}
+$.verto.init=function(obj,runtime){if(!obj){obj={};}
+if(!obj.skipPermCheck&&!obj.skipDeviceCheck){$.FSRTC.checkPerms(function(status){checkDevices(runtime);},true,true);}else if(obj.skipPermCheck&&!obj.skipDeviceCheck){checkDevices(runtime);}else if(!obj.skipPermCheck&&obj.skipDeviceCheck){$.FSRTC.checkPerms(function(status){runtime(status);},true,true);}else{runtime(null);}}
+$.verto.genUUID=function(){return generateGUID();}})(jQuery);(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.adapter=f()}})(function(){var define,module,exports;return(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i0&&arguments[0]!==undefined?arguments[0]:{},window=_ref.window;var options=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{shimChrome:true,shimFirefox:true,shimEdge:true,shimSafari:true};var logging=utils.log;var browserDetails=utils.detectBrowser(window);var adapter={browserDetails:browserDetails,commonShim:commonShim,extractVersion:utils.extractVersion,disableLog:utils.disableLog,disableWarnings:utils.disableWarnings};switch(browserDetails.browser){case'chrome':if(!chromeShim||!chromeShim.shimPeerConnection||!options.shimChrome){logging('Chrome shim is not included in this adapter release.');return adapter;}
+logging('adapter.js shimming chrome.');adapter.browserShim=chromeShim;chromeShim.shimGetUserMedia(window);chromeShim.shimMediaStream(window);chromeShim.shimPeerConnection(window);chromeShim.shimOnTrack(window);chromeShim.shimAddTrackRemoveTrack(window);chromeShim.shimGetSendersWithDtmf(window);chromeShim.shimSenderReceiverGetStats(window);chromeShim.fixNegotiationNeeded(window);commonShim.shimRTCIceCandidate(window);commonShim.shimConnectionState(window);commonShim.shimMaxMessageSize(window);commonShim.shimSendThrowTypeError(window);commonShim.removeAllowExtmapMixed(window);break;case'firefox':if(!firefoxShim||!firefoxShim.shimPeerConnection||!options.shimFirefox){logging('Firefox shim is not included in this adapter release.');return adapter;}
+logging('adapter.js shimming firefox.');adapter.browserShim=firefoxShim;firefoxShim.shimGetUserMedia(window);firefoxShim.shimPeerConnection(window);firefoxShim.shimOnTrack(window);firefoxShim.shimRemoveStream(window);firefoxShim.shimSenderGetStats(window);firefoxShim.shimReceiverGetStats(window);firefoxShim.shimRTCDataChannel(window);commonShim.shimRTCIceCandidate(window);commonShim.shimConnectionState(window);commonShim.shimMaxMessageSize(window);commonShim.shimSendThrowTypeError(window);break;case'edge':if(!edgeShim||!edgeShim.shimPeerConnection||!options.shimEdge){logging('MS edge shim is not included in this adapter release.');return adapter;}
+logging('adapter.js shimming edge.');adapter.browserShim=edgeShim;edgeShim.shimGetUserMedia(window);edgeShim.shimGetDisplayMedia(window);edgeShim.shimPeerConnection(window);edgeShim.shimReplaceTrack(window);commonShim.shimMaxMessageSize(window);commonShim.shimSendThrowTypeError(window);break;case'safari':if(!safariShim||!options.shimSafari){logging('Safari shim is not included in this adapter release.');return adapter;}
+logging('adapter.js shimming safari.');adapter.browserShim=safariShim;safariShim.shimRTCIceServerUrls(window);safariShim.shimCreateOfferLegacy(window);safariShim.shimCallbacksAPI(window);safariShim.shimLocalStreamsAPI(window);safariShim.shimRemoteStreamsAPI(window);safariShim.shimTrackEventTransceiver(window);safariShim.shimGetUserMedia(window);commonShim.shimRTCIceCandidate(window);commonShim.shimMaxMessageSize(window);commonShim.shimSendThrowTypeError(window);commonShim.removeAllowExtmapMixed(window);break;default:logging('Unsupported browser!');break;}
+return adapter;}},{"./chrome/chrome_shim":3,"./common_shim":6,"./edge/edge_shim":7,"./firefox/firefox_shim":11,"./safari/safari_shim":14,"./utils":15}],3:[function(require,module,exports){'use strict';Object.defineProperty(exports,"__esModule",{value:true});exports.shimGetDisplayMedia=exports.shimGetUserMedia=undefined;var _typeof=typeof Symbol==="function"&&typeof Symbol.iterator==="symbol"?function(obj){return typeof obj;}:function(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj;};var _getusermedia=require('./getusermedia');Object.defineProperty(exports,'shimGetUserMedia',{enumerable:true,get:function get(){return _getusermedia.shimGetUserMedia;}});var _getdisplaymedia=require('./getdisplaymedia');Object.defineProperty(exports,'shimGetDisplayMedia',{enumerable:true,get:function get(){return _getdisplaymedia.shimGetDisplayMedia;}});exports.shimMediaStream=shimMediaStream;exports.shimOnTrack=shimOnTrack;exports.shimGetSendersWithDtmf=shimGetSendersWithDtmf;exports.shimSenderReceiverGetStats=shimSenderReceiverGetStats;exports.shimAddTrackRemoveTrackWithNative=shimAddTrackRemoveTrackWithNative;exports.shimAddTrackRemoveTrack=shimAddTrackRemoveTrack;exports.shimPeerConnection=shimPeerConnection;exports.fixNegotiationNeeded=fixNegotiationNeeded;var _utils=require('../utils.js');var utils=_interopRequireWildcard(_utils);function _interopRequireWildcard(obj){if(obj&&obj.__esModule){return obj;}else{var newObj={};if(obj!=null){for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key))newObj[key]=obj[key];}}newObj.default=obj;return newObj;}}
+function walkStats(stats,base,resultSet){if(!base||resultSet.has(base.id)){return;}
+resultSet.set(base.id,base);Object.keys(base).forEach(function(name){if(name.endsWith('Id')){walkStats(stats,stats.get(base[name]),resultSet);}else if(name.endsWith('Ids')){base[name].forEach(function(id){walkStats(stats,stats.get(id),resultSet);});}});}
+function filterStats(result,track,outbound){var streamStatsType=outbound?'outbound-rtp':'inbound-rtp';var filteredResult=new Map();if(track===null){return filteredResult;}
+var trackStats=[];result.forEach(function(value){if(value.type==='track'&&value.trackIdentifier===track.id){trackStats.push(value);}});trackStats.forEach(function(trackStat){result.forEach(function(stats){if(stats.type===streamStatsType&&stats.trackId===trackStat.id){walkStats(result,stats,filteredResult);}});});return filteredResult;}
+function shimMediaStream(window){window.MediaStream=window.MediaStream||window.webkitMediaStream;}
+function shimOnTrack(window){if((typeof window==='undefined'?'undefined':_typeof(window))==='object'&&window.RTCPeerConnection&&!('ontrack'in window.RTCPeerConnection.prototype)){Object.defineProperty(window.RTCPeerConnection.prototype,'ontrack',{get:function get(){return this._ontrack;},set:function set(f){if(this._ontrack){this.removeEventListener('track',this._ontrack);}
+this.addEventListener('track',this._ontrack=f);},enumerable:true,configurable:true});var origSetRemoteDescription=window.RTCPeerConnection.prototype.setRemoteDescription;window.RTCPeerConnection.prototype.setRemoteDescription=function(){var _this=this;if(!this._ontrackpoly){this._ontrackpoly=function(e){e.stream.addEventListener('addtrack',function(te){var receiver=void 0;if(window.RTCPeerConnection.prototype.getReceivers){receiver=_this.getReceivers().find(function(r){return r.track&&r.track.id===te.track.id;});}else{receiver={track:te.track};}
+var event=new Event('track');event.track=te.track;event.receiver=receiver;event.transceiver={receiver:receiver};event.streams=[e.stream];_this.dispatchEvent(event);});e.stream.getTracks().forEach(function(track){var receiver=void 0;if(window.RTCPeerConnection.prototype.getReceivers){receiver=_this.getReceivers().find(function(r){return r.track&&r.track.id===track.id;});}else{receiver={track:track};}
+var event=new Event('track');event.track=track;event.receiver=receiver;event.transceiver={receiver:receiver};event.streams=[e.stream];_this.dispatchEvent(event);});};this.addEventListener('addstream',this._ontrackpoly);}
+return origSetRemoteDescription.apply(this,arguments);};}else{utils.wrapPeerConnectionEvent(window,'track',function(e){if(!e.transceiver){Object.defineProperty(e,'transceiver',{value:{receiver:e.receiver}});}
+return e;});}}
+function shimGetSendersWithDtmf(window){if((typeof window==='undefined'?'undefined':_typeof(window))==='object'&&window.RTCPeerConnection&&!('getSenders'in window.RTCPeerConnection.prototype)&&'createDTMFSender'in window.RTCPeerConnection.prototype){var shimSenderWithDtmf=function shimSenderWithDtmf(pc,track){return{track:track,get dtmf(){if(this._dtmf===undefined){if(track.kind==='audio'){this._dtmf=pc.createDTMFSender(track);}else{this._dtmf=null;}}
+return this._dtmf;},_pc:pc};};if(!window.RTCPeerConnection.prototype.getSenders){window.RTCPeerConnection.prototype.getSenders=function(){this._senders=this._senders||[];return this._senders.slice();};var origAddTrack=window.RTCPeerConnection.prototype.addTrack;window.RTCPeerConnection.prototype.addTrack=function(track,stream){var sender=origAddTrack.apply(this,arguments);if(!sender){sender=shimSenderWithDtmf(this,track);this._senders.push(sender);}
+return sender;};var origRemoveTrack=window.RTCPeerConnection.prototype.removeTrack;window.RTCPeerConnection.prototype.removeTrack=function(sender){origRemoveTrack.apply(this,arguments);var idx=this._senders.indexOf(sender);if(idx!==-1){this._senders.splice(idx,1);}};}
+var origAddStream=window.RTCPeerConnection.prototype.addStream;window.RTCPeerConnection.prototype.addStream=function(stream){var _this2=this;this._senders=this._senders||[];origAddStream.apply(this,[stream]);stream.getTracks().forEach(function(track){_this2._senders.push(shimSenderWithDtmf(_this2,track));});};var origRemoveStream=window.RTCPeerConnection.prototype.removeStream;window.RTCPeerConnection.prototype.removeStream=function(stream){var _this3=this;this._senders=this._senders||[];origRemoveStream.apply(this,[stream]);stream.getTracks().forEach(function(track){var sender=_this3._senders.find(function(s){return s.track===track;});if(sender){_this3._senders.splice(_this3._senders.indexOf(sender),1);}});};}else if((typeof window==='undefined'?'undefined':_typeof(window))==='object'&&window.RTCPeerConnection&&'getSenders'in window.RTCPeerConnection.prototype&&'createDTMFSender'in window.RTCPeerConnection.prototype&&window.RTCRtpSender&&!('dtmf'in window.RTCRtpSender.prototype)){var origGetSenders=window.RTCPeerConnection.prototype.getSenders;window.RTCPeerConnection.prototype.getSenders=function(){var _this4=this;var senders=origGetSenders.apply(this,[]);senders.forEach(function(sender){return sender._pc=_this4;});return senders;};Object.defineProperty(window.RTCRtpSender.prototype,'dtmf',{get:function get(){if(this._dtmf===undefined){if(this.track.kind==='audio'){this._dtmf=this._pc.createDTMFSender(this.track);}else{this._dtmf=null;}}
+return this._dtmf;}});}}
+function shimSenderReceiverGetStats(window){if(!((typeof window==='undefined'?'undefined':_typeof(window))==='object'&&window.RTCPeerConnection&&window.RTCRtpSender&&window.RTCRtpReceiver)){return;}
+if(!('getStats'in window.RTCRtpSender.prototype)){var origGetSenders=window.RTCPeerConnection.prototype.getSenders;if(origGetSenders){window.RTCPeerConnection.prototype.getSenders=function(){var _this5=this;var senders=origGetSenders.apply(this,[]);senders.forEach(function(sender){return sender._pc=_this5;});return senders;};}
+var origAddTrack=window.RTCPeerConnection.prototype.addTrack;if(origAddTrack){window.RTCPeerConnection.prototype.addTrack=function(){var sender=origAddTrack.apply(this,arguments);sender._pc=this;return sender;};}
+window.RTCRtpSender.prototype.getStats=function(){var sender=this;return this._pc.getStats().then(function(result){return(filterStats(result,sender.track,true));});};}
+if(!('getStats'in window.RTCRtpReceiver.prototype)){var origGetReceivers=window.RTCPeerConnection.prototype.getReceivers;if(origGetReceivers){window.RTCPeerConnection.prototype.getReceivers=function(){var _this6=this;var receivers=origGetReceivers.apply(this,[]);receivers.forEach(function(receiver){return receiver._pc=_this6;});return receivers;};}
+utils.wrapPeerConnectionEvent(window,'track',function(e){e.receiver._pc=e.srcElement;return e;});window.RTCRtpReceiver.prototype.getStats=function(){var receiver=this;return this._pc.getStats().then(function(result){return filterStats(result,receiver.track,false);});};}
+if(!('getStats'in window.RTCRtpSender.prototype&&'getStats'in window.RTCRtpReceiver.prototype)){return;}
+var origGetStats=window.RTCPeerConnection.prototype.getStats;window.RTCPeerConnection.prototype.getStats=function(){if(arguments.length>0&&arguments[0]instanceof window.MediaStreamTrack){var track=arguments[0];var sender=void 0;var receiver=void 0;var err=void 0;this.getSenders().forEach(function(s){if(s.track===track){if(sender){err=true;}else{sender=s;}}});this.getReceivers().forEach(function(r){if(r.track===track){if(receiver){err=true;}else{receiver=r;}}
+return r.track===track;});if(err||sender&&receiver){return Promise.reject(new DOMException('There are more than one sender or receiver for the track.','InvalidAccessError'));}else if(sender){return sender.getStats();}else if(receiver){return receiver.getStats();}
+return Promise.reject(new DOMException('There is no sender or receiver for the track.','InvalidAccessError'));}
+return origGetStats.apply(this,arguments);};}
+function shimAddTrackRemoveTrackWithNative(window){window.RTCPeerConnection.prototype.getLocalStreams=function(){var _this7=this;this._shimmedLocalStreams=this._shimmedLocalStreams||{};return Object.keys(this._shimmedLocalStreams).map(function(streamId){return _this7._shimmedLocalStreams[streamId][0];});};var origAddTrack=window.RTCPeerConnection.prototype.addTrack;window.RTCPeerConnection.prototype.addTrack=function(track,stream){if(!stream){return origAddTrack.apply(this,arguments);}
+this._shimmedLocalStreams=this._shimmedLocalStreams||{};var sender=origAddTrack.apply(this,arguments);if(!this._shimmedLocalStreams[stream.id]){this._shimmedLocalStreams[stream.id]=[stream,sender];}else if(this._shimmedLocalStreams[stream.id].indexOf(sender)===-1){this._shimmedLocalStreams[stream.id].push(sender);}
+return sender;};var origAddStream=window.RTCPeerConnection.prototype.addStream;window.RTCPeerConnection.prototype.addStream=function(stream){var _this8=this;this._shimmedLocalStreams=this._shimmedLocalStreams||{};stream.getTracks().forEach(function(track){var alreadyExists=_this8.getSenders().find(function(s){return s.track===track;});if(alreadyExists){throw new DOMException('Track already exists.','InvalidAccessError');}});var existingSenders=this.getSenders();origAddStream.apply(this,arguments);var newSenders=this.getSenders().filter(function(newSender){return existingSenders.indexOf(newSender)===-1;});this._shimmedLocalStreams[stream.id]=[stream].concat(newSenders);};var origRemoveStream=window.RTCPeerConnection.prototype.removeStream;window.RTCPeerConnection.prototype.removeStream=function(stream){this._shimmedLocalStreams=this._shimmedLocalStreams||{};delete this._shimmedLocalStreams[stream.id];return origRemoveStream.apply(this,arguments);};var origRemoveTrack=window.RTCPeerConnection.prototype.removeTrack;window.RTCPeerConnection.prototype.removeTrack=function(sender){var _this9=this;this._shimmedLocalStreams=this._shimmedLocalStreams||{};if(sender){Object.keys(this._shimmedLocalStreams).forEach(function(streamId){var idx=_this9._shimmedLocalStreams[streamId].indexOf(sender);if(idx!==-1){_this9._shimmedLocalStreams[streamId].splice(idx,1);}
+if(_this9._shimmedLocalStreams[streamId].length===1){delete _this9._shimmedLocalStreams[streamId];}});}
+return origRemoveTrack.apply(this,arguments);};}
+function shimAddTrackRemoveTrack(window){if(!window.RTCPeerConnection){return;}
+var browserDetails=utils.detectBrowser(window);if(window.RTCPeerConnection.prototype.addTrack&&browserDetails.version>=65){return shimAddTrackRemoveTrackWithNative(window);}
+var origGetLocalStreams=window.RTCPeerConnection.prototype.getLocalStreams;window.RTCPeerConnection.prototype.getLocalStreams=function(){var _this10=this;var nativeStreams=origGetLocalStreams.apply(this);this._reverseStreams=this._reverseStreams||{};return nativeStreams.map(function(stream){return _this10._reverseStreams[stream.id];});};var origAddStream=window.RTCPeerConnection.prototype.addStream;window.RTCPeerConnection.prototype.addStream=function(stream){var _this11=this;this._streams=this._streams||{};this._reverseStreams=this._reverseStreams||{};stream.getTracks().forEach(function(track){var alreadyExists=_this11.getSenders().find(function(s){return s.track===track;});if(alreadyExists){throw new DOMException('Track already exists.','InvalidAccessError');}});if(!this._reverseStreams[stream.id]){var newStream=new window.MediaStream(stream.getTracks());this._streams[stream.id]=newStream;this._reverseStreams[newStream.id]=stream;stream=newStream;}
+origAddStream.apply(this,[stream]);};var origRemoveStream=window.RTCPeerConnection.prototype.removeStream;window.RTCPeerConnection.prototype.removeStream=function(stream){this._streams=this._streams||{};this._reverseStreams=this._reverseStreams||{};origRemoveStream.apply(this,[this._streams[stream.id]||stream]);delete this._reverseStreams[this._streams[stream.id]?this._streams[stream.id].id:stream.id];delete this._streams[stream.id];};window.RTCPeerConnection.prototype.addTrack=function(track,stream){var _this12=this;if(this.signalingState==='closed'){throw new DOMException('The RTCPeerConnection\'s signalingState is \'closed\'.','InvalidStateError');}
+var streams=[].slice.call(arguments,1);if(streams.length!==1||!streams[0].getTracks().find(function(t){return t===track;})){throw new DOMException('The adapter.js addTrack polyfill only supports a single '+' stream which is associated with the specified track.','NotSupportedError');}
+var alreadyExists=this.getSenders().find(function(s){return s.track===track;});if(alreadyExists){throw new DOMException('Track already exists.','InvalidAccessError');}
+this._streams=this._streams||{};this._reverseStreams=this._reverseStreams||{};var oldStream=this._streams[stream.id];if(oldStream){oldStream.addTrack(track);Promise.resolve().then(function(){_this12.dispatchEvent(new Event('negotiationneeded'));});}else{var newStream=new window.MediaStream([track]);this._streams[stream.id]=newStream;this._reverseStreams[newStream.id]=stream;this.addStream(newStream);}
+return this.getSenders().find(function(s){return s.track===track;});};function replaceInternalStreamId(pc,description){var sdp=description.sdp;Object.keys(pc._reverseStreams||[]).forEach(function(internalId){var externalStream=pc._reverseStreams[internalId];var internalStream=pc._streams[externalStream.id];sdp=sdp.replace(new RegExp(internalStream.id,'g'),externalStream.id);});return new RTCSessionDescription({type:description.type,sdp:sdp});}
+function replaceExternalStreamId(pc,description){var sdp=description.sdp;Object.keys(pc._reverseStreams||[]).forEach(function(internalId){var externalStream=pc._reverseStreams[internalId];var internalStream=pc._streams[externalStream.id];sdp=sdp.replace(new RegExp(externalStream.id,'g'),internalStream.id);});return new RTCSessionDescription({type:description.type,sdp:sdp});}
+['createOffer','createAnswer'].forEach(function(method){var nativeMethod=window.RTCPeerConnection.prototype[method];window.RTCPeerConnection.prototype[method]=function(){var _this13=this;var args=arguments;var isLegacyCall=arguments.length&&typeof arguments[0]==='function';if(isLegacyCall){return nativeMethod.apply(this,[function(description){var desc=replaceInternalStreamId(_this13,description);args[0].apply(null,[desc]);},function(err){if(args[1]){args[1].apply(null,err);}},arguments[2]]);}
+return nativeMethod.apply(this,arguments).then(function(description){return replaceInternalStreamId(_this13,description);});};});var origSetLocalDescription=window.RTCPeerConnection.prototype.setLocalDescription;window.RTCPeerConnection.prototype.setLocalDescription=function(){if(!arguments.length||!arguments[0].type){return origSetLocalDescription.apply(this,arguments);}
+arguments[0]=replaceExternalStreamId(this,arguments[0]);return origSetLocalDescription.apply(this,arguments);};var origLocalDescription=Object.getOwnPropertyDescriptor(window.RTCPeerConnection.prototype,'localDescription');Object.defineProperty(window.RTCPeerConnection.prototype,'localDescription',{get:function get(){var description=origLocalDescription.get.apply(this);if(description.type===''){return description;}
+return replaceInternalStreamId(this,description);}});window.RTCPeerConnection.prototype.removeTrack=function(sender){var _this14=this;if(this.signalingState==='closed'){throw new DOMException('The RTCPeerConnection\'s signalingState is \'closed\'.','InvalidStateError');}
+if(!sender._pc){throw new DOMException('Argument 1 of RTCPeerConnection.removeTrack '+'does not implement interface RTCRtpSender.','TypeError');}
+var isLocal=sender._pc===this;if(!isLocal){throw new DOMException('Sender was not created by this connection.','InvalidAccessError');}
+this._streams=this._streams||{};var stream=void 0;Object.keys(this._streams).forEach(function(streamid){var hasTrack=_this14._streams[streamid].getTracks().find(function(track){return sender.track===track;});if(hasTrack){stream=_this14._streams[streamid];}});if(stream){if(stream.getTracks().length===1){this.removeStream(this._reverseStreams[stream.id]);}else{stream.removeTrack(sender.track);}
+this.dispatchEvent(new Event('negotiationneeded'));}};}
+function shimPeerConnection(window){if(!window.RTCPeerConnection&&window.webkitRTCPeerConnection){window.RTCPeerConnection=window.webkitRTCPeerConnection;}
+if(!window.RTCPeerConnection){return;}
+var origGetStats=window.RTCPeerConnection.prototype.getStats;window.RTCPeerConnection.prototype.getStats=function(selector,successCallback,errorCallback){var _this15=this;var args=arguments;if(arguments.length>0&&typeof selector==='function'){return origGetStats.apply(this,arguments);}
+if(origGetStats.length===0&&(arguments.length===0||typeof arguments[0]!=='function')){return origGetStats.apply(this,[]);}
+var fixChromeStats_=function fixChromeStats_(response){var standardReport={};var reports=response.result();reports.forEach(function(report){var standardStats={id:report.id,timestamp:report.timestamp,type:{localcandidate:'local-candidate',remotecandidate:'remote-candidate'}[report.type]||report.type};report.names().forEach(function(name){standardStats[name]=report.stat(name);});standardReport[standardStats.id]=standardStats;});return standardReport;};var makeMapStats=function makeMapStats(stats){return new Map(Object.keys(stats).map(function(key){return[key,stats[key]];}));};if(arguments.length>=2){var successCallbackWrapper_=function successCallbackWrapper_(response){args[1](makeMapStats(fixChromeStats_(response)));};return origGetStats.apply(this,[successCallbackWrapper_,arguments[0]]);}
+return new Promise(function(resolve,reject){origGetStats.apply(_this15,[function(response){resolve(makeMapStats(fixChromeStats_(response)));},reject]);}).then(successCallback,errorCallback);};['setLocalDescription','setRemoteDescription','addIceCandidate'].forEach(function(method){var nativeMethod=window.RTCPeerConnection.prototype[method];window.RTCPeerConnection.prototype[method]=function(){arguments[0]=new(method==='addIceCandidate'?window.RTCIceCandidate:window.RTCSessionDescription)(arguments[0]);return nativeMethod.apply(this,arguments);};});var nativeAddIceCandidate=window.RTCPeerConnection.prototype.addIceCandidate;window.RTCPeerConnection.prototype.addIceCandidate=function(){if(!arguments[0]){if(arguments[1]){arguments[1].apply(null);}
+return Promise.resolve();}
+return nativeAddIceCandidate.apply(this,arguments);};}
+function fixNegotiationNeeded(window){utils.wrapPeerConnectionEvent(window,'negotiationneeded',function(e){var pc=e.target;if(pc.signalingState!=='stable'){return;}
+return e;});}},{"../utils.js":15,"./getdisplaymedia":4,"./getusermedia":5}],4:[function(require,module,exports){'use strict';Object.defineProperty(exports,"__esModule",{value:true});exports.shimGetDisplayMedia=shimGetDisplayMedia;function shimGetDisplayMedia(window,getSourceId){if(window.navigator.mediaDevices&&'getDisplayMedia'in window.navigator.mediaDevices){return;}
+if(!window.navigator.mediaDevices){return;}
+if(typeof getSourceId!=='function'){console.error('shimGetDisplayMedia: getSourceId argument is not '+'a function');return;}
+window.navigator.mediaDevices.getDisplayMedia=function(constraints){return getSourceId(constraints).then(function(sourceId){var widthSpecified=constraints.video&&constraints.video.width;var heightSpecified=constraints.video&&constraints.video.height;var frameRateSpecified=constraints.video&&constraints.video.frameRate;constraints.video={mandatory:{chromeMediaSource:'desktop',chromeMediaSourceId:sourceId,maxFrameRate:frameRateSpecified||3}};if(widthSpecified){constraints.video.mandatory.maxWidth=widthSpecified;}
+if(heightSpecified){constraints.video.mandatory.maxHeight=heightSpecified;}
+return window.navigator.mediaDevices.getUserMedia(constraints);});};}},{}],5:[function(require,module,exports){'use strict';Object.defineProperty(exports,"__esModule",{value:true});var _typeof=typeof Symbol==="function"&&typeof Symbol.iterator==="symbol"?function(obj){return typeof obj;}:function(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj;};exports.shimGetUserMedia=shimGetUserMedia;var _utils=require('../utils.js');var utils=_interopRequireWildcard(_utils);function _interopRequireWildcard(obj){if(obj&&obj.__esModule){return obj;}else{var newObj={};if(obj!=null){for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key))newObj[key]=obj[key];}}newObj.default=obj;return newObj;}}
+var logging=utils.log;function shimGetUserMedia(window){var navigator=window&&window.navigator;if(!navigator.mediaDevices){return;}
+var browserDetails=utils.detectBrowser(window);var constraintsToChrome_=function constraintsToChrome_(c){if((typeof c==='undefined'?'undefined':_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 oldname_(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;};var shimConstraints_=function shimConstraints_(constraints,func){if(browserDetails.version>=61){return func(constraints);}
+constraints=JSON.parse(JSON.stringify(constraints));if(constraints&&_typeof(constraints.audio)==='object'){var remap=function remap(obj,a,b){if(a in obj&&!(b in obj)){obj[b]=obj[a];delete obj[a];}};constraints=JSON.parse(JSON.stringify(constraints));remap(constraints.audio,'autoGainControl','googAutoGainControl');remap(constraints.audio,'noiseSuppression','googNoiseSuppression');constraints.audio=constraintsToChrome_(constraints.audio);}
+if(constraints&&_typeof(constraints.video)==='object'){var face=constraints.video.facingMode;face=face&&((typeof face==='undefined'?'undefined':_typeof(face))==='object'?face:{ideal:face});var getSupportedFacingModeLies=browserDetails.version<66;if(face&&(face.exact==='user'||face.exact==='environment'||face.ideal==='user'||face.ideal==='environment')&&!(navigator.mediaDevices.getSupportedConstraints&&navigator.mediaDevices.getSupportedConstraints().facingMode&&!getSupportedFacingModeLies)){delete constraints.video.facingMode;var matches=void 0;if(face.exact==='environment'||face.ideal==='environment'){matches=['back','rear'];}else if(face.exact==='user'||face.ideal==='user'){matches=['front'];}
+if(matches){return navigator.mediaDevices.enumerateDevices().then(function(devices){devices=devices.filter(function(d){return d.kind==='videoinput';});var dev=devices.find(function(d){return matches.some(function(match){return d.label.toLowerCase().includes(match);});});if(!dev&&devices.length&&matches.includes('back')){dev=devices[devices.length-1];}
+if(dev){constraints.video.deviceId=face.exact?{exact:dev.deviceId}:{ideal:dev.deviceId};}
+constraints.video=constraintsToChrome_(constraints.video);logging('chrome: '+JSON.stringify(constraints));return func(constraints);});}}
+constraints.video=constraintsToChrome_(constraints.video);}
+logging('chrome: '+JSON.stringify(constraints));return func(constraints);};var shimError_=function shimError_(e){if(browserDetails.version>=64){return e;}
+return{name:{PermissionDeniedError:'NotAllowedError',PermissionDismissedError:'NotAllowedError',InvalidStateError:'NotAllowedError',DevicesNotFoundError:'NotFoundError',ConstraintNotSatisfiedError:'OverconstrainedError',TrackStartError:'NotReadableError',MediaDeviceFailedDueToShutdown:'NotAllowedError',MediaDeviceKillSwitchOn:'NotAllowedError',TabCaptureError:'AbortError',ScreenCaptureError:'AbortError',DeviceCaptureError:'AbortError'}[e.name]||e.name,message:e.message,constraint:e.constraint||e.constraintName,toString:function toString(){return this.name+(this.message&&': ')+this.message;}};};var getUserMedia_=function getUserMedia_(constraints,onSuccess,onError){shimConstraints_(constraints,function(c){navigator.webkitGetUserMedia(c,onSuccess,function(e){if(onError){onError(shimError_(e));}});});};navigator.getUserMedia=getUserMedia_.bind(navigator);var origGetUserMedia=navigator.mediaDevices.getUserMedia.bind(navigator.mediaDevices);navigator.mediaDevices.getUserMedia=function(cs){return shimConstraints_(cs,function(c){return origGetUserMedia(c).then(function(stream){if(c.audio&&!stream.getAudioTracks().length||c.video&&!stream.getVideoTracks().length){stream.getTracks().forEach(function(track){track.stop();});throw new DOMException('','NotFoundError');}
+return stream;},function(e){return Promise.reject(shimError_(e));});});};}},{"../utils.js":15}],6:[function(require,module,exports){'use strict';Object.defineProperty(exports,"__esModule",{value:true});var _typeof=typeof Symbol==="function"&&typeof Symbol.iterator==="symbol"?function(obj){return typeof obj;}:function(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj;};exports.shimRTCIceCandidate=shimRTCIceCandidate;exports.shimMaxMessageSize=shimMaxMessageSize;exports.shimSendThrowTypeError=shimSendThrowTypeError;exports.shimConnectionState=shimConnectionState;exports.removeAllowExtmapMixed=removeAllowExtmapMixed;var _sdp=require('sdp');var _sdp2=_interopRequireDefault(_sdp);var _utils=require('./utils');var utils=_interopRequireWildcard(_utils);function _interopRequireWildcard(obj){if(obj&&obj.__esModule){return obj;}else{var newObj={};if(obj!=null){for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key))newObj[key]=obj[key];}}newObj.default=obj;return newObj;}}
+function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj};}
+function shimRTCIceCandidate(window){if(!window.RTCIceCandidate||window.RTCIceCandidate&&'foundation'in window.RTCIceCandidate.prototype){return;}
+var NativeRTCIceCandidate=window.RTCIceCandidate;window.RTCIceCandidate=function(args){if((typeof args==='undefined'?'undefined':_typeof(args))==='object'&&args.candidate&&args.candidate.indexOf('a=')===0){args=JSON.parse(JSON.stringify(args));args.candidate=args.candidate.substr(2);}
+if(args.candidate&&args.candidate.length){var nativeCandidate=new NativeRTCIceCandidate(args);var parsedCandidate=_sdp2.default.parseCandidate(args.candidate);var augmentedCandidate=Object.assign(nativeCandidate,parsedCandidate);augmentedCandidate.toJSON=function(){return{candidate:augmentedCandidate.candidate,sdpMid:augmentedCandidate.sdpMid,sdpMLineIndex:augmentedCandidate.sdpMLineIndex,usernameFragment:augmentedCandidate.usernameFragment};};return augmentedCandidate;}
+return new NativeRTCIceCandidate(args);};window.RTCIceCandidate.prototype=NativeRTCIceCandidate.prototype;utils.wrapPeerConnectionEvent(window,'icecandidate',function(e){if(e.candidate){Object.defineProperty(e,'candidate',{value:new window.RTCIceCandidate(e.candidate),writable:'false'});}
+return e;});}
+function shimMaxMessageSize(window){if(window.RTCSctpTransport||!window.RTCPeerConnection){return;}
+var browserDetails=utils.detectBrowser(window);if(!('sctp'in window.RTCPeerConnection.prototype)){Object.defineProperty(window.RTCPeerConnection.prototype,'sctp',{get:function get(){return typeof this._sctp==='undefined'?null:this._sctp;}});}
+var sctpInDescription=function sctpInDescription(description){var sections=_sdp2.default.splitSections(description.sdp);sections.shift();return sections.some(function(mediaSection){var mLine=_sdp2.default.parseMLine(mediaSection);return mLine&&mLine.kind==='application'&&mLine.protocol.indexOf('SCTP')!==-1;});};var getRemoteFirefoxVersion=function getRemoteFirefoxVersion(description){var match=description.sdp.match(/mozilla...THIS_IS_SDPARTA-(\d+)/);if(match===null||match.length<2){return-1;}
+var version=parseInt(match[1],10);return version!==version?-1:version;};var getCanSendMaxMessageSize=function getCanSendMaxMessageSize(remoteIsFirefox){var canSendMaxMessageSize=65536;if(browserDetails.browser==='firefox'){if(browserDetails.version<57){if(remoteIsFirefox===-1){canSendMaxMessageSize=16384;}else{canSendMaxMessageSize=2147483637;}}else if(browserDetails.version<60){canSendMaxMessageSize=browserDetails.version===57?65535:65536;}else{canSendMaxMessageSize=2147483637;}}
+return canSendMaxMessageSize;};var getMaxMessageSize=function getMaxMessageSize(description,remoteIsFirefox){var maxMessageSize=65536;if(browserDetails.browser==='firefox'&&browserDetails.version===57){maxMessageSize=65535;}
+var match=_sdp2.default.matchPrefix(description.sdp,'a=max-message-size:');if(match.length>0){maxMessageSize=parseInt(match[0].substr(19),10);}else if(browserDetails.browser==='firefox'&&remoteIsFirefox!==-1){maxMessageSize=2147483637;}
+return maxMessageSize;};var origSetRemoteDescription=window.RTCPeerConnection.prototype.setRemoteDescription;window.RTCPeerConnection.prototype.setRemoteDescription=function(){this._sctp=null;if(sctpInDescription(arguments[0])){var isFirefox=getRemoteFirefoxVersion(arguments[0]);var canSendMMS=getCanSendMaxMessageSize(isFirefox);var remoteMMS=getMaxMessageSize(arguments[0],isFirefox);var maxMessageSize=void 0;if(canSendMMS===0&&remoteMMS===0){maxMessageSize=Number.POSITIVE_INFINITY;}else if(canSendMMS===0||remoteMMS===0){maxMessageSize=Math.max(canSendMMS,remoteMMS);}else{maxMessageSize=Math.min(canSendMMS,remoteMMS);}
+var sctp={};Object.defineProperty(sctp,'maxMessageSize',{get:function get(){return maxMessageSize;}});this._sctp=sctp;}
+return origSetRemoteDescription.apply(this,arguments);};}
+function shimSendThrowTypeError(window){if(!(window.RTCPeerConnection&&'createDataChannel'in window.RTCPeerConnection.prototype)){return;}
+function wrapDcSend(dc,pc){var origDataChannelSend=dc.send;dc.send=function(){var data=arguments[0];var length=data.length||data.size||data.byteLength;if(dc.readyState==='open'&&pc.sctp&&length>pc.sctp.maxMessageSize){throw new TypeError('Message too large (can send a maximum of '+pc.sctp.maxMessageSize+' bytes)');}
+return origDataChannelSend.apply(dc,arguments);};}
+var origCreateDataChannel=window.RTCPeerConnection.prototype.createDataChannel;window.RTCPeerConnection.prototype.createDataChannel=function(){var dataChannel=origCreateDataChannel.apply(this,arguments);wrapDcSend(dataChannel,this);return dataChannel;};utils.wrapPeerConnectionEvent(window,'datachannel',function(e){wrapDcSend(e.channel,e.target);return e;});}
+function shimConnectionState(window){if(!window.RTCPeerConnection||'connectionState'in window.RTCPeerConnection.prototype){return;}
+var proto=window.RTCPeerConnection.prototype;Object.defineProperty(proto,'connectionState',{get:function get(){return{completed:'connected',checking:'connecting'}[this.iceConnectionState]||this.iceConnectionState;},enumerable:true,configurable:true});Object.defineProperty(proto,'onconnectionstatechange',{get:function get(){return this._onconnectionstatechange||null;},set:function set(cb){if(this._onconnectionstatechange){this.removeEventListener('connectionstatechange',this._onconnectionstatechange);delete this._onconnectionstatechange;}
+if(cb){this.addEventListener('connectionstatechange',this._onconnectionstatechange=cb);}},enumerable:true,configurable:true});['setLocalDescription','setRemoteDescription'].forEach(function(method){var origMethod=proto[method];proto[method]=function(){if(!this._connectionstatechangepoly){this._connectionstatechangepoly=function(e){var pc=e.target;if(pc._lastConnectionState!==pc.connectionState){pc._lastConnectionState=pc.connectionState;var newEvent=new Event('connectionstatechange',e);pc.dispatchEvent(newEvent);}
+return e;};this.addEventListener('iceconnectionstatechange',this._connectionstatechangepoly);}
+return origMethod.apply(this,arguments);};});}
+function removeAllowExtmapMixed(window){if(!window.RTCPeerConnection){return;}
+var browserDetails=utils.detectBrowser(window);if(browserDetails.browser==='chrome'&&browserDetails.version>=71){return;}
+var nativeSRD=window.RTCPeerConnection.prototype.setRemoteDescription;window.RTCPeerConnection.prototype.setRemoteDescription=function(desc){if(desc&&desc.sdp&&desc.sdp.indexOf('\na=extmap-allow-mixed')!==-1){desc.sdp=desc.sdp.split('\n').filter(function(line){return line.trim()!=='a=extmap-allow-mixed';}).join('\n');}
+return nativeSRD.apply(this,arguments);};}},{"./utils":15,"sdp":17}],7:[function(require,module,exports){'use strict';Object.defineProperty(exports,"__esModule",{value:true});exports.shimGetDisplayMedia=exports.shimGetUserMedia=undefined;var _getusermedia=require('./getusermedia');Object.defineProperty(exports,'shimGetUserMedia',{enumerable:true,get:function get(){return _getusermedia.shimGetUserMedia;}});var _getdisplaymedia=require('./getdisplaymedia');Object.defineProperty(exports,'shimGetDisplayMedia',{enumerable:true,get:function get(){return _getdisplaymedia.shimGetDisplayMedia;}});exports.shimPeerConnection=shimPeerConnection;exports.shimReplaceTrack=shimReplaceTrack;var _utils=require('../utils');var utils=_interopRequireWildcard(_utils);var _filtericeservers=require('./filtericeservers');var _rtcpeerconnectionShim=require('rtcpeerconnection-shim');var _rtcpeerconnectionShim2=_interopRequireDefault(_rtcpeerconnectionShim);function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj};}
+function _interopRequireWildcard(obj){if(obj&&obj.__esModule){return obj;}else{var newObj={};if(obj!=null){for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key))newObj[key]=obj[key];}}newObj.default=obj;return newObj;}}
+function shimPeerConnection(window){var browserDetails=utils.detectBrowser(window);if(window.RTCIceGatherer){if(!window.RTCIceCandidate){window.RTCIceCandidate=function(args){return args;};}
+if(!window.RTCSessionDescription){window.RTCSessionDescription=function(args){return args;};}
+if(browserDetails.version<15025){var origMSTEnabled=Object.getOwnPropertyDescriptor(window.MediaStreamTrack.prototype,'enabled');Object.defineProperty(window.MediaStreamTrack.prototype,'enabled',{set:function set(value){origMSTEnabled.set.call(this,value);var ev=new Event('enabled');ev.enabled=value;this.dispatchEvent(ev);}});}}
+if(window.RTCRtpSender&&!('dtmf'in window.RTCRtpSender.prototype)){Object.defineProperty(window.RTCRtpSender.prototype,'dtmf',{get:function get(){if(this._dtmf===undefined){if(this.track.kind==='audio'){this._dtmf=new window.RTCDtmfSender(this);}else if(this.track.kind==='video'){this._dtmf=null;}}
+return this._dtmf;}});}
+if(window.RTCDtmfSender&&!window.RTCDTMFSender){window.RTCDTMFSender=window.RTCDtmfSender;}
+var RTCPeerConnectionShim=(0,_rtcpeerconnectionShim2.default)(window,browserDetails.version);window.RTCPeerConnection=function(config){if(config&&config.iceServers){config.iceServers=(0,_filtericeservers.filterIceServers)(config.iceServers,browserDetails.version);utils.log('ICE servers after filtering:',config.iceServers);}
+return new RTCPeerConnectionShim(config);};window.RTCPeerConnection.prototype=RTCPeerConnectionShim.prototype;}
+function shimReplaceTrack(window){if(window.RTCRtpSender&&!('replaceTrack'in window.RTCRtpSender.prototype)){window.RTCRtpSender.prototype.replaceTrack=window.RTCRtpSender.prototype.setTrack;}}},{"../utils":15,"./filtericeservers":8,"./getdisplaymedia":9,"./getusermedia":10,"rtcpeerconnection-shim":16}],8:[function(require,module,exports){'use strict';Object.defineProperty(exports,"__esModule",{value:true});exports.filterIceServers=filterIceServers;var _utils=require('../utils');var utils=_interopRequireWildcard(_utils);function _interopRequireWildcard(obj){if(obj&&obj.__esModule){return obj;}else{var newObj={};if(obj!=null){for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key))newObj[key]=obj[key];}}newObj.default=obj;return newObj;}}
+function filterIceServers(iceServers,edgeVersion){var hasTurn=false;iceServers=JSON.parse(JSON.stringify(iceServers));return iceServers.filter(function(server){if(server&&(server.urls||server.url)){var urls=server.urls||server.url;if(server.url&&!server.urls){utils.deprecated('RTCIceServer.url','RTCIceServer.urls');}
+var isString=typeof urls==='string';if(isString){urls=[urls];}
+urls=urls.filter(function(url){if(url.indexOf('stun:')===0){return false;}
+var validTurn=url.startsWith('turn')&&!url.startsWith('turn:[')&&url.includes('transport=udp');if(validTurn&&!hasTurn){hasTurn=true;return true;}
+return validTurn&&!hasTurn;});delete server.url;server.urls=isString?urls[0]:urls;return!!urls.length;}});}},{"../utils":15}],9:[function(require,module,exports){'use strict';Object.defineProperty(exports,"__esModule",{value:true});exports.shimGetDisplayMedia=shimGetDisplayMedia;function shimGetDisplayMedia(window){if(!('getDisplayMedia'in window.navigator)){return;}
+if(!window.navigator.mediaDevices){return;}
+if(window.navigator.mediaDevices&&'getDisplayMedia'in window.navigator.mediaDevices){return;}
+window.navigator.mediaDevices.getDisplayMedia=window.navigator.getDisplayMedia.bind(window.navigator.mediaDevices);}},{}],10:[function(require,module,exports){'use strict';Object.defineProperty(exports,"__esModule",{value:true});exports.shimGetUserMedia=shimGetUserMedia;function shimGetUserMedia(window){var navigator=window&&window.navigator;var shimError_=function shimError_(e){return{name:{PermissionDeniedError:'NotAllowedError'}[e.name]||e.name,message:e.message,constraint:e.constraint,toString:function toString(){return this.name;}};};var origGetUserMedia=navigator.mediaDevices.getUserMedia.bind(navigator.mediaDevices);navigator.mediaDevices.getUserMedia=function(c){return origGetUserMedia(c).catch(function(e){return Promise.reject(shimError_(e));});};}},{}],11:[function(require,module,exports){'use strict';Object.defineProperty(exports,"__esModule",{value:true});exports.shimGetDisplayMedia=exports.shimGetUserMedia=undefined;var _typeof=typeof Symbol==="function"&&typeof Symbol.iterator==="symbol"?function(obj){return typeof obj;}:function(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj;};var _getusermedia=require('./getusermedia');Object.defineProperty(exports,'shimGetUserMedia',{enumerable:true,get:function get(){return _getusermedia.shimGetUserMedia;}});var _getdisplaymedia=require('./getdisplaymedia');Object.defineProperty(exports,'shimGetDisplayMedia',{enumerable:true,get:function get(){return _getdisplaymedia.shimGetDisplayMedia;}});exports.shimOnTrack=shimOnTrack;exports.shimPeerConnection=shimPeerConnection;exports.shimSenderGetStats=shimSenderGetStats;exports.shimReceiverGetStats=shimReceiverGetStats;exports.shimRemoveStream=shimRemoveStream;exports.shimRTCDataChannel=shimRTCDataChannel;var _utils=require('../utils');var utils=_interopRequireWildcard(_utils);function _interopRequireWildcard(obj){if(obj&&obj.__esModule){return obj;}else{var newObj={};if(obj!=null){for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key))newObj[key]=obj[key];}}newObj.default=obj;return newObj;}}
+function shimOnTrack(window){if((typeof window==='undefined'?'undefined':_typeof(window))==='object'&&window.RTCTrackEvent&&'receiver'in window.RTCTrackEvent.prototype&&!('transceiver'in window.RTCTrackEvent.prototype)){Object.defineProperty(window.RTCTrackEvent.prototype,'transceiver',{get:function get(){return{receiver:this.receiver};}});}}
+function shimPeerConnection(window){var browserDetails=utils.detectBrowser(window);if((typeof window==='undefined'?'undefined':_typeof(window))!=='object'||!(window.RTCPeerConnection||window.mozRTCPeerConnection)){return;}
+if(!window.RTCPeerConnection&&window.mozRTCPeerConnection){window.RTCPeerConnection=window.mozRTCPeerConnection;}
+['setLocalDescription','setRemoteDescription','addIceCandidate'].forEach(function(method){var nativeMethod=window.RTCPeerConnection.prototype[method];window.RTCPeerConnection.prototype[method]=function(){arguments[0]=new(method==='addIceCandidate'?window.RTCIceCandidate:window.RTCSessionDescription)(arguments[0]);return nativeMethod.apply(this,arguments);};});var nativeAddIceCandidate=window.RTCPeerConnection.prototype.addIceCandidate;window.RTCPeerConnection.prototype.addIceCandidate=function(){if(!arguments[0]){if(arguments[1]){arguments[1].apply(null);}
+return Promise.resolve();}
+return nativeAddIceCandidate.apply(this,arguments);};var modernStatsTypes={inboundrtp:'inbound-rtp',outboundrtp:'outbound-rtp',candidatepair:'candidate-pair',localcandidate:'local-candidate',remotecandidate:'remote-candidate'};var nativeGetStats=window.RTCPeerConnection.prototype.getStats;window.RTCPeerConnection.prototype.getStats=function(selector,onSucc,onErr){return nativeGetStats.apply(this,[selector||null]).then(function(stats){if(browserDetails.version<53&&!onSucc){try{stats.forEach(function(stat){stat.type=modernStatsTypes[stat.type]||stat.type;});}catch(e){if(e.name!=='TypeError'){throw e;}
+stats.forEach(function(stat,i){stats.set(i,Object.assign({},stat,{type:modernStatsTypes[stat.type]||stat.type}));});}}
+return stats;}).then(onSucc,onErr);};}
+function shimSenderGetStats(window){if(!((typeof window==='undefined'?'undefined':_typeof(window))==='object'&&window.RTCPeerConnection&&window.RTCRtpSender)){return;}
+if(window.RTCRtpSender&&'getStats'in window.RTCRtpSender.prototype){return;}
+var origGetSenders=window.RTCPeerConnection.prototype.getSenders;if(origGetSenders){window.RTCPeerConnection.prototype.getSenders=function(){var _this=this;var senders=origGetSenders.apply(this,[]);senders.forEach(function(sender){return sender._pc=_this;});return senders;};}
+var origAddTrack=window.RTCPeerConnection.prototype.addTrack;if(origAddTrack){window.RTCPeerConnection.prototype.addTrack=function(){var sender=origAddTrack.apply(this,arguments);sender._pc=this;return sender;};}
+window.RTCRtpSender.prototype.getStats=function(){return this.track?this._pc.getStats(this.track):Promise.resolve(new Map());};}
+function shimReceiverGetStats(window){if(!((typeof window==='undefined'?'undefined':_typeof(window))==='object'&&window.RTCPeerConnection&&window.RTCRtpSender)){return;}
+if(window.RTCRtpSender&&'getStats'in window.RTCRtpReceiver.prototype){return;}
+var origGetReceivers=window.RTCPeerConnection.prototype.getReceivers;if(origGetReceivers){window.RTCPeerConnection.prototype.getReceivers=function(){var _this2=this;var receivers=origGetReceivers.apply(this,[]);receivers.forEach(function(receiver){return receiver._pc=_this2;});return receivers;};}
+utils.wrapPeerConnectionEvent(window,'track',function(e){e.receiver._pc=e.srcElement;return e;});window.RTCRtpReceiver.prototype.getStats=function(){return this._pc.getStats(this.track);};}
+function shimRemoveStream(window){if(!window.RTCPeerConnection||'removeStream'in window.RTCPeerConnection.prototype){return;}
+window.RTCPeerConnection.prototype.removeStream=function(stream){var _this3=this;utils.deprecated('removeStream','removeTrack');this.getSenders().forEach(function(sender){if(sender.track&&stream.getTracks().includes(sender.track)){_this3.removeTrack(sender);}});};}
+function shimRTCDataChannel(window){if(window.DataChannel&&!window.RTCDataChannel){window.RTCDataChannel=window.DataChannel;}}},{"../utils":15,"./getdisplaymedia":12,"./getusermedia":13}],12:[function(require,module,exports){'use strict';Object.defineProperty(exports,"__esModule",{value:true});exports.shimGetDisplayMedia=shimGetDisplayMedia;function shimGetDisplayMedia(window,preferredMediaSource){if(window.navigator.mediaDevices&&'getDisplayMedia'in window.navigator.mediaDevices){return;}
+if(!window.navigator.mediaDevices){return;}
+window.navigator.mediaDevices.getDisplayMedia=function(constraints){if(!(constraints&&constraints.video)){var err=new DOMException('getDisplayMedia without video '+'constraints is undefined');err.name='NotFoundError';err.code=8;return Promise.reject(err);}
+if(constraints.video===true){constraints.video={mediaSource:preferredMediaSource};}else{constraints.video.mediaSource=preferredMediaSource;}
+return window.navigator.mediaDevices.getUserMedia(constraints);};}},{}],13:[function(require,module,exports){'use strict';Object.defineProperty(exports,"__esModule",{value:true});var _typeof=typeof Symbol==="function"&&typeof Symbol.iterator==="symbol"?function(obj){return typeof obj;}:function(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj;};exports.shimGetUserMedia=shimGetUserMedia;var _utils=require('../utils');var utils=_interopRequireWildcard(_utils);function _interopRequireWildcard(obj){if(obj&&obj.__esModule){return obj;}else{var newObj={};if(obj!=null){for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key))newObj[key]=obj[key];}}newObj.default=obj;return newObj;}}
+function shimGetUserMedia(window){var browserDetails=utils.detectBrowser(window);var navigator=window&&window.navigator;var MediaStreamTrack=window&&window.MediaStreamTrack;navigator.getUserMedia=function(constraints,onSuccess,onError){utils.deprecated('navigator.getUserMedia','navigator.mediaDevices.getUserMedia');navigator.mediaDevices.getUserMedia(constraints).then(onSuccess,onError);};if(!(browserDetails.version>55&&'autoGainControl'in navigator.mediaDevices.getSupportedConstraints())){var remap=function remap(obj,a,b){if(a in obj&&!(b in obj)){obj[b]=obj[a];delete obj[a];}};var nativeGetUserMedia=navigator.mediaDevices.getUserMedia.bind(navigator.mediaDevices);navigator.mediaDevices.getUserMedia=function(c){if((typeof c==='undefined'?'undefined':_typeof(c))==='object'&&_typeof(c.audio)==='object'){c=JSON.parse(JSON.stringify(c));remap(c.audio,'autoGainControl','mozAutoGainControl');remap(c.audio,'noiseSuppression','mozNoiseSuppression');}
+return nativeGetUserMedia(c);};if(MediaStreamTrack&&MediaStreamTrack.prototype.getSettings){var nativeGetSettings=MediaStreamTrack.prototype.getSettings;MediaStreamTrack.prototype.getSettings=function(){var obj=nativeGetSettings.apply(this,arguments);remap(obj,'mozAutoGainControl','autoGainControl');remap(obj,'mozNoiseSuppression','noiseSuppression');return obj;};}
+if(MediaStreamTrack&&MediaStreamTrack.prototype.applyConstraints){var nativeApplyConstraints=MediaStreamTrack.prototype.applyConstraints;MediaStreamTrack.prototype.applyConstraints=function(c){if(this.kind==='audio'&&(typeof c==='undefined'?'undefined':_typeof(c))==='object'){c=JSON.parse(JSON.stringify(c));remap(c,'autoGainControl','mozAutoGainControl');remap(c,'noiseSuppression','mozNoiseSuppression');}
+return nativeApplyConstraints.apply(this,[c]);};}}}},{"../utils":15}],14:[function(require,module,exports){'use strict';Object.defineProperty(exports,"__esModule",{value:true});var _typeof=typeof Symbol==="function"&&typeof Symbol.iterator==="symbol"?function(obj){return typeof obj;}:function(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj;};exports.shimLocalStreamsAPI=shimLocalStreamsAPI;exports.shimRemoteStreamsAPI=shimRemoteStreamsAPI;exports.shimCallbacksAPI=shimCallbacksAPI;exports.shimGetUserMedia=shimGetUserMedia;exports.shimConstraints=shimConstraints;exports.shimRTCIceServerUrls=shimRTCIceServerUrls;exports.shimTrackEventTransceiver=shimTrackEventTransceiver;exports.shimCreateOfferLegacy=shimCreateOfferLegacy;var _utils=require('../utils');var utils=_interopRequireWildcard(_utils);function _interopRequireWildcard(obj){if(obj&&obj.__esModule){return obj;}else{var newObj={};if(obj!=null){for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key))newObj[key]=obj[key];}}newObj.default=obj;return newObj;}}
+function shimLocalStreamsAPI(window){if((typeof window==='undefined'?'undefined':_typeof(window))!=='object'||!window.RTCPeerConnection){return;}
+if(!('getLocalStreams'in window.RTCPeerConnection.prototype)){window.RTCPeerConnection.prototype.getLocalStreams=function(){if(!this._localStreams){this._localStreams=[];}
+return this._localStreams;};}
+if(!('addStream'in window.RTCPeerConnection.prototype)){var _addTrack=window.RTCPeerConnection.prototype.addTrack;window.RTCPeerConnection.prototype.addStream=function(stream){var _this=this;if(!this._localStreams){this._localStreams=[];}
+if(!this._localStreams.includes(stream)){this._localStreams.push(stream);}
+stream.getTracks().forEach(function(track){return _addTrack.call(_this,track,stream);});};window.RTCPeerConnection.prototype.addTrack=function(track,stream){if(stream){if(!this._localStreams){this._localStreams=[stream];}else if(!this._localStreams.includes(stream)){this._localStreams.push(stream);}}
+return _addTrack.call(this,track,stream);};}
+if(!('removeStream'in window.RTCPeerConnection.prototype)){window.RTCPeerConnection.prototype.removeStream=function(stream){var _this2=this;if(!this._localStreams){this._localStreams=[];}
+var index=this._localStreams.indexOf(stream);if(index===-1){return;}
+this._localStreams.splice(index,1);var tracks=stream.getTracks();this.getSenders().forEach(function(sender){if(tracks.includes(sender.track)){_this2.removeTrack(sender);}});};}}
+function shimRemoteStreamsAPI(window){if((typeof window==='undefined'?'undefined':_typeof(window))!=='object'||!window.RTCPeerConnection){return;}
+if(!('getRemoteStreams'in window.RTCPeerConnection.prototype)){window.RTCPeerConnection.prototype.getRemoteStreams=function(){return this._remoteStreams?this._remoteStreams:[];};}
+if(!('onaddstream'in window.RTCPeerConnection.prototype)){Object.defineProperty(window.RTCPeerConnection.prototype,'onaddstream',{get:function get(){return this._onaddstream;},set:function set(f){var _this3=this;if(this._onaddstream){this.removeEventListener('addstream',this._onaddstream);this.removeEventListener('track',this._onaddstreampoly);}
+this.addEventListener('addstream',this._onaddstream=f);this.addEventListener('track',this._onaddstreampoly=function(e){e.streams.forEach(function(stream){if(!_this3._remoteStreams){_this3._remoteStreams=[];}
+if(_this3._remoteStreams.includes(stream)){return;}
+_this3._remoteStreams.push(stream);var event=new Event('addstream');event.stream=stream;_this3.dispatchEvent(event);});});}});var origSetRemoteDescription=window.RTCPeerConnection.prototype.setRemoteDescription;window.RTCPeerConnection.prototype.setRemoteDescription=function(){var pc=this;if(!this._onaddstreampoly){this.addEventListener('track',this._onaddstreampoly=function(e){e.streams.forEach(function(stream){if(!pc._remoteStreams){pc._remoteStreams=[];}
+if(pc._remoteStreams.indexOf(stream)>=0){return;}
+pc._remoteStreams.push(stream);var event=new Event('addstream');event.stream=stream;pc.dispatchEvent(event);});});}
+return origSetRemoteDescription.apply(pc,arguments);};}}
+function shimCallbacksAPI(window){if((typeof window==='undefined'?'undefined':_typeof(window))!=='object'||!window.RTCPeerConnection){return;}
+var prototype=window.RTCPeerConnection.prototype;var createOffer=prototype.createOffer;var createAnswer=prototype.createAnswer;var setLocalDescription=prototype.setLocalDescription;var setRemoteDescription=prototype.setRemoteDescription;var addIceCandidate=prototype.addIceCandidate;prototype.createOffer=function(successCallback,failureCallback){var options=arguments.length>=2?arguments[2]:arguments[0];var promise=createOffer.apply(this,[options]);if(!failureCallback){return promise;}
+promise.then(successCallback,failureCallback);return Promise.resolve();};prototype.createAnswer=function(successCallback,failureCallback){var options=arguments.length>=2?arguments[2]:arguments[0];var promise=createAnswer.apply(this,[options]);if(!failureCallback){return promise;}
+promise.then(successCallback,failureCallback);return Promise.resolve();};var withCallback=function withCallback(description,successCallback,failureCallback){var promise=setLocalDescription.apply(this,[description]);if(!failureCallback){return promise;}
+promise.then(successCallback,failureCallback);return Promise.resolve();};prototype.setLocalDescription=withCallback;withCallback=function withCallback(description,successCallback,failureCallback){var promise=setRemoteDescription.apply(this,[description]);if(!failureCallback){return promise;}
+promise.then(successCallback,failureCallback);return Promise.resolve();};prototype.setRemoteDescription=withCallback;withCallback=function withCallback(candidate,successCallback,failureCallback){var promise=addIceCandidate.apply(this,[candidate]);if(!failureCallback){return promise;}
+promise.then(successCallback,failureCallback);return Promise.resolve();};prototype.addIceCandidate=withCallback;}
+function shimGetUserMedia(window){var navigator=window&&window.navigator;if(navigator.mediaDevices&&navigator.mediaDevices.getUserMedia){var mediaDevices=navigator.mediaDevices;var _getUserMedia=mediaDevices.getUserMedia.bind(mediaDevices);navigator.mediaDevices.getUserMedia=function(constraints){return _getUserMedia(shimConstraints(constraints));};}
+if(!navigator.getUserMedia&&navigator.mediaDevices&&navigator.mediaDevices.getUserMedia){navigator.getUserMedia=function(constraints,cb,errcb){navigator.mediaDevices.getUserMedia(constraints).then(cb,errcb);}.bind(navigator);}}
+function shimConstraints(constraints){if(constraints&&constraints.video!==undefined){return Object.assign({},constraints,{video:utils.compactObject(constraints.video)});}
+return constraints;}
+function shimRTCIceServerUrls(window){var OrigPeerConnection=window.RTCPeerConnection;window.RTCPeerConnection=function(pcConfig,pcConstraints){if(pcConfig&&pcConfig.iceServers){var newIceServers=[];for(var i=0;i=pos&&parseInt(match[pos],10);}
+function wrapPeerConnectionEvent(window,eventNameToWrap,wrapper){if(!window.RTCPeerConnection){return;}
+var proto=window.RTCPeerConnection.prototype;var nativeAddEventListener=proto.addEventListener;proto.addEventListener=function(nativeEventName,cb){if(nativeEventName!==eventNameToWrap){return nativeAddEventListener.apply(this,arguments);}
+var wrappedCallback=function wrappedCallback(e){var modifiedEvent=wrapper(e);if(modifiedEvent){cb(modifiedEvent);}};this._eventMap=this._eventMap||{};this._eventMap[cb]=wrappedCallback;return nativeAddEventListener.apply(this,[nativeEventName,wrappedCallback]);};var nativeRemoveEventListener=proto.removeEventListener;proto.removeEventListener=function(nativeEventName,cb){if(nativeEventName!==eventNameToWrap||!this._eventMap||!this._eventMap[cb]){return nativeRemoveEventListener.apply(this,arguments);}
+var unwrappedCb=this._eventMap[cb];delete this._eventMap[cb];return nativeRemoveEventListener.apply(this,[nativeEventName,unwrappedCb]);};Object.defineProperty(proto,'on'+eventNameToWrap,{get:function get(){return this['_on'+eventNameToWrap];},set:function set(cb){if(this['_on'+eventNameToWrap]){this.removeEventListener(eventNameToWrap,this['_on'+eventNameToWrap]);delete this['_on'+eventNameToWrap];}
+if(cb){this.addEventListener(eventNameToWrap,this['_on'+eventNameToWrap]=cb);}},enumerable:true,configurable:true});}
+function disableLog(bool){if(typeof bool!=='boolean'){return new Error('Argument type: '+(typeof bool==='undefined'?'undefined':_typeof(bool))+'. Please use a boolean.');}
+logDisabled_=bool;return bool?'adapter.js logging disabled':'adapter.js logging enabled';}
+function disableWarnings(bool){if(typeof bool!=='boolean'){return new Error('Argument type: '+(typeof bool==='undefined'?'undefined':_typeof(bool))+'. Please use a boolean.');}
+deprecationWarnings_=!bool;return'adapter.js deprecation warnings '+(bool?'disabled':'enabled');}
+function log(){if((typeof window==='undefined'?'undefined':_typeof(window))==='object'){if(logDisabled_){return;}
+if(typeof console!=='undefined'&&typeof console.log==='function'){console.log.apply(console,arguments);}}}
+function deprecated(oldMethod,newMethod){if(!deprecationWarnings_){return;}
+console.warn(oldMethod+' is deprecated, please use '+newMethod+' instead.');}
+function detectBrowser(window){var navigator=window.navigator;var result={browser:null,version:null};if(typeof window==='undefined'||!window.navigator){result.browser='Not a browser.';return result;}
+if(navigator.mozGetUserMedia){result.browser='firefox';result.version=extractVersion(navigator.userAgent,/Firefox\/(\d+)\./,1);}else if(navigator.webkitGetUserMedia){result.browser='chrome';result.version=extractVersion(navigator.userAgent,/Chrom(e|ium)\/(\d+)\./,2);}else if(navigator.mediaDevices&&navigator.userAgent.match(/Edge\/(\d+).(\d+)$/)){result.browser='edge';result.version=extractVersion(navigator.userAgent,/Edge\/(\d+).(\d+)$/,2);}else if(window.RTCPeerConnection&&navigator.userAgent.match(/AppleWebKit\/(\d+)\./)){result.browser='safari';result.version=extractVersion(navigator.userAgent,/AppleWebKit\/(\d+)\./,1);}else{result.browser='Not a supported browser.';return result;}
+return result;}
+function compactObject(data){if((typeof data==='undefined'?'undefined':_typeof(data))!=='object'){return data;}
+return Object.keys(data).reduce(function(accumulator,key){var isObject=_typeof(data[key])==='object';var value=isObject?compactObject(data[key]):data[key];var isEmptyObject=isObject&&!Object.keys(value).length;if(value===undefined||isEmptyObject){return accumulator;}
+return Object.assign(accumulator,_defineProperty({},key,value));},{});}},{}],16:[function(require,module,exports){'use strict';var SDPUtils=require('sdp');function fixStatsType(stat){return{inboundrtp:'inbound-rtp',outboundrtp:'outbound-rtp',candidatepair:'candidate-pair',localcandidate:'local-candidate',remotecandidate:'remote-candidate'}[stat.type]||stat.type;}
+function writeMediaSection(transceiver,caps,type,stream,dtlsRole){var sdp=SDPUtils.writeRtpDescription(transceiver.kind,caps);sdp+=SDPUtils.writeIceParameters(transceiver.iceGatherer.getLocalParameters());sdp+=SDPUtils.writeDtlsParameters(transceiver.dtlsTransport.getLocalParameters(),type==='offer'?'actpass':dtlsRole||'active');sdp+='a=mid:'+transceiver.mid+'\r\n';if(transceiver.rtpSender&&transceiver.rtpReceiver){sdp+='a=sendrecv\r\n';}else if(transceiver.rtpSender){sdp+='a=sendonly\r\n';}else if(transceiver.rtpReceiver){sdp+='a=recvonly\r\n';}else{sdp+='a=inactive\r\n';}
+if(transceiver.rtpSender){var trackId=transceiver.rtpSender._initialTrackId||transceiver.rtpSender.track.id;transceiver.rtpSender._initialTrackId=trackId;var msid='msid:'+(stream?stream.id:'-')+' '+
+trackId+'\r\n';sdp+='a='+msid;sdp+='a=ssrc:'+transceiver.sendEncodingParameters[0].ssrc+' '+msid;if(transceiver.sendEncodingParameters[0].rtx){sdp+='a=ssrc:'+transceiver.sendEncodingParameters[0].rtx.ssrc+' '+msid;sdp+='a=ssrc-group:FID '+
+transceiver.sendEncodingParameters[0].ssrc+' '+
+transceiver.sendEncodingParameters[0].rtx.ssrc+'\r\n';}}
+sdp+='a=ssrc:'+transceiver.sendEncodingParameters[0].ssrc+' cname:'+SDPUtils.localCName+'\r\n';if(transceiver.rtpSender&&transceiver.sendEncodingParameters[0].rtx){sdp+='a=ssrc:'+transceiver.sendEncodingParameters[0].rtx.ssrc+' cname:'+SDPUtils.localCName+'\r\n';}
+return sdp;}
+function filterIceServers(iceServers,edgeVersion){var hasTurn=false;iceServers=JSON.parse(JSON.stringify(iceServers));return iceServers.filter(function(server){if(server&&(server.urls||server.url)){var urls=server.urls||server.url;if(server.url&&!server.urls){console.warn('RTCIceServer.url is deprecated! Use urls instead.');}
+var isString=typeof urls==='string';if(isString){urls=[urls];}
+urls=urls.filter(function(url){var validTurn=url.indexOf('turn:')===0&&url.indexOf('transport=udp')!==-1&&url.indexOf('turn:[')===-1&&!hasTurn;if(validTurn){hasTurn=true;return true;}
+return url.indexOf('stun:')===0&&edgeVersion>=14393&&url.indexOf('?transport=udp')===-1;});delete server.url;server.urls=isString?urls[0]:urls;return!!urls.length;}});}
+function getCommonCapabilities(localCapabilities,remoteCapabilities){var commonCapabilities={codecs:[],headerExtensions:[],fecMechanisms:[]};var findCodecByPayloadType=function(pt,codecs){pt=parseInt(pt,10);for(var i=0;i0;i--){this._iceGatherers.push(new window.RTCIceGatherer({iceServers:config.iceServers,gatherPolicy:config.iceTransportPolicy}));}}else{config.iceCandidatePoolSize=0;}
+this._config=config;this.transceivers=[];this._sdpSessionId=SDPUtils.generateSessionId();this._sdpSessionVersion=0;this._dtlsRole=undefined;this._isClosed=false;};Object.defineProperty(RTCPeerConnection.prototype,'localDescription',{configurable:true,get:function(){return this._localDescription;}});Object.defineProperty(RTCPeerConnection.prototype,'remoteDescription',{configurable:true,get:function(){return this._remoteDescription;}});RTCPeerConnection.prototype.onicecandidate=null;RTCPeerConnection.prototype.onaddstream=null;RTCPeerConnection.prototype.ontrack=null;RTCPeerConnection.prototype.onremovestream=null;RTCPeerConnection.prototype.onsignalingstatechange=null;RTCPeerConnection.prototype.oniceconnectionstatechange=null;RTCPeerConnection.prototype.onconnectionstatechange=null;RTCPeerConnection.prototype.onicegatheringstatechange=null;RTCPeerConnection.prototype.onnegotiationneeded=null;RTCPeerConnection.prototype.ondatachannel=null;RTCPeerConnection.prototype._dispatchEvent=function(name,event){if(this._isClosed){return;}
+this.dispatchEvent(event);if(typeof this['on'+name]==='function'){this['on'+name](event);}};RTCPeerConnection.prototype._emitGatheringStateChange=function(){var event=new Event('icegatheringstatechange');this._dispatchEvent('icegatheringstatechange',event);};RTCPeerConnection.prototype.getConfiguration=function(){return this._config;};RTCPeerConnection.prototype.getLocalStreams=function(){return this.localStreams;};RTCPeerConnection.prototype.getRemoteStreams=function(){return this.remoteStreams;};RTCPeerConnection.prototype._createTransceiver=function(kind,doNotAdd){var hasBundleTransport=this.transceivers.length>0;var transceiver={track:null,iceGatherer:null,iceTransport:null,dtlsTransport:null,localCapabilities:null,remoteCapabilities:null,rtpSender:null,rtpReceiver:null,kind:kind,mid:null,sendEncodingParameters:null,recvEncodingParameters:null,stream:null,associatedRemoteMediaStreams:[],wantReceive:true};if(this.usingBundle&&hasBundleTransport){transceiver.iceTransport=this.transceivers[0].iceTransport;transceiver.dtlsTransport=this.transceivers[0].dtlsTransport;}else{var transports=this._createIceAndDtlsTransports();transceiver.iceTransport=transports.iceTransport;transceiver.dtlsTransport=transports.dtlsTransport;}
+if(!doNotAdd){this.transceivers.push(transceiver);}
+return transceiver;};RTCPeerConnection.prototype.addTrack=function(track,stream){if(this._isClosed){throw makeError('InvalidStateError','Attempted to call addTrack on a closed peerconnection.');}
+var alreadyExists=this.transceivers.find(function(s){return s.track===track;});if(alreadyExists){throw makeError('InvalidAccessError','Track already exists.');}
+var transceiver;for(var i=0;i=15025){stream.getTracks().forEach(function(track){pc.addTrack(track,stream);});}else{var clonedStream=stream.clone();stream.getTracks().forEach(function(track,idx){var clonedTrack=clonedStream.getTracks()[idx];track.addEventListener('enabled',function(event){clonedTrack.enabled=event.enabled;});});clonedStream.getTracks().forEach(function(track){pc.addTrack(track,clonedStream);});}};RTCPeerConnection.prototype.removeTrack=function(sender){if(this._isClosed){throw makeError('InvalidStateError','Attempted to call removeTrack on a closed peerconnection.');}
+if(!(sender instanceof window.RTCRtpSender)){throw new TypeError('Argument 1 of RTCPeerConnection.removeTrack '+'does not implement interface RTCRtpSender.');}
+var transceiver=this.transceivers.find(function(t){return t.rtpSender===sender;});if(!transceiver){throw makeError('InvalidAccessError','Sender was not created by this connection.');}
+var stream=transceiver.stream;transceiver.rtpSender.stop();transceiver.rtpSender=null;transceiver.track=null;transceiver.stream=null;var localStreams=this.transceivers.map(function(t){return t.stream;});if(localStreams.indexOf(stream)===-1&&this.localStreams.indexOf(stream)>-1){this.localStreams.splice(this.localStreams.indexOf(stream),1);}
+this._maybeFireNegotiationNeeded();};RTCPeerConnection.prototype.removeStream=function(stream){var pc=this;stream.getTracks().forEach(function(track){var sender=pc.getSenders().find(function(s){return s.track===track;});if(sender){pc.removeTrack(sender);}});};RTCPeerConnection.prototype.getSenders=function(){return this.transceivers.filter(function(transceiver){return!!transceiver.rtpSender;}).map(function(transceiver){return transceiver.rtpSender;});};RTCPeerConnection.prototype.getReceivers=function(){return this.transceivers.filter(function(transceiver){return!!transceiver.rtpReceiver;}).map(function(transceiver){return transceiver.rtpReceiver;});};RTCPeerConnection.prototype._createIceGatherer=function(sdpMLineIndex,usingBundle){var pc=this;if(usingBundle&&sdpMLineIndex>0){return this.transceivers[0].iceGatherer;}else if(this._iceGatherers.length){return this._iceGatherers.shift();}
+var iceGatherer=new window.RTCIceGatherer({iceServers:this._config.iceServers,gatherPolicy:this._config.iceTransportPolicy});Object.defineProperty(iceGatherer,'state',{value:'new',writable:true});this.transceivers[sdpMLineIndex].bufferedCandidateEvents=[];this.transceivers[sdpMLineIndex].bufferCandidates=function(event){var end=!event.candidate||Object.keys(event.candidate).length===0;iceGatherer.state=end?'completed':'gathering';if(pc.transceivers[sdpMLineIndex].bufferedCandidateEvents!==null){pc.transceivers[sdpMLineIndex].bufferedCandidateEvents.push(event);}};iceGatherer.addEventListener('localcandidate',this.transceivers[sdpMLineIndex].bufferCandidates);return iceGatherer;};RTCPeerConnection.prototype._gather=function(mid,sdpMLineIndex){var pc=this;var iceGatherer=this.transceivers[sdpMLineIndex].iceGatherer;if(iceGatherer.onlocalcandidate){return;}
+var bufferedCandidateEvents=this.transceivers[sdpMLineIndex].bufferedCandidateEvents;this.transceivers[sdpMLineIndex].bufferedCandidateEvents=null;iceGatherer.removeEventListener('localcandidate',this.transceivers[sdpMLineIndex].bufferCandidates);iceGatherer.onlocalcandidate=function(evt){if(pc.usingBundle&&sdpMLineIndex>0){return;}
+var event=new Event('icecandidate');event.candidate={sdpMid:mid,sdpMLineIndex:sdpMLineIndex};var cand=evt.candidate;var end=!cand||Object.keys(cand).length===0;if(end){if(iceGatherer.state==='new'||iceGatherer.state==='gathering'){iceGatherer.state='completed';}}else{if(iceGatherer.state==='new'){iceGatherer.state='gathering';}
+cand.component=1;cand.ufrag=iceGatherer.getLocalParameters().usernameFragment;var serializedCandidate=SDPUtils.writeCandidate(cand);event.candidate=Object.assign(event.candidate,SDPUtils.parseCandidate(serializedCandidate));event.candidate.candidate=serializedCandidate;event.candidate.toJSON=function(){return{candidate:event.candidate.candidate,sdpMid:event.candidate.sdpMid,sdpMLineIndex:event.candidate.sdpMLineIndex,usernameFragment:event.candidate.usernameFragment};};}
+var sections=SDPUtils.getMediaSections(pc._localDescription.sdp);if(!end){sections[event.candidate.sdpMLineIndex]+='a='+event.candidate.candidate+'\r\n';}else{sections[event.candidate.sdpMLineIndex]+='a=end-of-candidates\r\n';}
+pc._localDescription.sdp=SDPUtils.getDescription(pc._localDescription.sdp)+
+sections.join('');var complete=pc.transceivers.every(function(transceiver){return transceiver.iceGatherer&&transceiver.iceGatherer.state==='completed';});if(pc.iceGatheringState!=='gathering'){pc.iceGatheringState='gathering';pc._emitGatheringStateChange();}
+if(!end){pc._dispatchEvent('icecandidate',event);}
+if(complete){pc._dispatchEvent('icecandidate',new Event('icecandidate'));pc.iceGatheringState='complete';pc._emitGatheringStateChange();}};window.setTimeout(function(){bufferedCandidateEvents.forEach(function(e){iceGatherer.onlocalcandidate(e);});},0);};RTCPeerConnection.prototype._createIceAndDtlsTransports=function(){var pc=this;var iceTransport=new window.RTCIceTransport(null);iceTransport.onicestatechange=function(){pc._updateIceConnectionState();pc._updateConnectionState();};var dtlsTransport=new window.RTCDtlsTransport(iceTransport);dtlsTransport.ondtlsstatechange=function(){pc._updateConnectionState();};dtlsTransport.onerror=function(){Object.defineProperty(dtlsTransport,'state',{value:'failed',writable:true});pc._updateConnectionState();};return{iceTransport:iceTransport,dtlsTransport:dtlsTransport};};RTCPeerConnection.prototype._disposeIceAndDtlsTransports=function(sdpMLineIndex){var iceGatherer=this.transceivers[sdpMLineIndex].iceGatherer;if(iceGatherer){delete iceGatherer.onlocalcandidate;delete this.transceivers[sdpMLineIndex].iceGatherer;}
+var iceTransport=this.transceivers[sdpMLineIndex].iceTransport;if(iceTransport){delete iceTransport.onicestatechange;delete this.transceivers[sdpMLineIndex].iceTransport;}
+var dtlsTransport=this.transceivers[sdpMLineIndex].dtlsTransport;if(dtlsTransport){delete dtlsTransport.ondtlsstatechange;delete dtlsTransport.onerror;delete this.transceivers[sdpMLineIndex].dtlsTransport;}};RTCPeerConnection.prototype._transceive=function(transceiver,send,recv){var params=getCommonCapabilities(transceiver.localCapabilities,transceiver.remoteCapabilities);if(send&&transceiver.rtpSender){params.encodings=transceiver.sendEncodingParameters;params.rtcp={cname:SDPUtils.localCName,compound:transceiver.rtcpParameters.compound};if(transceiver.recvEncodingParameters.length){params.rtcp.ssrc=transceiver.recvEncodingParameters[0].ssrc;}
+transceiver.rtpSender.send(params);}
+if(recv&&transceiver.rtpReceiver&¶ms.codecs.length>0){if(transceiver.kind==='video'&&transceiver.recvEncodingParameters&&edgeVersion<15019){transceiver.recvEncodingParameters.forEach(function(p){delete p.rtx;});}
+if(transceiver.recvEncodingParameters.length){params.encodings=transceiver.recvEncodingParameters;}else{params.encodings=[{}];}
+params.rtcp={compound:transceiver.rtcpParameters.compound};if(transceiver.rtcpParameters.cname){params.rtcp.cname=transceiver.rtcpParameters.cname;}
+if(transceiver.sendEncodingParameters.length){params.rtcp.ssrc=transceiver.sendEncodingParameters[0].ssrc;}
+transceiver.rtpReceiver.receive(params);}};RTCPeerConnection.prototype.setLocalDescription=function(description){var pc=this;if(['offer','answer'].indexOf(description.type)===-1){return Promise.reject(makeError('TypeError','Unsupported type "'+description.type+'"'));}
+if(!isActionAllowedInSignalingState('setLocalDescription',description.type,pc.signalingState)||pc._isClosed){return Promise.reject(makeError('InvalidStateError','Can not set local '+description.type+' in state '+pc.signalingState));}
+var sections;var sessionpart;if(description.type==='offer'){sections=SDPUtils.splitSections(description.sdp);sessionpart=sections.shift();sections.forEach(function(mediaSection,sdpMLineIndex){var caps=SDPUtils.parseRtpParameters(mediaSection);pc.transceivers[sdpMLineIndex].localCapabilities=caps;});pc.transceivers.forEach(function(transceiver,sdpMLineIndex){pc._gather(transceiver.mid,sdpMLineIndex);});}else if(description.type==='answer'){sections=SDPUtils.splitSections(pc._remoteDescription.sdp);sessionpart=sections.shift();var isIceLite=SDPUtils.matchPrefix(sessionpart,'a=ice-lite').length>0;sections.forEach(function(mediaSection,sdpMLineIndex){var transceiver=pc.transceivers[sdpMLineIndex];var iceGatherer=transceiver.iceGatherer;var iceTransport=transceiver.iceTransport;var dtlsTransport=transceiver.dtlsTransport;var localCapabilities=transceiver.localCapabilities;var remoteCapabilities=transceiver.remoteCapabilities;var rejected=SDPUtils.isRejected(mediaSection)&&SDPUtils.matchPrefix(mediaSection,'a=bundle-only').length===0;if(!rejected&&!transceiver.rejected){var remoteIceParameters=SDPUtils.getIceParameters(mediaSection,sessionpart);var remoteDtlsParameters=SDPUtils.getDtlsParameters(mediaSection,sessionpart);if(isIceLite){remoteDtlsParameters.role='server';}
+if(!pc.usingBundle||sdpMLineIndex===0){pc._gather(transceiver.mid,sdpMLineIndex);if(iceTransport.state==='new'){iceTransport.start(iceGatherer,remoteIceParameters,isIceLite?'controlling':'controlled');}
+if(dtlsTransport.state==='new'){dtlsTransport.start(remoteDtlsParameters);}}
+var params=getCommonCapabilities(localCapabilities,remoteCapabilities);pc._transceive(transceiver,params.codecs.length>0,false);}});}
+pc._localDescription={type:description.type,sdp:description.sdp};if(description.type==='offer'){pc._updateSignalingState('have-local-offer');}else{pc._updateSignalingState('stable');}
+return Promise.resolve();};RTCPeerConnection.prototype.setRemoteDescription=function(description){var pc=this;if(['offer','answer'].indexOf(description.type)===-1){return Promise.reject(makeError('TypeError','Unsupported type "'+description.type+'"'));}
+if(!isActionAllowedInSignalingState('setRemoteDescription',description.type,pc.signalingState)||pc._isClosed){return Promise.reject(makeError('InvalidStateError','Can not set remote '+description.type+' in state '+pc.signalingState));}
+var streams={};pc.remoteStreams.forEach(function(stream){streams[stream.id]=stream;});var receiverList=[];var sections=SDPUtils.splitSections(description.sdp);var sessionpart=sections.shift();var isIceLite=SDPUtils.matchPrefix(sessionpart,'a=ice-lite').length>0;var usingBundle=SDPUtils.matchPrefix(sessionpart,'a=group:BUNDLE ').length>0;pc.usingBundle=usingBundle;var iceOptions=SDPUtils.matchPrefix(sessionpart,'a=ice-options:')[0];if(iceOptions){pc.canTrickleIceCandidates=iceOptions.substr(14).split(' ').indexOf('trickle')>=0;}else{pc.canTrickleIceCandidates=false;}
+sections.forEach(function(mediaSection,sdpMLineIndex){var lines=SDPUtils.splitLines(mediaSection);var kind=SDPUtils.getKind(mediaSection);var rejected=SDPUtils.isRejected(mediaSection)&&SDPUtils.matchPrefix(mediaSection,'a=bundle-only').length===0;var protocol=lines[0].substr(2).split(' ')[2];var direction=SDPUtils.getDirection(mediaSection,sessionpart);var remoteMsid=SDPUtils.parseMsid(mediaSection);var mid=SDPUtils.getMid(mediaSection)||SDPUtils.generateIdentifier();if(rejected||(kind==='application'&&(protocol==='DTLS/SCTP'||protocol==='UDP/DTLS/SCTP'))){pc.transceivers[sdpMLineIndex]={mid:mid,kind:kind,protocol:protocol,rejected:true};return;}
+if(!rejected&&pc.transceivers[sdpMLineIndex]&&pc.transceivers[sdpMLineIndex].rejected){pc.transceivers[sdpMLineIndex]=pc._createTransceiver(kind,true);}
+var transceiver;var iceGatherer;var iceTransport;var dtlsTransport;var rtpReceiver;var sendEncodingParameters;var recvEncodingParameters;var localCapabilities;var track;var remoteCapabilities=SDPUtils.parseRtpParameters(mediaSection);var remoteIceParameters;var remoteDtlsParameters;if(!rejected){remoteIceParameters=SDPUtils.getIceParameters(mediaSection,sessionpart);remoteDtlsParameters=SDPUtils.getDtlsParameters(mediaSection,sessionpart);remoteDtlsParameters.role='client';}
+recvEncodingParameters=SDPUtils.parseRtpEncodingParameters(mediaSection);var rtcpParameters=SDPUtils.parseRtcpParameters(mediaSection);var isComplete=SDPUtils.matchPrefix(mediaSection,'a=end-of-candidates',sessionpart).length>0;var cands=SDPUtils.matchPrefix(mediaSection,'a=candidate:').map(function(cand){return SDPUtils.parseCandidate(cand);}).filter(function(cand){return cand.component===1;});if((description.type==='offer'||description.type==='answer')&&!rejected&&usingBundle&&sdpMLineIndex>0&&pc.transceivers[sdpMLineIndex]){pc._disposeIceAndDtlsTransports(sdpMLineIndex);pc.transceivers[sdpMLineIndex].iceGatherer=pc.transceivers[0].iceGatherer;pc.transceivers[sdpMLineIndex].iceTransport=pc.transceivers[0].iceTransport;pc.transceivers[sdpMLineIndex].dtlsTransport=pc.transceivers[0].dtlsTransport;if(pc.transceivers[sdpMLineIndex].rtpSender){pc.transceivers[sdpMLineIndex].rtpSender.setTransport(pc.transceivers[0].dtlsTransport);}
+if(pc.transceivers[sdpMLineIndex].rtpReceiver){pc.transceivers[sdpMLineIndex].rtpReceiver.setTransport(pc.transceivers[0].dtlsTransport);}}
+if(description.type==='offer'&&!rejected){transceiver=pc.transceivers[sdpMLineIndex]||pc._createTransceiver(kind);transceiver.mid=mid;if(!transceiver.iceGatherer){transceiver.iceGatherer=pc._createIceGatherer(sdpMLineIndex,usingBundle);}
+if(cands.length&&transceiver.iceTransport.state==='new'){if(isComplete&&(!usingBundle||sdpMLineIndex===0)){transceiver.iceTransport.setRemoteCandidates(cands);}else{cands.forEach(function(candidate){maybeAddCandidate(transceiver.iceTransport,candidate);});}}
+localCapabilities=window.RTCRtpReceiver.getCapabilities(kind);if(edgeVersion<15019){localCapabilities.codecs=localCapabilities.codecs.filter(function(codec){return codec.name!=='rtx';});}
+sendEncodingParameters=transceiver.sendEncodingParameters||[{ssrc:(2*sdpMLineIndex+2)*1001}];var isNewTrack=false;if(direction==='sendrecv'||direction==='sendonly'){isNewTrack=!transceiver.rtpReceiver;rtpReceiver=transceiver.rtpReceiver||new window.RTCRtpReceiver(transceiver.dtlsTransport,kind);if(isNewTrack){var stream;track=rtpReceiver.track;if(remoteMsid&&remoteMsid.stream==='-'){}else if(remoteMsid){if(!streams[remoteMsid.stream]){streams[remoteMsid.stream]=new window.MediaStream();Object.defineProperty(streams[remoteMsid.stream],'id',{get:function(){return remoteMsid.stream;}});}
+Object.defineProperty(track,'id',{get:function(){return remoteMsid.track;}});stream=streams[remoteMsid.stream];}else{if(!streams.default){streams.default=new window.MediaStream();}
+stream=streams.default;}
+if(stream){addTrackToStreamAndFireEvent(track,stream);transceiver.associatedRemoteMediaStreams.push(stream);}
+receiverList.push([track,rtpReceiver,stream]);}}else if(transceiver.rtpReceiver&&transceiver.rtpReceiver.track){transceiver.associatedRemoteMediaStreams.forEach(function(s){var nativeTrack=s.getTracks().find(function(t){return t.id===transceiver.rtpReceiver.track.id;});if(nativeTrack){removeTrackFromStreamAndFireEvent(nativeTrack,s);}});transceiver.associatedRemoteMediaStreams=[];}
+transceiver.localCapabilities=localCapabilities;transceiver.remoteCapabilities=remoteCapabilities;transceiver.rtpReceiver=rtpReceiver;transceiver.rtcpParameters=rtcpParameters;transceiver.sendEncodingParameters=sendEncodingParameters;transceiver.recvEncodingParameters=recvEncodingParameters;pc._transceive(pc.transceivers[sdpMLineIndex],false,isNewTrack);}else if(description.type==='answer'&&!rejected){transceiver=pc.transceivers[sdpMLineIndex];iceGatherer=transceiver.iceGatherer;iceTransport=transceiver.iceTransport;dtlsTransport=transceiver.dtlsTransport;rtpReceiver=transceiver.rtpReceiver;sendEncodingParameters=transceiver.sendEncodingParameters;localCapabilities=transceiver.localCapabilities;pc.transceivers[sdpMLineIndex].recvEncodingParameters=recvEncodingParameters;pc.transceivers[sdpMLineIndex].remoteCapabilities=remoteCapabilities;pc.transceivers[sdpMLineIndex].rtcpParameters=rtcpParameters;if(cands.length&&iceTransport.state==='new'){if((isIceLite||isComplete)&&(!usingBundle||sdpMLineIndex===0)){iceTransport.setRemoteCandidates(cands);}else{cands.forEach(function(candidate){maybeAddCandidate(transceiver.iceTransport,candidate);});}}
+if(!usingBundle||sdpMLineIndex===0){if(iceTransport.state==='new'){iceTransport.start(iceGatherer,remoteIceParameters,'controlling');}
+if(dtlsTransport.state==='new'){dtlsTransport.start(remoteDtlsParameters);}}
+var commonCapabilities=getCommonCapabilities(transceiver.localCapabilities,transceiver.remoteCapabilities);var hasRtx=commonCapabilities.codecs.filter(function(c){return c.name.toLowerCase()==='rtx';}).length;if(!hasRtx&&transceiver.sendEncodingParameters[0].rtx){delete transceiver.sendEncodingParameters[0].rtx;}
+pc._transceive(transceiver,direction==='sendrecv'||direction==='recvonly',direction==='sendrecv'||direction==='sendonly');if(rtpReceiver&&(direction==='sendrecv'||direction==='sendonly')){track=rtpReceiver.track;if(remoteMsid){if(!streams[remoteMsid.stream]){streams[remoteMsid.stream]=new window.MediaStream();}
+addTrackToStreamAndFireEvent(track,streams[remoteMsid.stream]);receiverList.push([track,rtpReceiver,streams[remoteMsid.stream]]);}else{if(!streams.default){streams.default=new window.MediaStream();}
+addTrackToStreamAndFireEvent(track,streams.default);receiverList.push([track,rtpReceiver,streams.default]);}}else{delete transceiver.rtpReceiver;}}});if(pc._dtlsRole===undefined){pc._dtlsRole=description.type==='offer'?'active':'passive';}
+pc._remoteDescription={type:description.type,sdp:description.sdp};if(description.type==='offer'){pc._updateSignalingState('have-remote-offer');}else{pc._updateSignalingState('stable');}
+Object.keys(streams).forEach(function(sid){var stream=streams[sid];if(stream.getTracks().length){if(pc.remoteStreams.indexOf(stream)===-1){pc.remoteStreams.push(stream);var event=new Event('addstream');event.stream=stream;window.setTimeout(function(){pc._dispatchEvent('addstream',event);});}
+receiverList.forEach(function(item){var track=item[0];var receiver=item[1];if(stream.id!==item[2].id){return;}
+fireAddTrack(pc,track,receiver,[stream]);});}});receiverList.forEach(function(item){if(item[2]){return;}
+fireAddTrack(pc,item[0],item[1],[]);});window.setTimeout(function(){if(!(pc&&pc.transceivers)){return;}
+pc.transceivers.forEach(function(transceiver){if(transceiver.iceTransport&&transceiver.iceTransport.state==='new'&&transceiver.iceTransport.getRemoteCandidates().length>0){console.warn('Timeout for addRemoteCandidate. Consider sending '+'an end-of-candidates notification');transceiver.iceTransport.addRemoteCandidate({});}});},4000);return Promise.resolve();};RTCPeerConnection.prototype.close=function(){this.transceivers.forEach(function(transceiver){if(transceiver.iceTransport){transceiver.iceTransport.stop();}
+if(transceiver.dtlsTransport){transceiver.dtlsTransport.stop();}
+if(transceiver.rtpSender){transceiver.rtpSender.stop();}
+if(transceiver.rtpReceiver){transceiver.rtpReceiver.stop();}});this._isClosed=true;this._updateSignalingState('closed');};RTCPeerConnection.prototype._updateSignalingState=function(newState){this.signalingState=newState;var event=new Event('signalingstatechange');this._dispatchEvent('signalingstatechange',event);};RTCPeerConnection.prototype._maybeFireNegotiationNeeded=function(){var pc=this;if(this.signalingState!=='stable'||this.needNegotiation===true){return;}
+this.needNegotiation=true;window.setTimeout(function(){if(pc.needNegotiation){pc.needNegotiation=false;var event=new Event('negotiationneeded');pc._dispatchEvent('negotiationneeded',event);}},0);};RTCPeerConnection.prototype._updateIceConnectionState=function(){var newState;var states={'new':0,closed:0,checking:0,connected:0,completed:0,disconnected:0,failed:0};this.transceivers.forEach(function(transceiver){if(transceiver.iceTransport&&!transceiver.rejected){states[transceiver.iceTransport.state]++;}});newState='new';if(states.failed>0){newState='failed';}else if(states.checking>0){newState='checking';}else if(states.disconnected>0){newState='disconnected';}else if(states.new>0){newState='new';}else if(states.connected>0){newState='connected';}else if(states.completed>0){newState='completed';}
+if(newState!==this.iceConnectionState){this.iceConnectionState=newState;var event=new Event('iceconnectionstatechange');this._dispatchEvent('iceconnectionstatechange',event);}};RTCPeerConnection.prototype._updateConnectionState=function(){var newState;var states={'new':0,closed:0,connecting:0,connected:0,completed:0,disconnected:0,failed:0};this.transceivers.forEach(function(transceiver){if(transceiver.iceTransport&&transceiver.dtlsTransport&&!transceiver.rejected){states[transceiver.iceTransport.state]++;states[transceiver.dtlsTransport.state]++;}});states.connected+=states.completed;newState='new';if(states.failed>0){newState='failed';}else if(states.connecting>0){newState='connecting';}else if(states.disconnected>0){newState='disconnected';}else if(states.new>0){newState='new';}else if(states.connected>0){newState='connected';}
+if(newState!==this.connectionState){this.connectionState=newState;var event=new Event('connectionstatechange');this._dispatchEvent('connectionstatechange',event);}};RTCPeerConnection.prototype.createOffer=function(){var pc=this;if(pc._isClosed){return Promise.reject(makeError('InvalidStateError','Can not call createOffer after close'));}
+var numAudioTracks=pc.transceivers.filter(function(t){return t.kind==='audio';}).length;var numVideoTracks=pc.transceivers.filter(function(t){return t.kind==='video';}).length;var offerOptions=arguments[0];if(offerOptions){if(offerOptions.mandatory||offerOptions.optional){throw new TypeError('Legacy mandatory/optional constraints not supported.');}
+if(offerOptions.offerToReceiveAudio!==undefined){if(offerOptions.offerToReceiveAudio===true){numAudioTracks=1;}else if(offerOptions.offerToReceiveAudio===false){numAudioTracks=0;}else{numAudioTracks=offerOptions.offerToReceiveAudio;}}
+if(offerOptions.offerToReceiveVideo!==undefined){if(offerOptions.offerToReceiveVideo===true){numVideoTracks=1;}else if(offerOptions.offerToReceiveVideo===false){numVideoTracks=0;}else{numVideoTracks=offerOptions.offerToReceiveVideo;}}}
+pc.transceivers.forEach(function(transceiver){if(transceiver.kind==='audio'){numAudioTracks--;if(numAudioTracks<0){transceiver.wantReceive=false;}}else if(transceiver.kind==='video'){numVideoTracks--;if(numVideoTracks<0){transceiver.wantReceive=false;}}});while(numAudioTracks>0||numVideoTracks>0){if(numAudioTracks>0){pc._createTransceiver('audio');numAudioTracks--;}
+if(numVideoTracks>0){pc._createTransceiver('video');numVideoTracks--;}}
+var sdp=SDPUtils.writeSessionBoilerplate(pc._sdpSessionId,pc._sdpSessionVersion++);pc.transceivers.forEach(function(transceiver,sdpMLineIndex){var track=transceiver.track;var kind=transceiver.kind;var mid=transceiver.mid||SDPUtils.generateIdentifier();transceiver.mid=mid;if(!transceiver.iceGatherer){transceiver.iceGatherer=pc._createIceGatherer(sdpMLineIndex,pc.usingBundle);}
+var localCapabilities=window.RTCRtpSender.getCapabilities(kind);if(edgeVersion<15019){localCapabilities.codecs=localCapabilities.codecs.filter(function(codec){return codec.name!=='rtx';});}
+localCapabilities.codecs.forEach(function(codec){if(codec.name==='H264'&&codec.parameters['level-asymmetry-allowed']===undefined){codec.parameters['level-asymmetry-allowed']='1';}
+if(transceiver.remoteCapabilities&&transceiver.remoteCapabilities.codecs){transceiver.remoteCapabilities.codecs.forEach(function(remoteCodec){if(codec.name.toLowerCase()===remoteCodec.name.toLowerCase()&&codec.clockRate===remoteCodec.clockRate){codec.preferredPayloadType=remoteCodec.payloadType;}});}});localCapabilities.headerExtensions.forEach(function(hdrExt){var remoteExtensions=transceiver.remoteCapabilities&&transceiver.remoteCapabilities.headerExtensions||[];remoteExtensions.forEach(function(rHdrExt){if(hdrExt.uri===rHdrExt.uri){hdrExt.id=rHdrExt.id;}});});var sendEncodingParameters=transceiver.sendEncodingParameters||[{ssrc:(2*sdpMLineIndex+1)*1001}];if(track){if(edgeVersion>=15019&&kind==='video'&&!sendEncodingParameters[0].rtx){sendEncodingParameters[0].rtx={ssrc:sendEncodingParameters[0].ssrc+1};}}
+if(transceiver.wantReceive){transceiver.rtpReceiver=new window.RTCRtpReceiver(transceiver.dtlsTransport,kind);}
+transceiver.localCapabilities=localCapabilities;transceiver.sendEncodingParameters=sendEncodingParameters;});if(pc._config.bundlePolicy!=='max-compat'){sdp+='a=group:BUNDLE '+pc.transceivers.map(function(t){return t.mid;}).join(' ')+'\r\n';}
+sdp+='a=ice-options:trickle\r\n';pc.transceivers.forEach(function(transceiver,sdpMLineIndex){sdp+=writeMediaSection(transceiver,transceiver.localCapabilities,'offer',transceiver.stream,pc._dtlsRole);sdp+='a=rtcp-rsize\r\n';if(transceiver.iceGatherer&&pc.iceGatheringState!=='new'&&(sdpMLineIndex===0||!pc.usingBundle)){transceiver.iceGatherer.getLocalCandidates().forEach(function(cand){cand.component=1;sdp+='a='+SDPUtils.writeCandidate(cand)+'\r\n';});if(transceiver.iceGatherer.state==='completed'){sdp+='a=end-of-candidates\r\n';}}});var desc=new window.RTCSessionDescription({type:'offer',sdp:sdp});return Promise.resolve(desc);};RTCPeerConnection.prototype.createAnswer=function(){var pc=this;if(pc._isClosed){return Promise.reject(makeError('InvalidStateError','Can not call createAnswer after close'));}
+if(!(pc.signalingState==='have-remote-offer'||pc.signalingState==='have-local-pranswer')){return Promise.reject(makeError('InvalidStateError','Can not call createAnswer in signalingState '+pc.signalingState));}
+var sdp=SDPUtils.writeSessionBoilerplate(pc._sdpSessionId,pc._sdpSessionVersion++);if(pc.usingBundle){sdp+='a=group:BUNDLE '+pc.transceivers.map(function(t){return t.mid;}).join(' ')+'\r\n';}
+sdp+='a=ice-options:trickle\r\n';var mediaSectionsInOffer=SDPUtils.getMediaSections(pc._remoteDescription.sdp).length;pc.transceivers.forEach(function(transceiver,sdpMLineIndex){if(sdpMLineIndex+1>mediaSectionsInOffer){return;}
+if(transceiver.rejected){if(transceiver.kind==='application'){if(transceiver.protocol==='DTLS/SCTP'){sdp+='m=application 0 DTLS/SCTP 5000\r\n';}else{sdp+='m=application 0 '+transceiver.protocol+' webrtc-datachannel\r\n';}}else if(transceiver.kind==='audio'){sdp+='m=audio 0 UDP/TLS/RTP/SAVPF 0\r\n'+'a=rtpmap:0 PCMU/8000\r\n';}else if(transceiver.kind==='video'){sdp+='m=video 0 UDP/TLS/RTP/SAVPF 120\r\n'+'a=rtpmap:120 VP8/90000\r\n';}
+sdp+='c=IN IP4 0.0.0.0\r\n'+'a=inactive\r\n'+'a=mid:'+transceiver.mid+'\r\n';return;}
+if(transceiver.stream){var localTrack;if(transceiver.kind==='audio'){localTrack=transceiver.stream.getAudioTracks()[0];}else if(transceiver.kind==='video'){localTrack=transceiver.stream.getVideoTracks()[0];}
+if(localTrack){if(edgeVersion>=15019&&transceiver.kind==='video'&&!transceiver.sendEncodingParameters[0].rtx){transceiver.sendEncodingParameters[0].rtx={ssrc:transceiver.sendEncodingParameters[0].ssrc+1};}}}
+var commonCapabilities=getCommonCapabilities(transceiver.localCapabilities,transceiver.remoteCapabilities);var hasRtx=commonCapabilities.codecs.filter(function(c){return c.name.toLowerCase()==='rtx';}).length;if(!hasRtx&&transceiver.sendEncodingParameters[0].rtx){delete transceiver.sendEncodingParameters[0].rtx;}
+sdp+=writeMediaSection(transceiver,commonCapabilities,'answer',transceiver.stream,pc._dtlsRole);if(transceiver.rtcpParameters&&transceiver.rtcpParameters.reducedSize){sdp+='a=rtcp-rsize\r\n';}});var desc=new window.RTCSessionDescription({type:'answer',sdp:sdp});return Promise.resolve(desc);};RTCPeerConnection.prototype.addIceCandidate=function(candidate){var pc=this;var sections;if(candidate&&!(candidate.sdpMLineIndex!==undefined||candidate.sdpMid)){return Promise.reject(new TypeError('sdpMLineIndex or sdpMid required'));}
+return new Promise(function(resolve,reject){if(!pc._remoteDescription){return reject(makeError('InvalidStateError','Can not add ICE candidate without a remote description'));}else if(!candidate||candidate.candidate===''){for(var j=0;j0?SDPUtils.parseCandidate(candidate.candidate):{};if(cand.protocol==='tcp'&&(cand.port===0||cand.port===9)){return resolve();}
+if(cand.component&&cand.component!==1){return resolve();}
+if(sdpMLineIndex===0||(sdpMLineIndex>0&&transceiver.iceTransport!==pc.transceivers[0].iceTransport)){if(!maybeAddCandidate(transceiver.iceTransport,cand)){return reject(makeError('OperationError','Can not add ICE candidate'));}}
+var candidateString=candidate.candidate.trim();if(candidateString.indexOf('a=')===0){candidateString=candidateString.substr(2);}
+sections=SDPUtils.getMediaSections(pc._remoteDescription.sdp);sections[sdpMLineIndex]+='a='+
+(cand.type?candidateString:'end-of-candidates')
++'\r\n';pc._remoteDescription.sdp=SDPUtils.getDescription(pc._remoteDescription.sdp)+
+sections.join('');}else{return reject(makeError('OperationError','Can not add ICE candidate'));}}
+resolve();});};RTCPeerConnection.prototype.getStats=function(selector){if(selector&&selector instanceof window.MediaStreamTrack){var senderOrReceiver=null;this.transceivers.forEach(function(transceiver){if(transceiver.rtpSender&&transceiver.rtpSender.track===selector){senderOrReceiver=transceiver.rtpSender;}else if(transceiver.rtpReceiver&&transceiver.rtpReceiver.track===selector){senderOrReceiver=transceiver.rtpReceiver;}});if(!senderOrReceiver){throw makeError('InvalidAccessError','Invalid selector.');}
+return senderOrReceiver.getStats();}
+var promises=[];this.transceivers.forEach(function(transceiver){['rtpSender','rtpReceiver','iceGatherer','iceTransport','dtlsTransport'].forEach(function(method){if(transceiver[method]){promises.push(transceiver[method].getStats());}});});return Promise.all(promises).then(function(allStats){var results=new Map();allStats.forEach(function(stats){stats.forEach(function(stat){results.set(stat.id,stat);});});return results;});};var ortcObjects=['RTCRtpSender','RTCRtpReceiver','RTCIceGatherer','RTCIceTransport','RTCDtlsTransport'];ortcObjects.forEach(function(ortcObjectName){var obj=window[ortcObjectName];if(obj&&obj.prototype&&obj.prototype.getStats){var nativeGetstats=obj.prototype.getStats;obj.prototype.getStats=function(){return nativeGetstats.apply(this).then(function(nativeStats){var mapStats=new Map();Object.keys(nativeStats).forEach(function(id){nativeStats[id].type=fixStatsType(nativeStats[id]);mapStats.set(id,nativeStats[id]);});return mapStats;});};}});var methods=['createOffer','createAnswer'];methods.forEach(function(method){var nativeMethod=RTCPeerConnection.prototype[method];RTCPeerConnection.prototype[method]=function(){var args=arguments;if(typeof args[0]==='function'||typeof args[1]==='function'){return nativeMethod.apply(this,[arguments[2]]).then(function(description){if(typeof args[0]==='function'){args[0].apply(null,[description]);}},function(error){if(typeof args[1]==='function'){args[1].apply(null,[error]);}});}
+return nativeMethod.apply(this,arguments);};});methods=['setLocalDescription','setRemoteDescription','addIceCandidate'];methods.forEach(function(method){var nativeMethod=RTCPeerConnection.prototype[method];RTCPeerConnection.prototype[method]=function(){var args=arguments;if(typeof args[1]==='function'||typeof args[2]==='function'){return nativeMethod.apply(this,arguments).then(function(){if(typeof args[1]==='function'){args[1].apply(null);}},function(error){if(typeof args[2]==='function'){args[2].apply(null,[error]);}});}
+return nativeMethod.apply(this,arguments);};});['getStats'].forEach(function(method){var nativeMethod=RTCPeerConnection.prototype[method];RTCPeerConnection.prototype[method]=function(){var args=arguments;if(typeof args[1]==='function'){return nativeMethod.apply(this,arguments).then(function(){if(typeof args[1]==='function'){args[1].apply(null);}});}
+return nativeMethod.apply(this,arguments);};});return RTCPeerConnection;};},{"sdp":17}],17:[function(require,module,exports){'use strict';var SDPUtils={};SDPUtils.generateIdentifier=function(){return Math.random().toString(36).substr(2,10);};SDPUtils.localCName=SDPUtils.generateIdentifier();SDPUtils.splitLines=function(blob){return blob.trim().split('\n').map(function(line){return line.trim();});};SDPUtils.splitSections=function(blob){var parts=blob.split('\nm=');return parts.map(function(part,index){return(index>0?'m='+part:part).trim()+'\r\n';});};SDPUtils.getDescription=function(blob){var sections=SDPUtils.splitSections(blob);return sections&§ions[0];};SDPUtils.getMediaSections=function(blob){var sections=SDPUtils.splitSections(blob);sections.shift();return sections;};SDPUtils.matchPrefix=function(blob,prefix){return SDPUtils.splitLines(blob).filter(function(line){return line.indexOf(prefix)===0;});};SDPUtils.parseCandidate=function(line){var parts;if(line.indexOf('a=candidate:')===0){parts=line.substring(12).split(' ');}else{parts=line.substring(10).split(' ');}
+var candidate={foundation:parts[0],component:parseInt(parts[1],10),protocol:parts[2].toLowerCase(),priority:parseInt(parts[3],10),ip:parts[4],address:parts[4],port:parseInt(parts[5],10),type:parts[7]};for(var i=8;i0?parts[0].split('/')[1]:'sendrecv',uri:parts[1]};};SDPUtils.writeExtmap=function(headerExtension){return'a=extmap:'+(headerExtension.id||headerExtension.preferredId)+
+(headerExtension.direction&&headerExtension.direction!=='sendrecv'?'/'+headerExtension.direction:'')+' '+headerExtension.uri+'\r\n';};SDPUtils.parseFmtp=function(line){var parsed={};var kv;var parts=line.substr(line.indexOf(' ')+1).split(';');for(var j=0;j-1){parts.attribute=line.substr(sp+1,colon-sp-1);parts.value=line.substr(colon+1);}else{parts.attribute=line.substr(sp+1);}
+return parts;};SDPUtils.parseSsrcGroup=function(line){var parts=line.substr(13).split(' ');return{semantics:parts.shift(),ssrcs:parts.map(function(ssrc){return parseInt(ssrc,10);})};};SDPUtils.getMid=function(mediaSection){var mid=SDPUtils.matchPrefix(mediaSection,'a=mid:')[0];if(mid){return mid.substr(6);}};SDPUtils.parseFingerprint=function(line){var parts=line.substr(14).split(' ');return{algorithm:parts[0].toLowerCase(),value:parts[1]};};SDPUtils.getDtlsParameters=function(mediaSection,sessionpart){var lines=SDPUtils.matchPrefix(mediaSection+sessionpart,'a=fingerprint:');return{role:'auto',fingerprints:lines.map(SDPUtils.parseFingerprint)};};SDPUtils.writeDtlsParameters=function(params,setupType){var sdp='a=setup:'+setupType+'\r\n';params.fingerprints.forEach(function(fp){sdp+='a=fingerprint:'+fp.algorithm+' '+fp.value+'\r\n';});return sdp;};SDPUtils.getIceParameters=function(mediaSection,sessionpart){var lines=SDPUtils.splitLines(mediaSection);lines=lines.concat(SDPUtils.splitLines(sessionpart));var iceParameters={usernameFragment:lines.filter(function(line){return line.indexOf('a=ice-ufrag:')===0;})[0].substr(12),password:lines.filter(function(line){return line.indexOf('a=ice-pwd:')===0;})[0].substr(10)};return iceParameters;};SDPUtils.writeIceParameters=function(params){return'a=ice-ufrag:'+params.usernameFragment+'\r\n'+'a=ice-pwd:'+params.password+'\r\n';};SDPUtils.parseRtpParameters=function(mediaSection){var description={codecs:[],headerExtensions:[],fecMechanisms:[],rtcp:[]};var lines=SDPUtils.splitLines(mediaSection);var mline=lines[0].split(' ');for(var i=3;i0?'9':'0';sdp+=' UDP/TLS/RTP/SAVPF ';sdp+=caps.codecs.map(function(codec){if(codec.preferredPayloadType!==undefined){return codec.preferredPayloadType;}
+return codec.payloadType;}).join(' ')+'\r\n';sdp+='c=IN IP4 0.0.0.0\r\n';sdp+='a=rtcp:9 IN IP4 0.0.0.0\r\n';caps.codecs.forEach(function(codec){sdp+=SDPUtils.writeRtpMap(codec);sdp+=SDPUtils.writeFmtp(codec);sdp+=SDPUtils.writeRtcpFb(codec);});var maxptime=0;caps.codecs.forEach(function(codec){if(codec.maxptime>maxptime){maxptime=codec.maxptime;}});if(maxptime>0){sdp+='a=maxptime:'+maxptime+'\r\n';}
+sdp+='a=rtcp-mux\r\n';if(caps.headerExtensions){caps.headerExtensions.forEach(function(extension){sdp+=SDPUtils.writeExtmap(extension);});}
+return sdp;};SDPUtils.parseRtpEncodingParameters=function(mediaSection){var encodingParameters=[];var description=SDPUtils.parseRtpParameters(mediaSection);var hasRed=description.fecMechanisms.indexOf('RED')!==-1;var hasUlpfec=description.fecMechanisms.indexOf('ULPFEC')!==-1;var ssrcs=SDPUtils.matchPrefix(mediaSection,'a=ssrc:').map(function(line){return SDPUtils.parseSsrcMedia(line);}).filter(function(parts){return parts.attribute==='cname';});var primarySsrc=ssrcs.length>0&&ssrcs[0].ssrc;var secondarySsrc;var flows=SDPUtils.matchPrefix(mediaSection,'a=ssrc-group:FID').map(function(line){var parts=line.substr(17).split(' ');return parts.map(function(part){return parseInt(part,10);});});if(flows.length>0&&flows[0].length>1&&flows[0][0]===primarySsrc){secondarySsrc=flows[0][1];}
+description.codecs.forEach(function(codec){if(codec.name.toUpperCase()==='RTX'&&codec.parameters.apt){var encParam={ssrc:primarySsrc,codecPayloadType:parseInt(codec.parameters.apt,10)};if(primarySsrc&&secondarySsrc){encParam.rtx={ssrc:secondarySsrc};}
+encodingParameters.push(encParam);if(hasRed){encParam=JSON.parse(JSON.stringify(encParam));encParam.fec={ssrc:primarySsrc,mechanism:hasUlpfec?'red+ulpfec':'red'};encodingParameters.push(encParam);}}});if(encodingParameters.length===0&&primarySsrc){encodingParameters.push({ssrc:primarySsrc});}
+var bandwidth=SDPUtils.matchPrefix(mediaSection,'b=');if(bandwidth.length){if(bandwidth[0].indexOf('b=TIAS:')===0){bandwidth=parseInt(bandwidth[0].substr(7),10);}else if(bandwidth[0].indexOf('b=AS:')===0){bandwidth=parseInt(bandwidth[0].substr(5),10)*1000*0.95
+-(50*40*8);}else{bandwidth=undefined;}
+encodingParameters.forEach(function(params){params.maxBitrate=bandwidth;});}
+return encodingParameters;};SDPUtils.parseRtcpParameters=function(mediaSection){var rtcpParameters={};var remoteSsrc=SDPUtils.matchPrefix(mediaSection,'a=ssrc:').map(function(line){return SDPUtils.parseSsrcMedia(line);}).filter(function(obj){return obj.attribute==='cname';})[0];if(remoteSsrc){rtcpParameters.cname=remoteSsrc.value;rtcpParameters.ssrc=remoteSsrc.ssrc;}
+var rsize=SDPUtils.matchPrefix(mediaSection,'a=rtcp-rsize');rtcpParameters.reducedSize=rsize.length>0;rtcpParameters.compound=rsize.length===0;var mux=SDPUtils.matchPrefix(mediaSection,'a=rtcp-mux');rtcpParameters.mux=mux.length>0;return rtcpParameters;};SDPUtils.parseMsid=function(mediaSection){var parts;var spec=SDPUtils.matchPrefix(mediaSection,'a=msid:');if(spec.length===1){parts=spec[0].substr(7).split(' ');return{stream:parts[0],track:parts[1]};}
+var planB=SDPUtils.matchPrefix(mediaSection,'a=ssrc:').map(function(line){return SDPUtils.parseSsrcMedia(line);}).filter(function(msidParts){return msidParts.attribute==='msid';});if(planB.length>0){parts=planB[0].value.split(' ');return{stream:parts[0],track:parts[1]};}};SDPUtils.generateSessionId=function(){return Math.random().toString().substr(2,21);};SDPUtils.writeSessionBoilerplate=function(sessId,sessVer,sessUser){var sessionId;var version=sessVer!==undefined?sessVer:2;if(sessId){sessionId=sessId;}else{sessionId=SDPUtils.generateSessionId();}
+var user=sessUser||'thisisadapterortc';return'v=0\r\n'+'o='+user+' '+sessionId+' '+version+' IN IP4 127.0.0.1\r\n'+'s=-\r\n'+'t=0 0\r\n';};SDPUtils.writeMediaSection=function(transceiver,caps,type,stream){var sdp=SDPUtils.writeRtpDescription(transceiver.kind,caps);sdp+=SDPUtils.writeIceParameters(transceiver.iceGatherer.getLocalParameters());sdp+=SDPUtils.writeDtlsParameters(transceiver.dtlsTransport.getLocalParameters(),type==='offer'?'actpass':'active');sdp+='a=mid:'+transceiver.mid+'\r\n';if(transceiver.direction){sdp+='a='+transceiver.direction+'\r\n';}else if(transceiver.rtpSender&&transceiver.rtpReceiver){sdp+='a=sendrecv\r\n';}else if(transceiver.rtpSender){sdp+='a=sendonly\r\n';}else if(transceiver.rtpReceiver){sdp+='a=recvonly\r\n';}else{sdp+='a=inactive\r\n';}
+if(transceiver.rtpSender){var msid='msid:'+stream.id+' '+
+transceiver.rtpSender.track.id+'\r\n';sdp+='a='+msid;sdp+='a=ssrc:'+transceiver.sendEncodingParameters[0].ssrc+' '+msid;if(transceiver.sendEncodingParameters[0].rtx){sdp+='a=ssrc:'+transceiver.sendEncodingParameters[0].rtx.ssrc+' '+msid;sdp+='a=ssrc-group:FID '+
+transceiver.sendEncodingParameters[0].ssrc+' '+
+transceiver.sendEncodingParameters[0].rtx.ssrc+'\r\n';}}
+sdp+='a=ssrc:'+transceiver.sendEncodingParameters[0].ssrc+' cname:'+SDPUtils.localCName+'\r\n';if(transceiver.rtpSender&&transceiver.sendEncodingParameters[0].rtx){sdp+='a=ssrc:'+transceiver.sendEncodingParameters[0].rtx.ssrc+' cname:'+SDPUtils.localCName+'\r\n';}
+return sdp;};SDPUtils.getDirection=function(mediaSection,sessionpart){var lines=SDPUtils.splitLines(mediaSection);for(var i=0;i
- *
- * Version: MPL 1.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Verto HTML5/Javascript Telephony Signaling and Control Protocol Stack for FreeSWITCH
- *
- * The Initial Developer of the Original Code is
- * Anthony Minessale II
- * Portions created by the Initial Developer are Copyright (C)
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Anthony Minessale II
- *
- * jquery.FSRTC.js - WebRTC Glue code
- *
- */
-(function($) {
-
- // Find the line in sdpLines that starts with |prefix|, and, if specified,
- // contains |substr| (case-insensitive search).
- function findLine(sdpLines, prefix, substr) {
- return findLineInRange(sdpLines, 0, -1, prefix, substr);
- }
-
- // Find the line in sdpLines[startLine...endLine - 1] that starts with |prefix|
- // and, if specified, contains |substr| (case-insensitive search).
- function findLineInRange(sdpLines, startLine, endLine, prefix, substr) {
- var realEndLine = (endLine != -1) ? endLine : sdpLines.length;
- for (var i = startLine; i < realEndLine; ++i) {
- if (sdpLines[i].indexOf(prefix) === 0) {
- if (!substr || sdpLines[i].toLowerCase().indexOf(substr.toLowerCase()) !== -1) {
- return i;
- }
- }
- }
- return null;
- }
-
- // Gets the codec payload type from an a=rtpmap:X line.
- function getCodecPayloadType(sdpLine) {
- var pattern = new RegExp('a=rtpmap:(\\d+) \\w+\\/\\d+');
- var result = sdpLine.match(pattern);
- return (result && result.length == 2) ? result[1] : null;
- }
-
- // Returns a new m= line with the specified codec as the first one.
- function setDefaultCodec(mLine, payload) {
- var elements = mLine.split(' ');
- var newLine = [];
- var index = 0;
- for (var i = 0; i < elements.length; i++) {
- if (index === 3) { // Format of media starts from the fourth.
- newLine[index++] = payload; // Put target payload to the first.
- }
- if (elements[i] !== payload) newLine[index++] = elements[i];
- }
- return newLine.join(' ');
- }
-
- $.FSRTC = function(options) {
- this.options = $.extend({
- useVideo: null,
- useStereo: false,
- userData: null,
- localVideo: null,
- screenShare: false,
- useCamera: "any",
- iceServers: false,
- videoParams: {},
- audioParams: {},
- callbacks: {
- onICEComplete: function() {},
- onICE: function() {},
- onOfferSDP: function() {}
- },
- useStream: null,
- }, options);
-
- this.audioEnabled = true;
- this.videoEnabled = true;
-
-
- this.mediaData = {
- SDP: null,
- profile: {},
- candidateList: []
- };
-
- this.constraints = {
- offerToReceiveAudio: this.options.useSpeak === "none" ? false : true,
- offerToReceiveVideo: this.options.useVideo ? true : false,
- };
-
- if (self.options.useVideo) {
- self.options.useVideo.style.display = 'none';
- }
-
- setCompat();
- checkCompat();
- };
-
- $.FSRTC.validRes = [];
-
- $.FSRTC.prototype.useVideo = function(obj, local) {
- var self = this;
-
- if (obj) {
- self.options.useVideo = obj;
- self.options.localVideo = local;
- self.constraints.offerToReceiveVideo = true;
- } else {
- self.options.useVideo = null;
- self.options.localVideo = null;
- self.constraints.offerToReceiveVideo = false;
- }
-
- if (self.options.useVideo) {
- self.options.useVideo.style.display = 'none';
- }
- };
-
- $.FSRTC.prototype.useStereo = function(on) {
- var self = this;
- self.options.useStereo = on;
- };
-
- // Sets Opus in stereo if stereo is enabled, by adding the stereo=1 fmtp param.
- $.FSRTC.prototype.stereoHack = function(sdp) {
- var self = this;
-
- if (!self.options.useStereo) {
- return sdp;
- }
-
- var sdpLines = sdp.split('\r\n');
-
- // Find opus payload.
- var opusIndex = findLine(sdpLines, 'a=rtpmap', 'opus/48000'), opusPayload;
-
- if (!opusIndex) {
- return sdp;
- } else {
- opusPayload = getCodecPayloadType(sdpLines[opusIndex]);
- }
-
- // Find the payload in fmtp line.
- var fmtpLineIndex = findLine(sdpLines, 'a=fmtp:' + opusPayload.toString());
-
- if (fmtpLineIndex === null) {
- // create an fmtp line
- sdpLines[opusIndex] = sdpLines[opusIndex] + '\r\na=fmtp:' + opusPayload.toString() + " stereo=1; sprop-stereo=1"
- } else {
- // Append stereo=1 to fmtp line.
- sdpLines[fmtpLineIndex] = sdpLines[fmtpLineIndex].concat('; stereo=1; sprop-stereo=1');
- }
-
- sdp = sdpLines.join('\r\n');
- return sdp;
- };
-
- function setCompat() {
- }
-
- function checkCompat() {
- return true;
- }
-
- function onStreamError(self, e) {
- console.log('There has been a problem retrieving the streams - did you allow access? Check Device Resolution', e);
- doCallback(self, "onError", e);
- }
-
- function onStreamSuccess(self, stream) {
- console.log("Stream Success");
- doCallback(self, "onStream", stream);
- }
-
- function onRemoteStreamSuccess(self, stream) {
- console.log("Remote Stream Success");
- doCallback(self, "onRemoteStream", stream);
- }
-
- function onICE(self, candidate) {
- self.mediaData.candidate = candidate;
- self.mediaData.candidateList.push(self.mediaData.candidate);
-
- doCallback(self, "onICE");
- }
-
- function doCallback(self, func, arg) {
- if (func in self.options.callbacks) {
- self.options.callbacks[func](self, arg);
- }
- }
-
- function onICEComplete(self, candidate) {
- console.log("ICE Complete");
- doCallback(self, "onICEComplete");
- }
-
- function onChannelError(self, e) {
- console.error("Channel Error", e);
- doCallback(self, "onError", e);
- }
-
- function onICESDP(self, sdp) {
- self.mediaData.SDP = self.stereoHack(sdp.sdp);
- console.log("ICE SDP");
- doCallback(self, "onICESDP");
- }
-
- function onAnswerSDP(self, sdp) {
- self.answer.SDP = self.stereoHack(sdp.sdp);
- console.log("ICE ANSWER SDP");
- doCallback(self, "onAnswerSDP", self.answer.SDP);
- }
-
- function onMessage(self, msg) {
- console.log("Message");
- doCallback(self, "onICESDP", msg);
- }
-
- FSRTCattachMediaStream = function(element, stream) {
- if (typeof element.srcObject !== 'undefined') {
- element.srcObject = stream;
- } else {
- console.error('Error attaching stream to element.');
- }
- }
-
- function onRemoteStream(self, stream) {
- if (self.options.useVideo) {
- self.options.useVideo.style.display = 'block';
-
- // Hacks for Mobile Safari
- var iOS = ['iPad', 'iPhone', 'iPod'].indexOf(navigator.platform) >= 0;
-
- if (iOS) {
- self.options.useVideo.setAttribute("playsinline", true);
- }
- }
-
- var element = self.options.useAudio;
- console.log("REMOTE STREAM", stream, element);
-
- FSRTCattachMediaStream(element, stream);
-
-
-
- //self.options.useAudio.play();
- self.remoteStream = stream;
- onRemoteStreamSuccess(self, stream);
- }
-
- function onOfferSDP(self, sdp) {
- self.mediaData.SDP = self.stereoHack(sdp.sdp);
- console.log("Offer SDP");
- doCallback(self, "onOfferSDP");
- }
-
- $.FSRTC.prototype.answer = function(sdp, onSuccess, onError) {
- this.peer.addAnswerSDP({
- type: "answer",
- sdp: sdp
- },
- onSuccess, onError);
- };
-
- $.FSRTC.prototype.stopPeer = function() {
- if (self.peer) {
- console.log("stopping peer");
- self.peer.stop();
- }
- }
-
- $.FSRTC.prototype.stop = function() {
- var self = this;
-
- if (self.options.useVideo) {
- self.options.useVideo.style.display = 'none';
- self.options.useVideo['src'] = '';
- }
-
- if (self.localStream && !self.options.useStream) {
- if(typeof self.localStream.stop == 'function') {
- self.localStream.stop();
- } else {
- if (self.localStream.active){
- var tracks = self.localStream.getTracks();
- console.log(tracks);
- tracks.forEach(function(track, index){
- console.log(track);
- track.stop();
- })
- }
- }
- self.localStream = null;
- }
-
- if (self.options.localVideo) {
- deactivateLocalVideo(self.options.localVideo);
- }
-
- if (self.options.localVideoStream && !self.options.useStream) {
- if(typeof self.options.localVideoStream.stop == 'function') {
- self.options.localVideoStream.stop();
- } else {
- if (self.options.localVideoStream.active){
- var tracks = self.options.localVideoStream.getTracks();
- console.log(tracks);
- tracks.forEach(function(track, index){
- console.log(track);
- track.stop();
- })
- }
- }
- }
-
- if (self.peer) {
- console.log("stopping peer");
- self.peer.stop();
- }
- };
-
- $.FSRTC.prototype.getMute = function() {
- var self = this;
- return self.audioEnabled;
- }
-
- $.FSRTC.prototype.setMute = function(what) {
- var self = this;
- if (!self.localStream) {
- return false;
- }
- var audioTracks = self.localStream.getAudioTracks();
-
- for (var i = 0, len = audioTracks.length; i < len; i++ ) {
- switch(what) {
- case "on":
- audioTracks[i].enabled = true;
- break;
- case "off":
- audioTracks[i].enabled = false;
- break;
- case "toggle":
- audioTracks[i].enabled = !audioTracks[i].enabled;
- default:
- break;
- }
-
- self.audioEnabled = audioTracks[i].enabled;
- }
-
- return !self.audioEnabled;
- }
-
- $.FSRTC.prototype.getVideoMute = function() {
- var self = this;
- return self.videoEnabled;
- }
-
- $.FSRTC.prototype.setVideoMute = function(what) {
- var self = this;
- if (!self.localStream) {
- return false;
- }
- var videoTracks = self.localStream.getVideoTracks();
-
- for (var i = 0, len = videoTracks.length; i < len; i++ ) {
- switch(what) {
- case "on":
- videoTracks[i].enabled = true;
- break;
- case "off":
- videoTracks[i].enabled = false;
- break;
- case "toggle":
- videoTracks[i].enabled = !videoTracks[i].enabled;
- default:
- break;
- }
-
- self.videoEnabled = videoTracks[i].enabled;
- }
-
- return !self.videoEnabled;
- }
-
- $.FSRTC.prototype.createAnswer = function(params) {
- var self = this;
- self.type = "answer";
- self.remoteSDP = params.sdp;
- console.debug("inbound sdp: ", params.sdp);
-
- function onSuccess(stream) {
- self.localStream = stream;
-
- self.peer = FSRTCPeerConnection({
- type: self.type,
- attachStream: self.localStream,
- onICE: function(candidate) {
- return onICE(self, candidate);
- },
- onICEComplete: function() {
- return onICEComplete(self);
- },
- onRemoteStream: function(stream) {
- return onRemoteStream(self, stream);
- },
- onICESDP: function(sdp) {
- return onICESDP(self, sdp);
- },
- onChannelError: function(e) {
- return onChannelError(self, e);
- },
- constraints: self.constraints,
- iceServers: self.options.iceServers,
- offerSDP: {
- type: "offer",
- sdp: self.remoteSDP
- },
- turnServer: self.options.turnServer
- });
-
- onStreamSuccess(self, stream);
- }
-
- function onError(e) {
- onStreamError(self, e);
- }
-
- var mediaParams = getMediaParams(self);
-
- console.log("Audio constraints", mediaParams.audio);
- console.log("Video constraints", mediaParams.video);
-
- if (self.options.useVideo && self.options.localVideo && !self.options.useStream) {
- getUserMedia({
- constraints: {
- audio: false,
- video: { deviceId: params.useCamera },
- },
- localVideo: self.options.localVideo,
- onsuccess: function(e) {self.options.localVideoStream = e; console.log("local video ready");},
- onerror: function(e) {console.error("local video error!");}
- });
- }
-
- if (self.options.useStream) {
- if (self.options.useVideo) {
- self.options.localVideoStream = self.options.useStream;
- if (self.options.localVideo) {
- activateLocalVideo(self.options.localVideo, self.options.useStream);
- }
- }
- onSuccess(self.options.useStream);
- }
- else {
- getUserMedia({
- constraints: {
- audio: mediaParams.audio,
- video: mediaParams.video
- },
- video: mediaParams.useVideo,
- onsuccess: onSuccess,
- onerror: onError
- });
- }
-
- };
-
- function getMediaParams(obj) {
-
- var audio;
-
- if (obj.options.useMic && obj.options.useMic === "none") {
- console.log("Microphone Disabled");
- audio = false;
- } else if (obj.options.videoParams && obj.options.screenShare) {//obj.options.videoParams.chromeMediaSource == 'desktop') {
- console.error("SCREEN SHARE", obj.options.videoParams);
- audio = false;
- } else {
- audio = {
- };
-
- if (obj.options.audioParams) {
- audio = obj.options.audioParams;
- }
-
- if (obj.options.useMic !== "any") {
- //audio.optional = [{sourceId: obj.options.useMic}];
- audio.deviceId = {exact: obj.options.useMic};
- }
- }
-
- if (obj.options.useVideo && obj.options.localVideo && !obj.options.useStream) {
- getUserMedia({
- constraints: {
- audio: false,
- video: { deviceId: obj.options.useCamera },
- },
- localVideo: obj.options.localVideo,
- onsuccess: function(e) {obj.options.localVideoStream = e; console.log("local video ready");},
- onerror: function(e) {console.error("local video error!");}
- });
- }
-
- var video = {};
- var bestFrameRate = obj.options.videoParams.vertoBestFrameRate;
- var minFrameRate = obj.options.videoParams.minFrameRate || 15;
- delete obj.options.videoParams.vertoBestFrameRate;
-
- if (obj.options.screenShare) {
- if (!obj.options.useCamera && !!navigator.mozGetUserMedia) {
- //This is an issue, only FireFox needs to ask this additional question if its screen or window we need a better way
- var dowin = window.confirm("Do you want to share an application window? If not you can share an entire screen.");
-
- video = {
- width: {min: obj.options.videoParams.minWidth, max: obj.options.videoParams.maxWidth},
- height: {min: obj.options.videoParams.minHeight, max: obj.options.videoParams.maxHeight},
- mediaSource: dowin ? "window" : "screen"
- }
- } else {
- var opt = [];
- if (obj.options.useCamera) {
- opt.push({sourceId: obj.options.useCamera});
- }
-
- if (bestFrameRate) {
- opt.push({minFrameRate: bestFrameRate});
- opt.push({maxFrameRate: bestFrameRate});
- }
-
- video = {
- mandatory: obj.options.videoParams,
- optional: opt
- };
- // NOTE: This is a workaround for
- // https://bugs.chromium.org/p/chromium/issues/detail?id=862325
- if (!!navigator.userAgent.match(/Android/i)) {
- delete video.frameRate.min;
- }
- }
- } else {
-
- video = {
- //mandatory: obj.options.videoParams,
- width: {min: obj.options.videoParams.minWidth, max: obj.options.videoParams.maxWidth},
- height: {min: obj.options.videoParams.minHeight, max: obj.options.videoParams.maxHeight}
- };
-
-
-
- var useVideo = obj.options.useVideo;
-
- if (useVideo && obj.options.useCamera && obj.options.useCamera !== "none") {
- //if (!video.optional) {
- //video.optional = [];
- //}
-
-
- if (obj.options.useCamera !== "any") {
- //video.optional.push({sourceId: obj.options.useCamera});
- video.deviceId = {
- exact: obj.options.useCamera,
- };
- }
-
- if (bestFrameRate) {
- //video.optional.push({minFrameRate: bestFrameRate});
- //video.optional.push({maxFrameRate: bestFrameRate});
- video.frameRate = {ideal: bestFrameRate, min: minFrameRate, max: 30};
- }
-
- } else {
- console.log("Camera Disabled");
- video = false;
- useVideo = false;
- }
- }
-
- return {audio: audio, video: video, useVideo: useVideo};
- }
-
- $.FSRTC.prototype.call = function(profile) {
- checkCompat();
-
- var self = this;
- var screen = false;
-
- self.type = "offer";
-
- if (self.options.videoParams && self.options.screenShare) { //self.options.videoParams.chromeMediaSource == 'desktop') {
- screen = true;
- }
-
- function onSuccess(stream) {
- self.localStream = stream;
-
- if (screen) {
- self.constraints.offerToReceiveVideo = false;
- self.constraints.offerToReceiveAudio = false;
- self.constraints.offerToSendAudio = false;
- }
-
- self.peer = FSRTCPeerConnection({
- type: self.type,
- attachStream: self.localStream,
- onICE: function(candidate) {
- return onICE(self, candidate);
- },
- onICEComplete: function() {
- return onICEComplete(self);
- },
- onRemoteStream: screen ? function(stream) {} : function(stream) {
- return onRemoteStream(self, stream);
- },
- onOfferSDP: function(sdp) {
- return onOfferSDP(self, sdp);
- },
- onICESDP: function(sdp) {
- return onICESDP(self, sdp);
- },
- onChannelError: function(e) {
- return onChannelError(self, e);
- },
- constraints: self.constraints,
- iceServers: self.options.iceServers,
- turnServer: self.options.turnServer
- });
-
- onStreamSuccess(self, stream);
- }
-
- function onError(e) {
- onStreamError(self, e);
- }
-
- var mediaParams = getMediaParams(self);
-
- console.log("Audio constraints", mediaParams.audio);
- console.log("Video constraints", mediaParams.video);
-
- if (self.options.useStream) {
- if (self.options.useVideo) {
- self.options.localVideoStream = self.options.useStream;
- if (self.options.localVideo) {
- activateLocalVideo(self.options.localVideo, self.options.useStream);
- }
- }
- onSuccess(self.options.useStream);
- }
- else if (mediaParams.audio || mediaParams.video) {
-
- getUserMedia({
- constraints: {
- audio: mediaParams.audio,
- video: mediaParams.video
- },
- video: mediaParams.useVideo,
- onsuccess: onSuccess,
- onerror: onError
- });
-
- } else {
- onSuccess(null);
- }
-
-
-
- /*
- navigator.getUserMedia({
- video: self.options.useVideo,
- audio: true
- }, onSuccess, onError);
- */
-
- };
-
- // DERIVED from RTCPeerConnection-v1.5
- // 2013, @muazkh - github.com/muaz-khan
- // MIT License - https://www.webrtc-experiment.com/licence/
- // Documentation - https://github.com/muaz-khan/WebRTC-Experiment/tree/master/RTCPeerConnection
-
- function FSRTCPeerConnection(options) {
- var gathering = false, done = false;
- var config = {};
- var default_ice = [{ urls: ['stun:stun.l.google.com:19302'] }];
-
- if (self.options.turnServer) {
- default_ice.push(self.options.turnServer)
- }
-
- if (options.iceServers) {
- if (typeof(options.iceServers) === "boolean") {
- config.iceServers = default_ice;
- } else {
- config.iceServers = options.iceServers;
- }
- }
-
- config.bundlePolicy = "max-compat";
-
- var peer = new window.RTCPeerConnection(config);
-
- openOffererChannel();
- var x = 0;
-
- function ice_handler() {
-
- done = true;
- gathering = null;
-
- if (options.onICEComplete) {
- options.onICEComplete();
- }
-
- if (options.type == "offer") {
- options.onICESDP(peer.localDescription);
- } else {
- if (!x && options.onICESDP) {
- options.onICESDP(peer.localDescription);
- }
- }
- }
-
- peer.onicecandidate = function(event) {
-
- if (done) {
- return;
- }
-
- if (!gathering) {
- gathering = setTimeout(ice_handler, 1000);
- }
-
- if (event) {
- if (event.candidate) {
- options.onICE(event.candidate);
- }
- } else {
- done = true;
-
- if (gathering) {
- clearTimeout(gathering);
- gathering = null;
- }
-
- ice_handler();
- }
- };
-
- // attachStream = MediaStream;
- if (options.attachStream) peer.addStream(options.attachStream);
-
- // attachStreams[0] = audio-stream;
- // attachStreams[1] = video-stream;
- // attachStreams[2] = screen-capturing-stream;
- if (options.attachStreams && options.attachStream.length) {
- var streams = options.attachStreams;
- for (var i = 0; i < streams.length; i++) {
- peer.addStream(streams[i]);
- }
- }
-
- peer.onaddstream = function(event) {
- var remoteMediaStream = event.stream;
-
- // onRemoteStreamEnded(MediaStream)
- remoteMediaStream.oninactive = function () {
- if (options.onRemoteStreamEnded) options.onRemoteStreamEnded(remoteMediaStream);
- };
-
- // onRemoteStream(MediaStream)
- if (options.onRemoteStream) options.onRemoteStream(remoteMediaStream);
-
- //console.debug('on:add:stream', remoteMediaStream);
- };
-
- //var constraints = options.constraints || {
- // offerToReceiveAudio: true,
- //offerToReceiveVideo: true
- //};
-
- // onOfferSDP(RTCSessionDescription)
- function createOffer() {
- if (!options.onOfferSDP) return;
-
- peer.createOffer(function(sessionDescription) {
- sessionDescription.sdp = serializeSdp(sessionDescription.sdp);
- peer.setLocalDescription(sessionDescription);
- options.onOfferSDP(sessionDescription);
- },
- onSdpError, options.constraints);
- }
-
- // onAnswerSDP(RTCSessionDescription)
- function createAnswer() {
- if (options.type != "answer") return;
-
- //options.offerSDP.sdp = addStereo(options.offerSDP.sdp);
- peer.setRemoteDescription(new window.RTCSessionDescription(options.offerSDP), onSdpSuccess, onSdpError);
- peer.createAnswer(function(sessionDescription) {
- sessionDescription.sdp = serializeSdp(sessionDescription.sdp);
- peer.setLocalDescription(sessionDescription);
- if (options.onAnswerSDP) {
- options.onAnswerSDP(sessionDescription);
- }
- },
- onSdpError);
- }
-
-
- if ((options.onChannelMessage) || !options.onChannelMessage) {
- createOffer();
- createAnswer();
- }
-
- // DataChannel Bandwidth
- function setBandwidth(sdp) {
- // remove existing bandwidth lines
- sdp = sdp.replace(/b=AS([^\r\n]+\r\n)/g, '');
- sdp = sdp.replace(/a=mid:data\r\n/g, 'a=mid:data\r\nb=AS:1638400\r\n');
-
- return sdp;
- }
-
- // old: FF<>Chrome interoperability management
- function getInteropSDP(sdp) {
- var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split(''),
- extractedChars = '';
-
- function getChars() {
- extractedChars += chars[parseInt(Math.random() * 40)] || '';
- if (extractedChars.length < 40) getChars();
-
- return extractedChars;
- }
-
- // usually audio-only streaming failure occurs out of audio-specific crypto line
- // a=crypto:1 AES_CM_128_HMAC_SHA1_32 --------- kAttributeCryptoVoice
- if (options.onAnswerSDP) sdp = sdp.replace(/(a=crypto:0 AES_CM_128_HMAC_SHA1_32)(.*?)(\r\n)/g, '');
-
- // video-specific crypto line i.e. SHA1_80
- // a=crypto:1 AES_CM_128_HMAC_SHA1_80 --------- kAttributeCryptoVideo
- var inline = getChars() + '\r\n' + (extractedChars = '');
- sdp = sdp.indexOf('a=crypto') == -1 ? sdp.replace(/c=IN/g, 'a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:' + inline + 'c=IN') : sdp;
-
- return sdp;
- }
-
- function serializeSdp(sdp) {
- return sdp;
- }
-
- // DataChannel management
- var channel;
-
- function openOffererChannel() {
- if (!options.onChannelMessage) return;
-
- _openOffererChannel();
-
- return;
- }
-
- function _openOffererChannel() {
- channel = peer.createDataChannel(options.channel || 'RTCDataChannel', {
- reliable: false
- });
-
- setChannelEvents();
- }
-
- function setChannelEvents() {
- channel.onmessage = function(event) {
- if (options.onChannelMessage) options.onChannelMessage(event);
- };
-
- channel.onopen = function() {
- if (options.onChannelOpened) options.onChannelOpened(channel);
- };
- channel.onclose = function(event) {
- if (options.onChannelClosed) options.onChannelClosed(event);
-
- console.warn('WebRTC DataChannel closed', event);
- };
- channel.onerror = function(event) {
- if (options.onChannelError) options.onChannelError(event);
-
- console.error('WebRTC DataChannel error', event);
- };
- }
-
- function openAnswererChannel() {
- peer.ondatachannel = function(event) {
- channel = event.channel;
- channel.binaryType = 'blob';
- setChannelEvents();
- };
-
- return;
- }
-
- // fake:true is also available on chrome under a flag!
- function useless() {
- log('Error in fake:true');
- }
-
- function onSdpSuccess() {}
-
- function onSdpError(e) {
- if (options.onChannelError) {
- options.onChannelError(e);
- }
- console.error('sdp error:', e);
- }
-
- return {
- addAnswerSDP: function(sdp, cbSuccess, cbError) {
-
- peer.setRemoteDescription(new window.RTCSessionDescription(sdp), cbSuccess ? cbSuccess : onSdpSuccess, cbError ? cbError : onSdpError);
- },
- addICE: function(candidate) {
- peer.addIceCandidate(new window.RTCIceCandidate({
- sdpMLineIndex: candidate.sdpMLineIndex,
- candidate: candidate.candidate
- }));
- },
-
- peer: peer,
- channel: channel,
- sendData: function(message) {
- if (channel) {
- channel.send(message);
- }
- },
-
- stop: function() {
- peer.close();
- if (options.attachStream) {
- if(typeof options.attachStream.stop == 'function') {
- options.attachStream.stop();
- } else {
- options.attachStream.active = false;
- }
- }
- }
-
- };
- }
-
- // getUserMedia
- var video_constraints = {
- //mandatory: {},
- //optional: []
- };
-
- function activateLocalVideo(el, stream) {
- el.srcObject = stream;
- el.style.display = 'block';
- }
-
- function deactivateLocalVideo(el) {
- el.srcObject = null;
- el.style.display = 'none';
- }
-
- function getUserMedia(options) {
- var n = navigator,
- media;
- n.getMedia = n.getUserMedia;
- n.getMedia(options.constraints || {
- audio: true,
- video: video_constraints
- },
- streaming, options.onerror ||
- function(e) {
- console.error(e);
- });
-
- function streaming(stream) {
- if (options.localVideo) {
- activateLocalVideo(options.localVideo, stream);
- }
-
- if (options.onsuccess) {
- options.onsuccess(stream);
- }
-
- media = stream;
- }
-
- return media;
- }
-
- $.FSRTC.resSupported = function(w, h) {
- for (var i in $.FSRTC.validRes) {
- if ($.FSRTC.validRes[i][0] == w && $.FSRTC.validRes[i][1] == h) {
- return true;
- }
- }
-
- return false;
- }
-
- $.FSRTC.bestResSupported = function() {
- var w = 0, h = 0;
-
- for (var i in $.FSRTC.validRes) {
- if ($.FSRTC.validRes[i][0] >= w && $.FSRTC.validRes[i][1] >= h) {
- w = $.FSRTC.validRes[i][0];
- h = $.FSRTC.validRes[i][1];
- }
- }
-
- return [w, h];
- }
-
- var resList = [[160, 120], [320, 180], [320, 240], [640, 360], [640, 480], [1280, 720], [1920, 1080]];
- var resI = 0;
- var ttl = 0;
-
- var checkRes = function (cam, func) {
-
- if (resI >= resList.length) {
- var res = {
- 'validRes': $.FSRTC.validRes,
- 'bestResSupported': $.FSRTC.bestResSupported()
- };
-
- localStorage.setItem("res_" + cam, $.toJSON(res));
-
- if (func) return func(res);
- return;
- }
-
- w = resList[resI][0];
- h = resList[resI][1];
- resI++;
-
- var video = {
- width: {exact: w},
- height: {exact: h}
- };
-
- if (cam !== "any") {
- video.deviceId = {
- exact: cam,
- };
- }
-
- getUserMedia({
- constraints: {
- audio: ttl++ == 0,
- video: video
- },
- onsuccess: function(e) {
- e.getTracks().forEach(function(track) {track.stop();});
- console.info(w + "x" + h + " supported."); $.FSRTC.validRes.push([w, h]); checkRes(cam, func);},
- onerror: function(e) {console.warn( w + "x" + h + " not supported."); checkRes(cam, func);}
- });
- }
-
-
- $.FSRTC.getValidRes = function (cam, func) {
- var used = [];
- var cached = localStorage.getItem("res_" + cam);
-
- if (cached) {
- var cache = $.parseJSON(cached);
-
- if (cache) {
- $.FSRTC.validRes = cache.validRes;
- console.log("CACHED RES FOR CAM " + cam, cache);
- } else {
- console.error("INVALID CACHE");
- }
- return func ? func(cache) : null;
- }
-
-
- $.FSRTC.validRes = [];
- resI = 0;
-
- checkRes(cam, func);
- }
-
- $.FSRTC.checkPerms = function (runtime, check_audio, check_video) {
- getUserMedia({
- constraints: {
- audio: check_audio,
- video: check_video,
- },
- onsuccess: function(e) {
-
- e.getTracks().forEach(function(track) {track.stop();});
-
- console.info("media perm init complete");
- if (runtime) {
- setTimeout(runtime, 100, true);
- }
- },
- onerror: function(e) {
- if (check_video && check_audio) {
- console.error("error, retesting with audio params only");
- return $.FSRTC.checkPerms(runtime, check_audio, false);
- }
-
- console.error("media perm init error");
-
- if (runtime) {
- runtime(false)
- }
- }
- });
- }
-
-})(jQuery);
-/*
- * Verto HTML5/Javascript Telephony Signaling and Control Protocol Stack for FreeSWITCH
- * Copyright (C) 2005-2014, Anthony Minessale II
- *
- * Version: MPL 1.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is jquery.jsonrpclient.js modified for Verto HTML5/Javascript Telephony Signaling and Control Protocol Stack for FreeSWITCH
- *
- * The Initial Developer of the Original Code is
- * Textalk AB http://textalk.se/
- * Portions created by the Initial Developer are Copyright (C)
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Anthony Minessale II
- *
- * jquery.jsonrpclient.js - JSON RPC client code
- *
- */
-/**
- * This plugin requires jquery.json.js to be available, or at least the methods $.toJSON and
- * $.parseJSON.
- *
- * The plan is to make use of websockets if they are available, but work just as well with only
- * http if not.
- *
- * Usage example:
- *
- * var foo = new $.JsonRpcClient({ ajaxUrl: '/backend/jsonrpc' });
- * foo.call(
- * 'bar', [ 'A parameter', 'B parameter' ],
- * function(result) { alert('Foo bar answered: ' + result.my_answer); },
- * function(error) { console.log('There was an error', error); }
- * );
- *
- * More examples are available in README.md
- */
-(function($) {
- /**
- * @fn new
- * @memberof $.JsonRpcClient
- *
- * @param options An object stating the backends:
- * ajaxUrl A url (relative or absolute) to a http(s) backend.
- * socketUrl A url (relative of absolute) to a ws(s) backend.
- * onmessage A socket message handler for other messages (non-responses).
- * getSocket A function returning a WebSocket or null.
- * It must take an onmessage_cb and bind it to the onmessage event
- * (or chain it before/after some other onmessage handler).
- * Or, it could return null if no socket is available.
- * The returned instance must have readyState <= 1, and if less than 1,
- * react to onopen binding.
- */
- $.JsonRpcClient = function(options) {
- var self = this;
- this.options = $.extend({
- ajaxUrl : null,
- socketUrl : null, ///< The ws-url for default getSocket.
- onmessage : null, ///< Other onmessage-handler.
- login : null, /// auth login
- passwd : null, /// auth passwd
- sessid : null,
- loginParams : null,
- userVariables : null,
- getSocket : function(onmessage_cb) { return self._getSocket(onmessage_cb); }
- }, options);
-
- self.ws_cnt = 0;
-
- // Declare an instance version of the onmessage callback to wrap 'this'.
- this.wsOnMessage = function(event) { self._wsOnMessage(event); };
- };
-
- /// Holding the WebSocket on default getsocket.
- $.JsonRpcClient.prototype._ws_socket = null;
-
- /// Object : { success_cb: cb, error_cb: cb }
- $.JsonRpcClient.prototype._ws_callbacks = {};
-
- /// The next JSON-RPC request id.
- $.JsonRpcClient.prototype._current_id = 1;
-
-
- $.JsonRpcClient.prototype.speedTest = function (bytes, cb) {
- var socket = this.options.getSocket(this.wsOnMessage);
- if (socket !== null) {
- this.speedCB = cb;
- this.speedBytes = bytes;
- socket.send("#SPU " + bytes);
-
- var loops = bytes / 1024;
- var rem = bytes % 1024;
- var i;
- var data = new Array(1024).join(".");
- for (i = 0; i < loops; i++) {
- socket.send("#SPB " + data);
- }
-
- if (rem) {
- socket.send("#SPB " + data);
- }
-
- socket.send("#SPE");
- }
- };
-
-
-
- /**
- * @fn call
- * @memberof $.JsonRpcClient
- *
- * @param method The method to run on JSON-RPC server.
- * @param params The params; an array or object.
- * @param success_cb A callback for successful request.
- * @param error_cb A callback for error.
- */
- $.JsonRpcClient.prototype.call = function(method, params, success_cb, error_cb) {
- // Construct the JSON-RPC 2.0 request.
-
- if (!params) {
- params = {};
- }
-
- if (this.options.sessid) {
- params.sessid = this.options.sessid;
- }
-
- var request = {
- jsonrpc : '2.0',
- method : method,
- params : params,
- id : this._current_id++ // Increase the id counter to match request/response
- };
-
- if (!success_cb) {
- success_cb = function(e){console.log("Success: ", e);};
- }
-
- if (!error_cb) {
- error_cb = function(e){console.log("Error: ", e);};
- }
-
- // Try making a WebSocket call.
- var socket = this.options.getSocket(this.wsOnMessage);
- if (socket !== null) {
- this._wsCall(socket, request, success_cb, error_cb);
- return;
- }
-
- // No WebSocket, and no HTTP backend? This won't work.
- if (this.options.ajaxUrl === null) {
- throw "$.JsonRpcClient.call used with no websocket and no http endpoint.";
- }
-
- $.ajax({
- type : 'POST',
- url : this.options.ajaxUrl,
- data : $.toJSON(request),
- dataType : 'json',
- cache : false,
-
- success : function(data) {
- if ('error' in data) error_cb(data.error, this);
- success_cb(data.result, this);
- },
-
- // JSON-RPC Server could return non-200 on error
- error : function(jqXHR, textStatus, errorThrown) {
- try {
- var response = $.parseJSON(jqXHR.responseText);
-
- if ('console' in window) console.log(response);
-
- error_cb(response.error, this);
- } catch (err) {
- // Perhaps the responseText wasn't really a jsonrpc-error.
- error_cb({ error: jqXHR.responseText }, this);
- }
- }
- });
- };
-
- /**
- * Notify sends a command to the server that won't need a response. In http, there is probably
- * an empty response - that will be dropped, but in ws there should be no response at all.
- *
- * This is very similar to call, but has no id and no handling of callbacks.
- *
- * @fn notify
- * @memberof $.JsonRpcClient
- *
- * @param method The method to run on JSON-RPC server.
- * @param params The params; an array or object.
- */
- $.JsonRpcClient.prototype.notify = function(method, params) {
- // Construct the JSON-RPC 2.0 request.
-
- if (this.options.sessid) {
- params.sessid = this.options.sessid;
- }
-
- var request = {
- jsonrpc: '2.0',
- method: method,
- params: params
- };
-
- // Try making a WebSocket call.
- var socket = this.options.getSocket(this.wsOnMessage);
- if (socket !== null) {
- this._wsCall(socket, request);
- return;
- }
-
- // No WebSocket, and no HTTP backend? This won't work.
- if (this.options.ajaxUrl === null) {
- throw "$.JsonRpcClient.notify used with no websocket and no http endpoint.";
- }
-
- $.ajax({
- type : 'POST',
- url : this.options.ajaxUrl,
- data : $.toJSON(request),
- dataType : 'json',
- cache : false
- });
- };
-
- /**
- * Make a batch-call by using a callback.
- *
- * The callback will get an object "batch" as only argument. On batch, you can call the methods
- * "call" and "notify" just as if it was a normal $.JsonRpcClient object, and all calls will be
- * sent as a batch call then the callback is done.
- *
- * @fn batch
- * @memberof $.JsonRpcClient
- *
- * @param callback The main function which will get a batch handler to run call and notify on.
- * @param all_done_cb A callback function to call after all results have been handled.
- * @param error_cb A callback function to call if there is an error from the server.
- * Note, that batch calls should always get an overall success, and the
- * only error
- */
- $.JsonRpcClient.prototype.batch = function(callback, all_done_cb, error_cb) {
- var batch = new $.JsonRpcClient._batchObject(this, all_done_cb, error_cb);
- callback(batch);
- batch._execute();
- };
-
- /**
- * The default getSocket handler.
- *
- * @param onmessage_cb The callback to be bound to onmessage events on the socket.
- *
- * @fn _getSocket
- * @memberof $.JsonRpcClient
- */
-
- $.JsonRpcClient.prototype.socketReady = function() {
- if (this._ws_socket === null || this._ws_socket.readyState > 1) {
- return false;
- }
-
- return true;
- };
-
- $.JsonRpcClient.prototype.closeSocket = function() {
- var self = this;
- if (self.socketReady()) {
- self._ws_socket.onclose = function (w) {console.log("Closing Socket");};
- self._ws_socket.close();
- }
- };
-
- $.JsonRpcClient.prototype.loginData = function(params) {
- var self = this;
- self.options.login = params.login;
- self.options.passwd = params.passwd;
- self.options.loginParams = params.loginParams;
- self.options.userVariables = params.userVariables;
- };
-
- $.JsonRpcClient.prototype.connectSocket = function(onmessage_cb) {
- var self = this;
-
- if (self.to) {
- clearTimeout(self.to);
- }
-
- if (!self.socketReady()) {
- self.authing = false;
-
- if (self._ws_socket) {
- delete self._ws_socket;
- }
-
- // No socket, or dying socket, let's get a new one.
- self._ws_socket = new WebSocket(self.options.socketUrl);
-
- if (self._ws_socket) {
- // Set up onmessage handler.
- self._ws_socket.onmessage = onmessage_cb;
- self._ws_socket.onclose = function (w) {
- if (!self.ws_sleep) {
- self.ws_sleep = 1000;
- }
-
- if (self.options.onWSClose) {
- self.options.onWSClose(self);
- }
-
- if (self.ws_cnt > 10 && self.options.wsFallbackURL) {
- self.options.socketUrl = self.options.wsFallbackURL;
- }
-
- console.error("Websocket Lost " + self.ws_cnt + " sleep: " + self.ws_sleep + "msec");
-
- self.to = setTimeout(function() {
- console.log("Attempting Reconnection....");
- self.connectSocket(onmessage_cb);
- }, self.ws_sleep);
-
- self.ws_cnt++;
-
- if (self.ws_sleep < 3000 && (self.ws_cnt % 10) === 0) {
- self.ws_sleep += 1000;
- }
- };
-
- // Set up sending of message for when the socket is open.
- self._ws_socket.onopen = function() {
- if (self.to) {
- clearTimeout(self.to);
- }
- self.ws_sleep = 1000;
- self.ws_cnt = 0;
- if (self.options.onWSConnect) {
- self.options.onWSConnect(self);
- }
-
- var req;
- // Send the requests.
- while ((req = $.JsonRpcClient.q.pop())) {
- self._ws_socket.send(req);
- }
- };
- }
- }
-
- return self._ws_socket ? true : false;
- };
-
- $.JsonRpcClient.prototype.stopRetrying = function() {
- if (self.to)
- clearTimeout(self.to);
- }
-
- $.JsonRpcClient.prototype._getSocket = function(onmessage_cb) {
- // If there is no ws url set, we don't have a socket.
- // Likewise, if there is no window.WebSocket.
- if (this.options.socketUrl === null || !("WebSocket" in window)) return null;
-
- this.connectSocket(onmessage_cb);
-
- return this._ws_socket;
- };
-
- /**
- * Queue to save messages delivered when websocket is not ready
- */
- $.JsonRpcClient.q = [];
-
- /**
- * Internal handler to dispatch a JRON-RPC request through a websocket.
- *
- * @fn _wsCall
- * @memberof $.JsonRpcClient
- */
- $.JsonRpcClient.prototype._wsCall = function(socket, request, success_cb, error_cb) {
- var request_json = $.toJSON(request);
-
- if (socket.readyState < 1) {
- // The websocket is not open yet; we have to set sending of the message in onopen.
- self = this; // In closure below, this is set to the WebSocket. Use self instead.
- $.JsonRpcClient.q.push(request_json);
- } else {
- // We have a socket and it should be ready to send on.
- socket.send(request_json);
- }
-
- // Setup callbacks. If there is an id, this is a call and not a notify.
- if ('id' in request && typeof success_cb !== 'undefined') {
- this._ws_callbacks[request.id] = { request: request_json, request_obj: request, success_cb: success_cb, error_cb: error_cb };
- }
- };
-
- /**
- * Internal handler for the websocket messages. It determines if the message is a JSON-RPC
- * response, and if so, tries to couple it with a given callback. Otherwise, it falls back to
- * given external onmessage-handler, if any.
- *
- * @param event The websocket onmessage-event.
- */
- $.JsonRpcClient.prototype._wsOnMessage = function(event) {
- // Check if this could be a JSON RPC message.
- var response;
-
- // Special sub proto
- if (event.data[0] == "#" && event.data[1] == "S" && event.data[2] == "P") {
- if (event.data[3] == "U") {
- this.up_dur = parseInt(event.data.substring(4));
- } else if (this.speedCB && event.data[3] == "D") {
- this.down_dur = parseInt(event.data.substring(4));
-
- var up_kps = (((this.speedBytes * 8) / (this.up_dur / 1000)) / 1024).toFixed(0);
- var down_kps = (((this.speedBytes * 8) / (this.down_dur / 1000)) / 1024).toFixed(0);
-
- console.info("Speed Test: Up: " + up_kps + " Down: " + down_kps);
- var cb = this.speedCB;
- this.speedCB = null;
- cb(event, {
- upDur: this.up_dur,
- downDur: this.down_dur,
- upKPS: up_kps,
- downKPS: down_kps
- });
- }
-
- return;
- }
-
-
- try {
- response = $.parseJSON(event.data);
-
- /// @todo Make using the jsonrcp 2.0 check optional, to use this on JSON-RPC 1 backends.
-
- if (typeof response === 'object' &&
- 'jsonrpc' in response &&
- response.jsonrpc === '2.0') {
-
- /// @todo Handle bad response (without id).
-
- // If this is an object with result, it is a response.
- if ('result' in response && this._ws_callbacks[response.id]) {
- // Get the success callback.
- var success_cb = this._ws_callbacks[response.id].success_cb;
-
- /*
- // set the sessid if present
- if ('sessid' in response.result && !this.options.sessid || (this.options.sessid != response.result.sessid)) {
- this.options.sessid = response.result.sessid;
- if (this.options.sessid) {
- console.log("setting session UUID to: " + this.options.sessid);
- }
- }
- */
- // Delete the callback from the storage.
- delete this._ws_callbacks[response.id];
-
- // Run callback with result as parameter.
- success_cb(response.result, this);
- return;
- } else if ('error' in response && this._ws_callbacks[response.id]) {
- // If this is an object with error, it is an error response.
-
- // Get the error callback.
- var error_cb = this._ws_callbacks[response.id].error_cb;
- var orig_req = this._ws_callbacks[response.id].request;
-
- // if this is an auth request, send the credentials and resend the failed request
- if (!self.authing && response.error.code == -32000 && self.options.login && self.options.passwd) {
- self.authing = true;
-
- this.call("login", { login: self.options.login, passwd: self.options.passwd, loginParams: self.options.loginParams,
- userVariables: self.options.userVariables},
- this._ws_callbacks[response.id].request_obj.method == "login" ?
- function(e) {
- self.authing = false;
- console.log("logged in");
- delete self._ws_callbacks[response.id];
-
- if (self.options.onWSLogin) {
- self.options.onWSLogin(true, self);
- }
- }
-
- :
-
- function(e) {
- self.authing = false;
- console.log("logged in, resending request id: " + response.id);
- var socket = self.options.getSocket(self.wsOnMessage);
- if (socket !== null) {
- socket.send(orig_req);
- }
- if (self.options.onWSLogin) {
- self.options.onWSLogin(true, self);
- }
- },
-
- function(e) {
- console.log("error logging in, request id:", response.id);
- delete self._ws_callbacks[response.id];
- error_cb(response.error, this);
- if (self.options.onWSLogin) {
- self.options.onWSLogin(false, self);
- }
- });
- return;
- }
-
- // Delete the callback from the storage.
- delete this._ws_callbacks[response.id];
-
- // Run callback with the error object as parameter.
- error_cb(response.error, this);
- return;
- }
- }
- } catch (err) {
- // Probably an error while parsing a non json-string as json. All real JSON-RPC cases are
- // handled above, and the fallback method is called below.
- console.log("ERROR: "+ err);
- return;
- }
-
- // This is not a JSON-RPC response. Call the fallback message handler, if given.
- if (typeof this.options.onmessage === 'function') {
- event.eventData = response;
- if (!event.eventData) {
- event.eventData = {};
- }
-
- var reply = this.options.onmessage(event);
-
- if (reply && typeof reply === "object" && event.eventData.id) {
- var msg = {
- jsonrpc: "2.0",
- id: event.eventData.id,
- result: reply
- };
-
- var socket = self.options.getSocket(self.wsOnMessage);
- if (socket !== null) {
- socket.send($.toJSON(msg));
- }
- }
- }
- };
-
-
- /************************************************************************************************
- * Batch object with methods
- ************************************************************************************************/
-
- /**
- * Handling object for batch calls.
- */
- $.JsonRpcClient._batchObject = function(jsonrpcclient, all_done_cb, error_cb) {
- // Array of objects to hold the call and notify requests. Each objects will have the request
- // object, and unless it is a notify, success_cb and error_cb.
- this._requests = [];
-
- this.jsonrpcclient = jsonrpcclient;
- this.all_done_cb = all_done_cb;
- this.error_cb = typeof error_cb === 'function' ? error_cb : function() {};
-
- };
-
- /**
- * @sa $.JsonRpcClient.prototype.call
- */
- $.JsonRpcClient._batchObject.prototype.call = function(method, params, success_cb, error_cb) {
-
- if (!params) {
- params = {};
- }
-
- if (this.options.sessid) {
- params.sessid = this.options.sessid;
- }
-
- if (!success_cb) {
- success_cb = function(e){console.log("Success: ", e);};
- }
-
- if (!error_cb) {
- error_cb = function(e){console.log("Error: ", e);};
- }
-
- this._requests.push({
- request : {
- jsonrpc : '2.0',
- method : method,
- params : params,
- id : this.jsonrpcclient._current_id++ // Use the client's id series.
- },
- success_cb : success_cb,
- error_cb : error_cb
- });
- };
-
- /**
- * @sa $.JsonRpcClient.prototype.notify
- */
- $.JsonRpcClient._batchObject.prototype.notify = function(method, params) {
- if (this.options.sessid) {
- params.sessid = this.options.sessid;
- }
-
- this._requests.push({
- request : {
- jsonrpc : '2.0',
- method : method,
- params : params
- }
- });
- };
-
- /**
- * Executes the batched up calls.
- */
- $.JsonRpcClient._batchObject.prototype._execute = function() {
- var self = this;
-
- if (this._requests.length === 0) return; // All done :P
-
- // Collect all request data and sort handlers by request id.
- var batch_request = [];
- var handlers = {};
- var i = 0;
- var call;
- var success_cb;
- var error_cb;
-
- // If we have a WebSocket, just send the requests individually like normal calls.
- var socket = self.jsonrpcclient.options.getSocket(self.jsonrpcclient.wsOnMessage);
- if (socket !== null) {
- for (i = 0; i < this._requests.length; i++) {
- call = this._requests[i];
- success_cb = ('success_cb' in call) ? call.success_cb : undefined;
- error_cb = ('error_cb' in call) ? call.error_cb : undefined;
- self.jsonrpcclient._wsCall(socket, call.request, success_cb, error_cb);
- }
-
- if (typeof all_done_cb === 'function') all_done_cb(result);
- return;
- }
-
- for (i = 0; i < this._requests.length; i++) {
- call = this._requests[i];
- batch_request.push(call.request);
-
- // If the request has an id, it should handle returns (otherwise it's a notify).
- if ('id' in call.request) {
- handlers[call.request.id] = {
- success_cb : call.success_cb,
- error_cb : call.error_cb
- };
- }
- }
-
- success_cb = function(data) { self._batchCb(data, handlers, self.all_done_cb); };
-
- // No WebSocket, and no HTTP backend? This won't work.
- if (self.jsonrpcclient.options.ajaxUrl === null) {
- throw "$.JsonRpcClient.batch used with no websocket and no http endpoint.";
- }
-
- // Send request
- $.ajax({
- url : self.jsonrpcclient.options.ajaxUrl,
- data : $.toJSON(batch_request),
- dataType : 'json',
- cache : false,
- type : 'POST',
-
- // Batch-requests should always return 200
- error : function(jqXHR, textStatus, errorThrown) {
- self.error_cb(jqXHR, textStatus, errorThrown);
- },
- success : success_cb
- });
- };
-
- /**
- * Internal helper to match the result array from a batch call to their respective callbacks.
- *
- * @fn _batchCb
- * @memberof $.JsonRpcClient
- */
- $.JsonRpcClient._batchObject.prototype._batchCb = function(result, handlers, all_done_cb) {
- for (var i = 0; i < result.length; i++) {
- var response = result[i];
-
- // Handle error
- if ('error' in response) {
- if (response.id === null || !(response.id in handlers)) {
- // An error on a notify? Just log it to the console.
- if ('console' in window) console.log(response);
- } else {
- handlers[response.id].error_cb(response.error, this);
- }
- } else {
- // Here we should always have a correct id and no error.
- if (!(response.id in handlers) && 'console' in window) {
- console.log(response);
- } else {
- handlers[response.id].success_cb(response.result, this);
- }
- }
- }
-
- if (typeof all_done_cb === 'function') all_done_cb(result);
- };
-
-})(jQuery);
-
-/*
- * Verto HTML5/Javascript Telephony Signaling and Control Protocol Stack for FreeSWITCH
- * Copyright (C) 2005-2014, Anthony Minessale II
- *
- * Version: MPL 1.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Verto HTML5/Javascript Telephony Signaling and Control Protocol Stack for FreeSWITCH
- *
- * The Initial Developer of the Original Code is
- * Anthony Minessale II
- * Portions created by the Initial Developer are Copyright (C)
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Anthony Minessale II
- *
- * jquery.verto.js - Main interface
- *
- */
-
-(function($) {
- var sources = [];
-
- var generateGUID = (typeof(window.crypto) !== 'undefined' && typeof(window.crypto.getRandomValues) !== 'undefined') ?
- function() {
- // If we have a cryptographically secure PRNG, use that
- // http://stackoverflow.com/questions/6906916/collisions-when-generating-uuids-in-javascript
- var buf = new Uint16Array(8);
- window.crypto.getRandomValues(buf);
- var S4 = function(num) {
- var ret = num.toString(16);
- while (ret.length < 4) {
- ret = "0" + ret;
- }
- return ret;
- };
- return (S4(buf[0]) + S4(buf[1]) + "-" + S4(buf[2]) + "-" + S4(buf[3]) + "-" + S4(buf[4]) + "-" + S4(buf[5]) + S4(buf[6]) + S4(buf[7]));
- }
-
- :
-
- function() {
- // Otherwise, just use Math.random
- // http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#2117523
- return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
- var r = Math.random() * 16 | 0,
- v = c == 'x' ? r : (r & 0x3 | 0x8);
- return v.toString(16);
- });
- };
-
- /// MASTER OBJ
- $.verto = function(options, callbacks) {
- var verto = this;
-
- $.verto.saved.push(verto);
-
- verto.options = $.extend({
- login: null,
- passwd: null,
- socketUrl: null,
- tag: null,
- localTag: null,
- videoParams: {},
- audioParams: {},
- loginParams: {},
- deviceParams: {onResCheck: null},
- userVariables: {},
- iceServers: false,
- ringSleep: 6000,
- sessid: null,
- useStream: null
- }, options);
-
- if (verto.options.deviceParams.useCamera) {
- $.FSRTC.getValidRes(verto.options.deviceParams.useCamera, verto.options.deviceParams.onResCheck);
- }
-
- if (!verto.options.deviceParams.useMic) {
- verto.options.deviceParams.useMic = "any";
- }
-
- if (!verto.options.deviceParams.useSpeak) {
- verto.options.deviceParams.useSpeak = "any";
- }
-
- if (verto.options.sessid) {
- verto.sessid = verto.options.sessid;
- } else {
- verto.sessid = localStorage.getItem("verto_session_uuid") || generateGUID();
- localStorage.setItem("verto_session_uuid", verto.sessid);
- }
-
- verto.dialogs = {};
- verto.callbacks = callbacks || {};
- verto.eventSUBS = {};
-
- verto.rpcClient = new $.JsonRpcClient({
- login: verto.options.login,
- passwd: verto.options.passwd,
- socketUrl: verto.options.socketUrl,
- wsFallbackURL: verto.options.wsFallbackURL,
- turnServer: verto.options.turnServer,
- loginParams: verto.options.loginParams,
- userVariables: verto.options.userVariables,
- sessid: verto.sessid,
- onmessage: function(e) {
- return verto.handleMessage(e.eventData);
- },
- onWSConnect: function(o) {
- o.call('login', {});
- },
- onWSLogin: function(success) {
- if (verto.callbacks.onWSLogin) {
- verto.callbacks.onWSLogin(verto, success);
- }
- },
- onWSClose: function(success) {
- if (verto.callbacks.onWSClose) {
- verto.callbacks.onWSClose(verto, success);
- }
- verto.purge();
- }
- });
-
- var tag = verto.options.tag;
- if (typeof(tag) === "function") {
- tag = tag();
- }
-
- if (verto.options.ringFile && verto.options.tag) {
- verto.ringer = $("#" + tag);
- }
-
- verto.rpcClient.call('login', {});
-
- };
-
-
- $.verto.prototype.deviceParams = function(obj) {
- var verto = this;
-
- for (var i in obj) {
- verto.options.deviceParams[i] = obj[i];
- }
-
- if (obj.useCamera) {
- $.FSRTC.getValidRes(verto.options.deviceParams.useCamera, obj ? obj.onResCheck : undefined);
- }
- };
-
- $.verto.prototype.videoParams = function(obj) {
- var verto = this;
-
- for (var i in obj) {
- verto.options.videoParams[i] = obj[i];
- }
- };
-
- $.verto.prototype.iceServers = function(obj) {
- var verto = this;
- verto.options.iceServers = obj;
- };
-
- $.verto.prototype.loginData = function(params) {
- var verto = this;
- verto.options.login = params.login;
- verto.options.passwd = params.passwd;
- verto.rpcClient.loginData(params);
- };
-
- $.verto.prototype.logout = function(msg) {
- var verto = this;
- verto.rpcClient.closeSocket();
- if (verto.callbacks.onWSClose) {
- verto.callbacks.onWSClose(verto, false);
- }
- verto.purge();
- };
-
- $.verto.prototype.login = function(msg) {
- var verto = this;
- verto.logout();
- verto.rpcClient.call('login', {});
- };
-
- $.verto.prototype.message = function(msg) {
- var verto = this;
- var err = 0;
-
- if (!msg.to) {
- console.error("Missing To");
- err++;
- }
-
- if (!msg.body) {
- console.error("Missing Body");
- err++;
- }
-
- if (err) {
- return false;
- }
-
- verto.sendMethod("verto.info", {
- msg: msg
- });
-
- return true;
- };
-
- $.verto.prototype.processReply = function(method, success, e) {
- var verto = this;
- var i;
-
- //console.log("Response: " + method, success, e);
-
- switch (method) {
- case "verto.subscribe":
- for (i in e.unauthorizedChannels) {
- drop_bad(verto, e.unauthorizedChannels[i]);
- }
- for (i in e.subscribedChannels) {
- mark_ready(verto, e.subscribedChannels[i]);
- }
-
- break;
- case "verto.unsubscribe":
- //console.error(e);
- break;
- }
- };
-
- $.verto.prototype.sendMethod = function(method, params) {
- var verto = this;
-
- verto.rpcClient.call(method, params,
-
- function(e) {
- /* Success */
- verto.processReply(method, true, e);
- },
-
- function(e) {
- /* Error */
- verto.processReply(method, false, e);
- });
- };
-
- function do_sub(verto, channel, obj) {
-
- }
-
- function drop_bad(verto, channel) {
- console.error("drop unauthorized channel: " + channel);
- delete verto.eventSUBS[channel];
- }
-
- function mark_ready(verto, channel) {
- for (var j in verto.eventSUBS[channel]) {
- verto.eventSUBS[channel][j].ready = true;
- console.log("subscribed to channel: " + channel);
- if (verto.eventSUBS[channel][j].readyHandler) {
- verto.eventSUBS[channel][j].readyHandler(verto, channel);
- }
- }
- }
-
- var SERNO = 1;
-
- function do_subscribe(verto, channel, subChannels, sparams) {
- var params = sparams || {};
-
- var local = params.local;
-
- var obj = {
- eventChannel: channel,
- userData: params.userData,
- handler: params.handler,
- ready: false,
- readyHandler: params.readyHandler,
- serno: SERNO++
- };
-
- var isnew = false;
-
- if (!verto.eventSUBS[channel]) {
- verto.eventSUBS[channel] = [];
- subChannels.push(channel);
- isnew = true;
- }
-
- verto.eventSUBS[channel].push(obj);
-
- if (local) {
- obj.ready = true;
- obj.local = true;
- }
-
- if (!isnew && verto.eventSUBS[channel][0].ready) {
- obj.ready = true;
- if (obj.readyHandler) {
- obj.readyHandler(verto, channel);
- }
- }
-
- return {
- serno: obj.serno,
- eventChannel: channel
- };
-
- }
-
- $.verto.prototype.subscribe = function(channel, sparams) {
- var verto = this;
- var r = [];
- var subChannels = [];
- var params = sparams || {};
-
- if (typeof(channel) === "string") {
- r.push(do_subscribe(verto, channel, subChannels, params));
- } else {
- for (var i in channel) {
- r.push(do_subscribe(verto, channel, subChannels, params));
- }
- }
-
- if (subChannels.length) {
- verto.sendMethod("verto.subscribe", {
- eventChannel: subChannels.length == 1 ? subChannels[0] : subChannels,
- subParams: params.subParams
- });
- }
-
- return r;
- };
-
- $.verto.prototype.unsubscribe = function(handle) {
- var verto = this;
- var i;
-
- if (!handle) {
- for (i in verto.eventSUBS) {
- if (verto.eventSUBS[i]) {
- verto.unsubscribe(verto.eventSUBS[i]);
- }
- }
- } else {
- var unsubChannels = {};
- var sendChannels = [];
- var channel;
-
- if (typeof(handle) == "string") {
- delete verto.eventSUBS[handle];
- unsubChannels[handle]++;
- } else {
- for (i in handle) {
- if (typeof(handle[i]) == "string") {
- channel = handle[i];
- delete verto.eventSUBS[channel];
- unsubChannels[channel]++;
- } else {
- var repl = [];
- channel = handle[i].eventChannel;
-
- for (var j in verto.eventSUBS[channel]) {
- if (verto.eventSUBS[channel][j].serno == handle[i].serno) {} else {
- repl.push(verto.eventSUBS[channel][j]);
- }
- }
-
- verto.eventSUBS[channel] = repl;
-
- if (verto.eventSUBS[channel].length === 0) {
- delete verto.eventSUBS[channel];
- unsubChannels[channel]++;
- }
- }
- }
- }
-
- for (var u in unsubChannels) {
- console.log("Sending Unsubscribe for: ", u);
- sendChannels.push(u);
- }
-
- if (sendChannels.length) {
- verto.sendMethod("verto.unsubscribe", {
- eventChannel: sendChannels.length == 1 ? sendChannels[0] : sendChannels
- });
- }
- }
- };
-
- $.verto.prototype.broadcast = function(channel, params) {
- var verto = this;
- var msg = {
- eventChannel: channel,
- data: {}
- };
- for (var i in params) {
- msg.data[i] = params[i];
- }
- verto.sendMethod("verto.broadcast", msg);
- };
-
- $.verto.prototype.purge = function(callID) {
- var verto = this;
- var x = 0;
- var i;
-
- for (i in verto.dialogs) {
- if (!x) {
- console.log("purging dialogs");
- }
- x++;
- verto.dialogs[i].setState($.verto.enum.state.purge);
- }
-
- for (i in verto.eventSUBS) {
- if (verto.eventSUBS[i]) {
- console.log("purging subscription: " + i);
- delete verto.eventSUBS[i];
- }
- }
- };
-
- $.verto.prototype.hangup = function(callID) {
- var verto = this;
- if (callID) {
- var dialog = verto.dialogs[callID];
-
- if (dialog) {
- dialog.hangup();
- }
- } else {
- for (var i in verto.dialogs) {
- verto.dialogs[i].hangup();
- }
- }
- };
-
- $.verto.prototype.newCall = function(args, callbacks) {
- var verto = this;
-
- if (!verto.rpcClient.socketReady()) {
- console.error("Not Connected...");
- return;
- }
-
- if (args["useCamera"]) {
- verto.options.deviceParams["useCamera"] = args["useCamera"];
- }
-
- var dialog = new $.verto.dialog($.verto.enum.direction.outbound, this, args);
-
- if (callbacks) {
- dialog.callbacks = callbacks;
- }
-
- dialog.invite();
-
- return dialog;
- };
-
- $.verto.prototype.handleMessage = function(data) {
- var verto = this;
-
- if (!(data && data.method)) {
- console.error("Invalid Data", data);
- return;
- }
-
- if (data.params.callID) {
- var dialog = verto.dialogs[data.params.callID];
-
- if (data.method === "verto.attach" && dialog) {
- delete dialog.verto.dialogs[dialog.callID];
- dialog.rtc.stop();
- dialog = null;
- }
-
- if (dialog) {
-
- switch (data.method) {
- case 'verto.bye':
- dialog.hangup(data.params);
- break;
- case 'verto.answer':
- dialog.handleAnswer(data.params);
- break;
- case 'verto.media':
- dialog.handleMedia(data.params);
- break;
- case 'verto.display':
- dialog.handleDisplay(data.params);
- break;
- case 'verto.info':
- dialog.handleInfo(data.params);
- break;
- default:
- console.debug("INVALID METHOD OR NON-EXISTANT CALL REFERENCE IGNORED", dialog, data.method);
- break;
- }
- } else {
-
- switch (data.method) {
- case 'verto.attach':
- data.params.attach = true;
-
- if (data.params.sdp && data.params.sdp.indexOf("m=video") > 0) {
- data.params.useVideo = true;
- }
-
- if (data.params.sdp && data.params.sdp.indexOf("stereo=1") > 0) {
- data.params.useStereo = true;
- }
-
- dialog = new $.verto.dialog($.verto.enum.direction.inbound, verto, data.params);
- dialog.setState($.verto.enum.state.recovering);
-
- break;
- case 'verto.invite':
-
- if (data.params.sdp && data.params.sdp.indexOf("m=video") > 0) {
- data.params.wantVideo = true;
- }
-
- if (data.params.sdp && data.params.sdp.indexOf("stereo=1") > 0) {
- data.params.useStereo = true;
- }
-
- dialog = new $.verto.dialog($.verto.enum.direction.inbound, verto, data.params);
- break;
- default:
- console.debug("INVALID METHOD OR NON-EXISTANT CALL REFERENCE IGNORED");
- break;
- }
- }
-
- return {
- method: data.method
- };
- } else {
- switch (data.method) {
- case 'verto.punt':
- verto.purge();
- verto.logout();
- break;
- case 'verto.event':
- var list = null;
- var key = null;
-
- if (data.params) {
- key = data.params.eventChannel;
- }
-
- if (key) {
- list = verto.eventSUBS[key];
-
- if (!list) {
- list = verto.eventSUBS[key.split(".")[0]];
- }
- }
-
- if (!list && key && key === verto.sessid) {
- if (verto.callbacks.onMessage) {
- verto.callbacks.onMessage(verto, null, $.verto.enum.message.pvtEvent, data.params);
- }
- } else if (!list && key && verto.dialogs[key]) {
- verto.dialogs[key].sendMessage($.verto.enum.message.pvtEvent, data.params);
- } else if (!list) {
- if (!key) {
- key = "UNDEFINED";
- }
- console.error("UNSUBBED or invalid EVENT " + key + " IGNORED");
- } else {
- for (var i in list) {
- var sub = list[i];
-
- if (!sub || !sub.ready) {
- console.error("invalid EVENT for " + key + " IGNORED");
- } else if (sub.handler) {
- sub.handler(verto, data.params, sub.userData);
- } else if (verto.callbacks.onEvent) {
- verto.callbacks.onEvent(verto, data.params, sub.userData);
- } else {
- console.log("EVENT:", data.params);
- }
- }
- }
-
- break;
-
- case "verto.info":
- if (verto.callbacks.onMessage) {
- verto.callbacks.onMessage(verto, null, $.verto.enum.message.info, data.params.msg);
- }
- //console.error(data);
- console.debug("MESSAGE from: " + data.params.msg.from, data.params.msg.body);
-
- break;
-
- case 'verto.clientReady':
- if (verto.callbacks.onMessage) {
- verto.callbacks.onMessage(verto, null, $.verto.enum.message.clientReady, data.params);
- }
- console.debug("CLIENT READY", data.params);
- break;
-
- default:
- console.error("INVALID METHOD OR NON-EXISTANT CALL REFERENCE IGNORED", data.method);
- break;
- }
- }
- };
-
- var del_array = function(array, name) {
- var r = [];
- var len = array.length;
-
- for (var i = 0; i < len; i++) {
- if (array[i] != name) {
- r.push(array[i]);
- }
- }
-
- return r;
- };
-
- var hashArray = function() {
- var vha = this;
-
- var hash = {};
- var array = [];
-
- vha.reorder = function(a) {
- array = a;
- var h = hash;
- hash = {};
-
- var len = array.length;
-
- for (var i = 0; i < len; i++) {
- var key = array[i];
- if (h[key]) {
- hash[key] = h[key];
- delete h[key];
- }
- }
- h = undefined;
- };
-
- vha.clear = function() {
- hash = undefined;
- array = undefined;
- hash = {};
- array = [];
- };
-
- vha.add = function(name, val, insertAt) {
- var redraw = false;
-
- if (!hash[name]) {
- if (insertAt === undefined || insertAt < 0 || insertAt >= array.length) {
- array.push(name);
- } else {
- var x = 0;
- var n = [];
- var len = array.length;
-
- for (var i = 0; i < len; i++) {
- if (x++==insertAt) {
- n.push(name);
- }
- n.push(array[i]);
- }
-
- array = undefined;
- array = n;
- n = undefined;
- redraw = true;
- }
- }
-
- hash[name] = val;
-
- return redraw;
- };
-
- vha.del = function(name) {
- var r = false;
-
- if (hash[name]) {
- array = del_array(array, name);
- delete hash[name];
- r = true;
- } else {
- console.error("can't del nonexistant key " + name);
- }
-
- return r;
- };
-
- vha.get = function(name) {
- return hash[name];
- };
-
- vha.order = function() {
- return array;
- };
-
- vha.hash = function() {
- return hash;
- };
-
- vha.indexOf = function(name) {
- var len = array.length;
-
- for (var i = 0; i < len; i++) {
- if (array[i] == name) {
- return i;
- }
- }
- };
-
- vha.arrayLen = function() {
- return array.length;
- };
-
- vha.asArray = function() {
- var r = [];
-
- var len = array.length;
-
- for (var i = 0; i < len; i++) {
- var key = array[i];
- r.push(hash[key]);
- }
-
- return r;
- };
-
- vha.each = function(cb) {
- var len = array.length;
-
- for (var i = 0; i < len; i++) {
- cb(array[i], hash[array[i]]);
- }
- };
-
- vha.dump = function(html) {
- var str = "";
-
- vha.each(function(name, val) {
- str += "name: " + name + " val: " + JSON.stringify(val) + (html ? " " : "\n");
- });
-
- return str;
- };
-
- };
-
- $.verto.liveArray = function(verto, context, name, config) {
- var la = this;
- var lastSerno = 0;
- var binding = null;
- var user_obj = config.userObj;
- var local = false;
-
- // Inherit methods of hashArray
- hashArray.call(la);
-
- // Save the hashArray add, del, reorder, clear methods so we can make our own.
- la._add = la.add;
- la._del = la.del;
- la._reorder = la.reorder;
- la._clear = la.clear;
-
- la.context = context;
- la.name = name;
- la.user_obj = user_obj;
-
- la.verto = verto;
- la.broadcast = function(channel, obj) {
- verto.broadcast(channel, obj);
- };
- la.errs = 0;
-
- la.clear = function() {
- la._clear();
- lastSerno = 0;
-
- if (la.onChange) {
- la.onChange(la, {
- action: "clear"
- });
- }
- };
-
- la.checkSerno = function(serno) {
- if (serno < 0) {
- return true;
- }
-
- if (lastSerno > 0 && serno != (lastSerno + 1)) {
- if (la.onErr) {
- la.onErr(la, {
- lastSerno: lastSerno,
- serno: serno
- });
- }
- la.errs++;
- console.debug(la.errs);
- if (la.errs < 3) {
- la.bootstrap(la.user_obj);
- }
- return false;
- } else {
- lastSerno = serno;
- return true;
- }
- };
-
- la.reorder = function(serno, a) {
- if (la.checkSerno(serno)) {
- la._reorder(a);
- if (la.onChange) {
- la.onChange(la, {
- serno: serno,
- action: "reorder"
- });
- }
- }
- };
-
- la.init = function(serno, val, key, index) {
- if (key === null || key === undefined) {
- key = serno;
- }
- if (la.checkSerno(serno)) {
- if (la.onChange) {
- la.onChange(la, {
- serno: serno,
- action: "init",
- index: index,
- key: key,
- data: val
- });
- }
- }
- };
-
- la.bootObj = function(serno, val) {
- if (la.checkSerno(serno)) {
-
- //la.clear();
- for (var i in val) {
- la._add(val[i][0], val[i][1]);
- }
-
- if (la.onChange) {
- la.onChange(la, {
- serno: serno,
- action: "bootObj",
- data: val,
- redraw: true
- });
- }
- }
- };
-
- // @param serno La is the serial number for la particular request.
- // @param key If looking at it as a hash table, la represents the key in the hashArray object where you want to store the val object.
- // @param index If looking at it as an array, la represents the position in the array where you want to store the val object.
- // @param val La is the object you want to store at the key or index location in the hash table / array.
- la.add = function(serno, val, key, index) {
- if (key === null || key === undefined) {
- key = serno;
- }
- if (la.checkSerno(serno)) {
- var redraw = la._add(key, val, index);
- if (la.onChange) {
- la.onChange(la, {
- serno: serno,
- action: "add",
- index: index,
- key: key,
- data: val,
- redraw: redraw
- });
- }
- }
- };
-
- la.modify = function(serno, val, key, index) {
- if (key === null || key === undefined) {
- key = serno;
- }
- if (la.checkSerno(serno)) {
- la._add(key, val, index);
- if (la.onChange) {
- la.onChange(la, {
- serno: serno,
- action: "modify",
- key: key,
- data: val,
- index: index
- });
- }
- }
- };
-
- la.del = function(serno, key, index) {
- if (key === null || key === undefined) {
- key = serno;
- }
- if (la.checkSerno(serno)) {
- if (index === null || index < 0 || index === undefined) {
- index = la.indexOf(key);
- }
- var ok = la._del(key);
-
- if (ok && la.onChange) {
- la.onChange(la, {
- serno: serno,
- action: "del",
- key: key,
- index: index
- });
- }
- }
- };
-
- var eventHandler = function(v, e, la) {
- var packet = e.data;
-
- //console.error("READ:", packet);
-
- if (packet.name != la.name) {
- return;
- }
-
- switch (packet.action) {
-
- case "init":
- la.init(packet.wireSerno, packet.data, packet.hashKey, packet.arrIndex);
- break;
-
- case "bootObj":
- la.bootObj(packet.wireSerno, packet.data);
- break;
- case "add":
- la.add(packet.wireSerno, packet.data, packet.hashKey, packet.arrIndex);
- break;
-
- case "modify":
- if (! (packet.arrIndex || packet.hashKey)) {
- console.error("Invalid Packet", packet);
- } else {
- la.modify(packet.wireSerno, packet.data, packet.hashKey, packet.arrIndex);
- }
- break;
- case "del":
- if (! (packet.arrIndex || packet.hashKey)) {
- console.error("Invalid Packet", packet);
- } else {
- la.del(packet.wireSerno, packet.hashKey, packet.arrIndex);
- }
- break;
-
- case "clear":
- la.clear();
- break;
-
- case "reorder":
- la.reorder(packet.wireSerno, packet.order);
- break;
-
- default:
- if (la.checkSerno(packet.wireSerno)) {
- if (la.onChange) {
- la.onChange(la, {
- serno: packet.wireSerno,
- action: packet.action,
- data: packet.data
- });
- }
- }
- break;
- }
- };
-
- if (la.context) {
- binding = la.verto.subscribe(la.context, {
- handler: eventHandler,
- userData: la,
- subParams: config.subParams
- });
- }
-
- la.destroy = function() {
- la._clear();
- la.verto.unsubscribe(binding);
- };
-
- la.sendCommand = function(cmd, obj) {
- var self = la;
- self.broadcast(self.context, {
- liveArray: {
- command: cmd,
- context: self.context,
- name: self.name,
- obj: obj
- }
- });
- };
-
- la.bootstrap = function(obj) {
- var self = la;
- la.sendCommand("bootstrap", obj);
- //self.heartbeat();
- };
-
- la.changepage = function(obj) {
- var self = la;
- self.clear();
- self.broadcast(self.context, {
- liveArray: {
- command: "changepage",
- context: la.context,
- name: la.name,
- obj: obj
- }
- });
- };
-
- la.heartbeat = function(obj) {
- var self = la;
-
- var callback = function() {
- self.heartbeat.call(self, obj);
- };
- self.broadcast(self.context, {
- liveArray: {
- command: "heartbeat",
- context: self.context,
- name: self.name,
- obj: obj
- }
- });
- self.hb_pid = setTimeout(callback, 30000);
- };
-
- la.bootstrap(la.user_obj);
- };
-
- $.verto.liveTable = function(verto, context, name, jq, config) {
- var dt;
- var la = new $.verto.liveArray(verto, context, name, {
- subParams: config.subParams
- });
- var lt = this;
-
- lt.liveArray = la;
- lt.dataTable = dt;
- lt.verto = verto;
-
- lt.destroy = function() {
- if (dt) {
- dt.fnDestroy();
- }
- if (la) {
- la.destroy();
- }
-
- dt = null;
- la = null;
- };
-
- la.onErr = function(obj, args) {
- console.error("Error: ", obj, args);
- };
-
- /* back compat so jsonstatus can always be enabled */
- function genRow(data) {
- if (typeof(data[4]) === "string" && data[4].indexOf("{") > -1) {
- var tmp = $.parseJSON(data[4]);
- data[4] = tmp.oldStatus;
- data[5] = null;
- }
- return data;
- }
-
- function genArray(obj) {
- var data = obj.asArray();
-
- for (var i in data) {
- data[i] = genRow(data[i]);
- }
-
- return data;
- }
-
-
- la.onChange = function(obj, args) {
- var index = 0;
- var iserr = 0;
-
- if (!dt) {
- if (!config.aoColumns) {
- if (args.action != "init") {
- return;
- }
-
- config.aoColumns = [];
-
- for (var i in args.data) {
- config.aoColumns.push({
- "sTitle": args.data[i]
- });
- }
- }
-
- dt = jq.dataTable(config);
- }
-
- if (dt && (args.action == "del" || args.action == "modify")) {
- index = args.index;
-
- if (index === undefined && args.key) {
- index = la.indexOf(args.key);
- }
-
- if (index === undefined) {
- console.error("INVALID PACKET Missing INDEX\n", args);
- return;
- }
- }
-
- if (config.onChange) {
- config.onChange(obj, args);
- }
-
- try {
- switch (args.action) {
- case "bootObj":
- if (!args.data) {
- console.error("missing data");
- return;
- }
- dt.fnClearTable();
- dt.fnAddData(genArray(obj));
- dt.fnAdjustColumnSizing();
- break;
- case "add":
- if (!args.data) {
- console.error("missing data");
- return;
- }
- if (args.redraw > -1) {
- // specific position, more costly
- dt.fnClearTable();
- dt.fnAddData(genArray(obj));
- } else {
- dt.fnAddData(genRow(args.data));
- }
- dt.fnAdjustColumnSizing();
- break;
- case "modify":
- if (!args.data) {
- return;
- }
- //console.debug(args, index);
- dt.fnUpdate(genRow(args.data), index);
- dt.fnAdjustColumnSizing();
- break;
- case "del":
- dt.fnDeleteRow(index);
- dt.fnAdjustColumnSizing();
- break;
- case "clear":
- dt.fnClearTable();
- break;
- case "reorder":
- // specific position, more costly
- dt.fnClearTable();
- dt.fnAddData(genArray(obj));
- break;
- case "hide":
- jq.hide();
- break;
-
- case "show":
- jq.show();
- break;
-
- }
- } catch(err) {
- console.error("ERROR: " + err);
- iserr++;
- }
-
- if (iserr) {
- obj.errs++;
- if (obj.errs < 3) {
- obj.bootstrap(obj.user_obj);
- }
- } else {
- obj.errs = 0;
- }
-
- };
-
- la.onChange(la, {
- action: "init"
- });
-
- };
-
- var CONFMAN_SERNO = 1;
-
- /*
- Conference Manager without jQuery table.
- */
-
- $.verto.conf = function(verto, params) {
- var conf = this;
-
- conf.params = $.extend({
- dialog: null,
- hasVid: false,
- laData: null,
- onBroadcast: null,
- onLaChange: null,
- onLaRow: null
- }, params);
-
- conf.verto = verto;
- conf.serno = CONFMAN_SERNO++;
-
- createMainModeratorMethods();
-
- verto.subscribe(conf.params.laData.modChannel, {
- handler: function(v, e) {
- if (conf.params.onBroadcast) {
- conf.params.onBroadcast(verto, conf, e.data);
- }
- }
- });
-
- verto.subscribe(conf.params.laData.infoChannel, {
- handler: function(v, e) {
- if (typeof(conf.params.infoCallback) === "function") {
- conf.params.infoCallback(v,e);
- }
- }
- });
-
- verto.subscribe(conf.params.laData.chatChannel, {
- handler: function(v, e) {
- if (typeof(conf.params.chatCallback) === "function") {
- conf.params.chatCallback(v,e);
- }
- }
- });
- };
-
- $.verto.conf.prototype.modCommand = function(cmd, id, value) {
- var conf = this;
-
- conf.verto.rpcClient.call("verto.broadcast", {
- "eventChannel": conf.params.laData.modChannel,
- "data": {
- "application": "conf-control",
- "command": cmd,
- "id": id,
- "value": value
- }
- });
- };
-
- $.verto.conf.prototype.destroy = function() {
- var conf = this;
-
- conf.destroyed = true;
- conf.params.onBroadcast(conf.verto, conf, 'destroy');
-
- if (conf.params.laData.modChannel) {
- conf.verto.unsubscribe(conf.params.laData.modChannel);
- }
-
- if (conf.params.laData.chatChannel) {
- conf.verto.unsubscribe(conf.params.laData.chatChannel);
- }
-
- if (conf.params.laData.infoChannel) {
- conf.verto.unsubscribe(conf.params.laData.infoChannel);
- }
- };
-
- function createMainModeratorMethods() {
- $.verto.conf.prototype.listVideoLayouts = function() {
- this.modCommand("list-videoLayouts", null, null);
- };
-
- $.verto.conf.prototype.play = function(file) {
- this.modCommand("play", null, file);
- };
-
- $.verto.conf.prototype.stop = function() {
- this.modCommand("stop", null, "all");
- };
-
- $.verto.conf.prototype.deaf = function(memberID) {
- this.modCommand("deaf", parseInt(memberID));
- };
-
- $.verto.conf.prototype.undeaf = function(memberID) {
- this.modCommand("undeaf", parseInt(memberID));
- };
-
- $.verto.conf.prototype.record = function(file) {
- this.modCommand("recording", null, ["start", file]);
- };
-
- $.verto.conf.prototype.stopRecord = function() {
- this.modCommand("recording", null, ["stop", "all"]);
- };
-
- $.verto.conf.prototype.snapshot = function(file) {
- if (!this.params.hasVid) {
- throw 'Conference has no video';
- }
- this.modCommand("vid-write-png", null, file);
- };
-
- $.verto.conf.prototype.setVideoLayout = function(layout, canvasID) {
- if (!this.params.hasVid) {
- throw 'Conference has no video';
- }
- if (canvasID) {
- this.modCommand("vid-layout", null, [layout, canvasID]);
- } else {
- this.modCommand("vid-layout", null, layout);
- }
- };
-
- $.verto.conf.prototype.kick = function(memberID) {
- this.modCommand("kick", parseInt(memberID));
- };
-
- $.verto.conf.prototype.muteMic = function(memberID) {
- this.modCommand("tmute", parseInt(memberID));
- };
-
- $.verto.conf.prototype.muteVideo = function(memberID) {
- if (!this.params.hasVid) {
- throw 'Conference has no video';
- }
- this.modCommand("tvmute", parseInt(memberID));
- };
-
- $.verto.conf.prototype.presenter = function(memberID) {
- if (!this.params.hasVid) {
- throw 'Conference has no video';
- }
- this.modCommand("vid-res-id", parseInt(memberID), "presenter");
- };
-
- $.verto.conf.prototype.videoFloor = function(memberID) {
- if (!this.params.hasVid) {
- throw 'Conference has no video';
- }
- this.modCommand("vid-floor", parseInt(memberID), "force");
- };
-
- $.verto.conf.prototype.banner = function(memberID, text) {
- if (!this.params.hasVid) {
- throw 'Conference has no video';
- }
- this.modCommand("vid-banner", parseInt(memberID), escape(text));
- };
-
- $.verto.conf.prototype.volumeDown = function(memberID) {
- this.modCommand("volume_out", parseInt(memberID), "down");
- };
-
- $.verto.conf.prototype.volumeUp = function(memberID) {
- this.modCommand("volume_out", parseInt(memberID), "up");
- };
-
- $.verto.conf.prototype.gainDown = function(memberID) {
- this.modCommand("volume_in", parseInt(memberID), "down");
- };
-
- $.verto.conf.prototype.gainUp = function(memberID) {
- this.modCommand("volume_in", parseInt(memberID), "up");
- };
-
- $.verto.conf.prototype.transfer = function(memberID, exten) {
- this.modCommand("transfer", parseInt(memberID), exten);
- };
-
- $.verto.conf.prototype.sendChat = function(message, type) {
- var conf = this;
- conf.verto.rpcClient.call("verto.broadcast", {
- "eventChannel": conf.params.laData.chatChannel,
- "data": {
- "action": "send",
- "message": message,
- "type": type
- }
- });
- };
-
- }
-
- $.verto.modfuncs = {};
-
- $.verto.confMan = function(verto, params) {
- var confMan = this;
-
- confMan.params = $.extend({
- tableID: null,
- statusID: null,
- mainModID: null,
- dialog: null,
- hasVid: false,
- laData: null,
- onBroadcast: null,
- onLaChange: null,
- onLaRow: null
- }, params);
-
- confMan.verto = verto;
- confMan.serno = CONFMAN_SERNO++;
- confMan.canvasCount = confMan.params.laData.canvasCount;
-
- function genMainMod(jq) {
- var play_id = "play_" + confMan.serno;
- var stop_id = "stop_" + confMan.serno;
- var recording_id = "recording_" + confMan.serno;
- var snapshot_id = "snapshot_" + confMan.serno;
- var rec_stop_id = "recording_stop" + confMan.serno;
- var div_id = "confman_" + confMan.serno;
-
- var html = " " +
- "Play " +
- "Stop " +
- "Record " +
- "Record Stop " +
- (confMan.params.hasVid ? "PNG Snapshot " : "") +
- "
";
-
- jq.html(html);
-
- $.verto.modfuncs.change_video_layout = function(id, canvas_id) {
- var val = $("#" + id + " option:selected").text();
- if (val !== "none") {
- confMan.modCommand("vid-layout", null, [val, canvas_id]);
- }
- };
-
- if (confMan.params.hasVid) {
- for (var j = 0; j < confMan.canvasCount; j++) {
- var vlayout_id = "confman_vid_layout_" + j + "_" + confMan.serno;
- var vlselect_id = "confman_vl_select_" + j + "_" + confMan.serno;
-
-
- var vlhtml = " " +
- "Video Layout Canvas " + (j+1) +
- " " +
- "
";
- jq.append(vlhtml);
- }
-
- $("#" + snapshot_id).click(function() {
- var file = prompt("Please enter file name", "");
- if (file) {
- confMan.modCommand("vid-write-png", null, file);
- }
- });
- }
-
- $("#" + play_id).click(function() {
- var file = prompt("Please enter file name", "");
- if (file) {
- confMan.modCommand("play", null, file);
- }
- });
-
- $("#" + stop_id).click(function() {
- confMan.modCommand("stop", null, "all");
- });
-
- $("#" + recording_id).click(function() {
- var file = prompt("Please enter file name", "");
- if (file) {
- confMan.modCommand("recording", null, ["start", file]);
- }
- });
-
- $("#" + rec_stop_id).click(function() {
- confMan.modCommand("recording", null, ["stop", "all"]);
- });
-
- }
-
- function genControls(jq, rowid) {
- var x = parseInt(rowid);
- var kick_id = "kick_" + x;
- var canvas_in_next_id = "canvas_in_next_" + x;
- var canvas_in_prev_id = "canvas_in_prev_" + x;
- var canvas_out_next_id = "canvas_out_next_" + x;
- var canvas_out_prev_id = "canvas_out_prev_" + x;
-
- var canvas_in_set_id = "canvas_in_set_" + x;
- var canvas_out_set_id = "canvas_out_set_" + x;
-
- var layer_set_id = "layer_set_" + x;
- var layer_next_id = "layer_next_" + x;
- var layer_prev_id = "layer_prev_" + x;
-
- var tmute_id = "tmute_" + x;
- var tvmute_id = "tvmute_" + x;
- var vbanner_id = "vbanner_" + x;
- var tvpresenter_id = "tvpresenter_" + x;
- var tvfloor_id = "tvfloor_" + x;
- var box_id = "box_" + x;
- var gainup_id = "gain_in_up" + x;
- var gaindn_id = "gain_in_dn" + x;
- var volup_id = "vol_in_up" + x;
- var voldn_id = "vol_in_dn" + x;
- var transfer_id = "transfer" + x;
-
-
- var html = "";
-
- html += "General Controls
";
-
- html += "Kick " +
- "Mute " +
- "Gain - " +
- "Gain + " +
- "Vol - " +
- "Vol + " +
- "Transfer ";
-
- if (confMan.params.hasVid) {
- html += "Video Controls ";
-
-
- html += "VMute " +
- "Presenter " +
- "Vid Floor " +
- "Banner ";
-
- if (confMan.canvasCount > 1) {
- html += "Canvas Controls " +
- "Set Input Canvas " +
- "Prev Input Canvas " +
- "Next Input Canvas " +
-
- " " +
-
- "Set Watching Canvas " +
- "Prev Watching Canvas " +
- "Next Watching Canvas ";
- }
-
- html += " " +
-
- "Set Layer " +
- "Prev Layer " +
- "Next Layer " +
-
-
-
- "";
- }
-
- jq.html(html);
-
-
- if (!jq.data("mouse")) {
- $("#" + box_id).hide();
- }
-
- jq.mouseover(function(e) {
- jq.data({"mouse": true});
- $("#" + box_id).show();
- });
-
- jq.mouseout(function(e) {
- jq.data({"mouse": false});
- $("#" + box_id).hide();
- });
-
- $("#" + transfer_id).click(function() {
- var xten = prompt("Enter Extension");
- if (xten) {
- confMan.modCommand("transfer", x, xten);
- }
- });
-
- $("#" + kick_id).click(function() {
- confMan.modCommand("kick", x);
- });
-
-
- $("#" + layer_set_id).click(function() {
- var cid = prompt("Please enter layer ID", "");
- if (cid) {
- confMan.modCommand("vid-layer", x, cid);
- }
- });
-
- $("#" + layer_next_id).click(function() {
- confMan.modCommand("vid-layer", x, "next");
- });
- $("#" + layer_prev_id).click(function() {
- confMan.modCommand("vid-layer", x, "prev");
- });
-
- $("#" + canvas_in_set_id).click(function() {
- var cid = prompt("Please enter canvas ID", "");
- if (cid) {
- confMan.modCommand("vid-canvas", x, cid);
- }
- });
-
- $("#" + canvas_out_set_id).click(function() {
- var cid = prompt("Please enter canvas ID", "");
- if (cid) {
- confMan.modCommand("vid-watching-canvas", x, cid);
- }
- });
-
- $("#" + canvas_in_next_id).click(function() {
- confMan.modCommand("vid-canvas", x, "next");
- });
- $("#" + canvas_in_prev_id).click(function() {
- confMan.modCommand("vid-canvas", x, "prev");
- });
-
-
- $("#" + canvas_out_next_id).click(function() {
- confMan.modCommand("vid-watching-canvas", x, "next");
- });
- $("#" + canvas_out_prev_id).click(function() {
- confMan.modCommand("vid-watching-canvas", x, "prev");
- });
-
- $("#" + tmute_id).click(function() {
- confMan.modCommand("tmute", x);
- });
-
- if (confMan.params.hasVid) {
- $("#" + tvmute_id).click(function() {
- confMan.modCommand("tvmute", x);
- });
- $("#" + tvpresenter_id).click(function() {
- confMan.modCommand("vid-res-id", x, "presenter");
- });
- $("#" + tvfloor_id).click(function() {
- confMan.modCommand("vid-floor", x, "force");
- });
- $("#" + vbanner_id).click(function() {
- var text = prompt("Please enter text", "");
- if (text) {
- confMan.modCommand("vid-banner", x, escape(text));
- }
- });
- }
-
- $("#" + gainup_id).click(function() {
- confMan.modCommand("volume_in", x, "up");
- });
-
- $("#" + gaindn_id).click(function() {
- confMan.modCommand("volume_in", x, "down");
- });
-
- $("#" + volup_id).click(function() {
- confMan.modCommand("volume_out", x, "up");
- });
-
- $("#" + voldn_id).click(function() {
- confMan.modCommand("volume_out", x, "down");
- });
-
- return html;
- }
-
- var atitle = "";
- var awidth = 0;
-
- //$(".jsDataTable").width(confMan.params.hasVid ? "900px" : "800px");
-
- verto.subscribe(confMan.params.laData.infoChannel, {
- handler: function(v, e) {
- if (typeof(confMan.params.infoCallback) === "function") {
- confMan.params.infoCallback(v,e);
- }
- }
- });
-
- verto.subscribe(confMan.params.laData.chatChannel, {
- handler: function(v, e) {
- if (typeof(confMan.params.chatCallback) === "function") {
- confMan.params.chatCallback(v,e);
- }
- }
- });
-
- if (confMan.params.laData.role === "moderator") {
- atitle = "Action";
- awidth = 600;
-
- if (confMan.params.mainModID) {
- genMainMod($(confMan.params.mainModID));
- $(confMan.params.displayID).html("Moderator Controls Ready ");
- } else {
- $(confMan.params.mainModID).html("");
- }
-
- verto.subscribe(confMan.params.laData.modChannel, {
- handler: function(v, e) {
- //console.error("MODDATA:", e.data);
- if (confMan.params.onBroadcast) {
- confMan.params.onBroadcast(verto, confMan, e.data);
- }
-
- if (e.data["conf-command"] === "list-videoLayouts") {
- for (var j = 0; j < confMan.canvasCount; j++) {
- var vlselect_id = "#confman_vl_select_" + j + "_" + confMan.serno;
- var vlayout_id = "#confman_vid_layout_" + j + "_" + confMan.serno;
-
- var x = 0;
- var options;
-
- $(vlselect_id).selectmenu({});
- $(vlselect_id).selectmenu("enable");
- $(vlselect_id).empty();
-
- $(vlselect_id).append(new Option("Choose a Layout", "none"));
-
- if (e.data.responseData) {
- var rdata = [];
-
- for (var i in e.data.responseData) {
- rdata.push(e.data.responseData[i].name);
- }
-
- options = rdata.sort(function(a, b) {
- var ga = a.substring(0, 6) == "group:" ? true : false;
- var gb = b.substring(0, 6) == "group:" ? true : false;
-
- if ((ga || gb) && ga != gb) {
- return ga ? -1 : 1;
- }
-
- return ( ( a == b ) ? 0 : ( ( a > b ) ? 1 : -1 ) );
- });
-
- for (var i in options) {
- $(vlselect_id).append(new Option(options[i], options[i]));
- x++;
- }
- }
-
- if (x) {
- $(vlselect_id).selectmenu('refresh', true);
- } else {
- $(vlayout_id).hide();
- }
- }
- } else {
-
- if (!confMan.destroyed && confMan.params.displayID) {
- $(confMan.params.displayID).html(e.data.response + " ");
- if (confMan.lastTimeout) {
- clearTimeout(confMan.lastTimeout);
- confMan.lastTimeout = 0;
- }
- confMan.lastTimeout = setTimeout(function() { $(confMan.params.displayID).html(confMan.destroyed ? "" : "Moderator Controls Ready ");}, 4000);
- }
- }
- }
- });
-
-
- if (confMan.params.hasVid) {
- confMan.modCommand("list-videoLayouts", null, null);
- }
- }
-
- var row_callback = null;
-
- if (confMan.params.laData.role === "moderator") {
- row_callback = function(nRow, aData, iDisplayIndex, iDisplayIndexFull) {
- if (!aData[5]) {
- var $row = $('td:eq(5)', nRow);
- genControls($row, aData);
-
- if (confMan.params.onLaRow) {
- confMan.params.onLaRow(verto, confMan, $row, aData);
- }
- }
- };
- }
-
- confMan.lt = new $.verto.liveTable(verto, confMan.params.laData.laChannel, confMan.params.laData.laName, $(confMan.params.tableID), {
- subParams: {
- callID: confMan.params.dialog ? confMan.params.dialog.callID : null
- },
-
- "onChange": function(obj, args) {
- $(confMan.params.statusID).text("Conference Members: " + " (" + obj.arrayLen() + " Total)");
- if (confMan.params.onLaChange) {
- confMan.params.onLaChange(verto, confMan, $.verto.enum.confEvent.laChange, obj, args);
- }
- },
-
- "aaData": [],
- "aoColumns": [
- {
- "sTitle": "ID",
- "sWidth": "50"
- },
- {
- "sTitle": "Number",
- "sWidth": "250"
- },
- {
- "sTitle": "Name",
- "sWidth": "250"
- },
- {
- "sTitle": "Codec",
- "sWidth": "100"
- },
- {
- "sTitle": "Status",
- "sWidth": confMan.params.hasVid ? "200px" : "150px"
- },
- {
- "sTitle": atitle,
- "sWidth": awidth,
- }
- ],
- "bAutoWidth": true,
- "bDestroy": true,
- "bSort": false,
- "bInfo": false,
- "bFilter": false,
- "bLengthChange": false,
- "bPaginate": false,
- "iDisplayLength": 1400,
-
- "oLanguage": {
- "sEmptyTable": "The Conference is Empty....."
- },
-
- "fnRowCallback": row_callback
-
- });
- };
-
- $.verto.confMan.prototype.modCommand = function(cmd, id, value) {
- var confMan = this;
-
- confMan.verto.rpcClient.call("verto.broadcast", {
- "eventChannel": confMan.params.laData.modChannel,
- "data": {
- "application": "conf-control",
- "command": cmd,
- "id": id,
- "value": value
- }
- });
- };
-
- $.verto.confMan.prototype.sendChat = function(message, type) {
- var confMan = this;
- confMan.verto.rpcClient.call("verto.broadcast", {
- "eventChannel": confMan.params.laData.chatChannel,
- "data": {
- "action": "send",
- "message": message,
- "type": type
- }
- });
- };
-
-
- $.verto.confMan.prototype.destroy = function() {
- var confMan = this;
-
- confMan.destroyed = true;
-
- if (confMan.lt) {
- confMan.lt.destroy();
- }
-
- if (confMan.params.laData.chatChannel) {
- confMan.verto.unsubscribe(confMan.params.laData.chatChannel);
- }
-
- if (confMan.params.laData.modChannel) {
- confMan.verto.unsubscribe(confMan.params.laData.modChannel);
- }
-
- if (confMan.params.mainModID) {
- $(confMan.params.mainModID).html("");
- }
- };
-
- $.verto.dialog = function(direction, verto, params) {
- var dialog = this;
-
- dialog.params = $.extend({
- useVideo: verto.options.useVideo,
- useStereo: verto.options.useStereo,
- screenShare: false,
- useCamera: false,
- useMic: verto.options.deviceParams.useMic,
- useSpeak: verto.options.deviceParams.useSpeak,
- tag: verto.options.tag,
- localTag: verto.options.localTag,
- login: verto.options.login,
- videoParams: verto.options.videoParams,
- useStream: verto.options.useStream,
- }, params);
-
-
- if (!dialog.params.screenShare) {
- dialog.params.useCamera = verto.options.deviceParams.useCamera;
- }
-
- dialog.verto = verto;
- dialog.direction = direction;
- dialog.lastState = null;
- dialog.state = dialog.lastState = $.verto.enum.state.new;
- dialog.callbacks = verto.callbacks;
- dialog.answered = false;
- dialog.attach = params.attach || false;
- dialog.screenShare = params.screenShare || false;
- dialog.useCamera = dialog.params.useCamera;
- dialog.useMic = dialog.params.useMic;
- dialog.useSpeak = dialog.params.useSpeak;
-
- if (dialog.params.callID) {
- dialog.callID = dialog.params.callID;
- } else {
- dialog.callID = dialog.params.callID = generateGUID();
- }
-
- if (typeof(dialog.params.tag) === "function") {
- dialog.params.tag = dialog.params.tag();
- }
-
- if (dialog.params.tag) {
- dialog.audioStream = document.getElementById(dialog.params.tag);
-
- if (dialog.params.useVideo) {
- dialog.videoStream = dialog.audioStream;
- }
- } //else conjure one TBD
-
- if (dialog.params.localTag) {
- dialog.localVideo = document.getElementById(dialog.params.localTag);
- }
-
- dialog.verto.dialogs[dialog.callID] = dialog;
-
- var RTCcallbacks = {};
-
- if (dialog.direction == $.verto.enum.direction.inbound) {
- if (dialog.params.display_direction === "outbound") {
- dialog.params.remote_caller_id_name = dialog.params.caller_id_name;
- dialog.params.remote_caller_id_number = dialog.params.caller_id_number;
- } else {
- dialog.params.remote_caller_id_name = dialog.params.callee_id_name;
- dialog.params.remote_caller_id_number = dialog.params.callee_id_number;
- }
-
- if (!dialog.params.remote_caller_id_name) {
- dialog.params.remote_caller_id_name = "Nobody";
- }
-
- if (!dialog.params.remote_caller_id_number) {
- dialog.params.remote_caller_id_number = "UNKNOWN";
- }
-
- RTCcallbacks.onMessage = function(rtc, msg) {
- console.debug(msg);
- };
-
- RTCcallbacks.onAnswerSDP = function(rtc, sdp) {
- console.error("answer sdp", sdp);
- };
- } else {
- dialog.params.remote_caller_id_name = "Outbound Call";
- dialog.params.remote_caller_id_number = dialog.params.destination_number;
- }
-
- RTCcallbacks.onICESDP = function(rtc) {
- console.log("RECV " + rtc.type + " SDP", rtc.mediaData.SDP);
-
- if (dialog.state == $.verto.enum.state.requesting || dialog.state == $.verto.enum.state.answering || dialog.state == $.verto.enum.state.active) {
- location.reload();
- return;
- }
-
- if (rtc.type == "offer") {
- if (dialog.state == $.verto.enum.state.active) {
- dialog.setState($.verto.enum.state.requesting);
- dialog.sendMethod("verto.attach", {
- sdp: rtc.mediaData.SDP
- });
- } else {
- dialog.setState($.verto.enum.state.requesting);
-
- dialog.sendMethod("verto.invite", {
- sdp: rtc.mediaData.SDP
- });
- }
- } else { //answer
- dialog.setState($.verto.enum.state.answering);
-
- dialog.sendMethod(dialog.attach ? "verto.attach" : "verto.answer", {
- sdp: dialog.rtc.mediaData.SDP
- });
- }
- };
-
- RTCcallbacks.onICE = function(rtc) {
- //console.log("cand", rtc.mediaData.candidate);
- if (rtc.type == "offer") {
- console.log("offer", rtc.mediaData.candidate);
- return;
- }
- };
-
- RTCcallbacks.onStream = function(rtc, stream) {
- if (dialog.callbacks.permissionCallback &&
- typeof dialog.callbacks.permissionCallback.onGranted === 'function') {
- dialog.callbacks.permissionCallback.onGranted(stream);
- }
- else if (dialog.verto.options.permissionCallback &&
- typeof dialog.verto.options.permissionCallback.onGranted === 'function'){
- dialog.verto.options.permissionCallback.onGranted(stream);
- }
- console.log("stream started");
- };
-
- RTCcallbacks.onRemoteStream = function(rtc, stream) {
- if (typeof dialog.callbacks.onRemoteStream === 'function') {
- dialog.callbacks.onRemoteStream(stream, dialog);
- }
- console.log("remote stream started");
- };
-
- RTCcallbacks.onError = function(e) {
- if (dialog.callbacks.permissionCallback &&
- typeof dialog.callbacks.permissionCallback.onDenied === 'function') {
- dialog.callbacks.permissionCallback.onDenied();
- }
- else if (dialog.verto.options.permissionCallback &&
- typeof dialog.verto.options.permissionCallback.onDenied === 'function'){
- dialog.verto.options.permissionCallback.onDenied();
- }
- console.error("ERROR:", e);
- dialog.hangup({cause: "Device or Permission Error"});
- };
-
- dialog.rtc = new $.FSRTC({
- callbacks: RTCcallbacks,
- localVideo: dialog.screenShare ? null : dialog.localVideo,
- useVideo: dialog.params.useVideo ? dialog.videoStream : null,
- useAudio: dialog.audioStream,
- useStereo: dialog.params.useStereo,
- videoParams: dialog.params.videoParams,
- audioParams: verto.options.audioParams,
- iceServers: verto.options.iceServers,
- screenShare: dialog.screenShare,
- useCamera: dialog.useCamera,
- useMic: dialog.useMic,
- useSpeak: dialog.useSpeak,
- turnServer: verto.options.turnServer,
- useStream: dialog.params.useStream
- });
-
- dialog.rtc.verto = dialog.verto;
-
- if (dialog.direction == $.verto.enum.direction.inbound) {
- if (dialog.attach) {
- dialog.answer();
- } else {
- dialog.ring();
- }
- }
- };
-
- $.verto.dialog.prototype.invite = function() {
- var dialog = this;
- dialog.rtc.call();
- };
-
- $.verto.dialog.prototype.sendMethod = function(method, obj) {
- var dialog = this;
- obj.dialogParams = {};
-
- for (var i in dialog.params) {
- if (i == "sdp" && method != "verto.invite" && method != "verto.attach") {
- continue;
- }
-
- if ((obj.noDialogParams && i != "callID")) {
- continue;
- }
-
- obj.dialogParams[i] = dialog.params[i];
- }
-
- delete obj.noDialogParams;
-
- dialog.verto.rpcClient.call(method, obj,
-
- function(e) {
- /* Success */
- dialog.processReply(method, true, e);
- },
-
- function(e) {
- /* Error */
- dialog.processReply(method, false, e);
- });
- };
-
- function checkStateChange(oldS, newS) {
-
- if (newS == $.verto.enum.state.purge || $.verto.enum.states[oldS.name][newS.name]) {
- return true;
- }
-
- return false;
- }
-
-
- // Attach audio output device to video element using device/sink ID.
- function find_name(id) {
- for (var i in $.verto.audioOutDevices) {
- var source = $.verto.audioOutDevices[i];
- if (source.id === id) {
- return(source.label);
- }
- }
-
- return id;
- }
-
- $.verto.dialog.prototype.setAudioPlaybackDevice = function(sinkId, callback, arg) {
- var dialog = this;
- var element = dialog.audioStream;
-
- if (typeof element.sinkId !== 'undefined') {
- var devname = find_name(sinkId);
- console.info("Dialog: " + dialog.callID + " Setting speaker:", element, devname);
-
- element.setSinkId(sinkId)
- .then(function() {
- console.log("Dialog: " + dialog.callID + ' Success, audio output device attached: ' + sinkId);
- if (callback) {
- callback(true, devname, arg);
- }
- })
- .catch(function(error) {
- var errorMessage = error;
- if (error.name === 'SecurityError') {
- errorMessage = "Dialog: " + dialog.callID + ' You need to use HTTPS for selecting audio output ' +
- 'device: ' + error;
- }
- if (callback) {
- callback(false, null, arg);
- }
- console.error(errorMessage);
- });
- } else {
- console.warn("Dialog: " + dialog.callID + ' Browser does not support output device selection.');
- if (callback) {
- callback(false, null, arg);
- }
- }
- }
-
- $.verto.dialog.prototype.setState = function(state) {
- var dialog = this;
-
- if (dialog.state == $.verto.enum.state.ringing) {
- dialog.stopRinging();
- }
-
- if (dialog.state == state || !checkStateChange(dialog.state, state)) {
- console.error("Dialog " + dialog.callID + ": INVALID state change from " + dialog.state.name + " to " + state.name);
- dialog.hangup();
- return false;
- }
-
- console.log("Dialog " + dialog.callID + ": state change from " + dialog.state.name + " to " + state.name);
-
- dialog.lastState = dialog.state;
- dialog.state = state;
-
- if (dialog.callbacks.onDialogState) {
- dialog.callbacks.onDialogState(this);
- }
-
- switch (dialog.state) {
-
- case $.verto.enum.state.early:
- case $.verto.enum.state.active:
-
- var speaker = dialog.useSpeak;
- console.info("Using Speaker: ", speaker);
-
- if (speaker && speaker !== "any" && speaker !== "none") {
- setTimeout(function() {
- dialog.setAudioPlaybackDevice(speaker);
- }, 500);
- }
-
- break;
-
- case $.verto.enum.state.trying:
- setTimeout(function() {
- if (dialog.state == $.verto.enum.state.trying) {
- dialog.setState($.verto.enum.state.hangup);
- }
- }, 30000);
- break;
- case $.verto.enum.state.purge:
- dialog.setState($.verto.enum.state.destroy);
- break;
- case $.verto.enum.state.hangup:
-
- if (dialog.lastState.val > $.verto.enum.state.requesting.val && dialog.lastState.val < $.verto.enum.state.hangup.val) {
- dialog.sendMethod("verto.bye", {});
- }
-
- dialog.setState($.verto.enum.state.destroy);
- break;
- case $.verto.enum.state.destroy:
-
- if (typeof(dialog.verto.options.tag) === "function") {
- $('#' + dialog.params.tag).remove();
- }
-
- delete dialog.verto.dialogs[dialog.callID];
- if (dialog.params.screenShare) {
- dialog.rtc.stopPeer();
- } else {
- dialog.rtc.stop();
- }
- break;
- }
-
- return true;
- };
-
- $.verto.dialog.prototype.processReply = function(method, success, e) {
- var dialog = this;
-
- //console.log("Response: " + method + " State:" + dialog.state.name, success, e);
-
- switch (method) {
-
- case "verto.answer":
- case "verto.attach":
- if (success) {
- dialog.setState($.verto.enum.state.active);
- } else {
- dialog.hangup();
- }
- break;
- case "verto.invite":
- if (success) {
- dialog.setState($.verto.enum.state.trying);
- } else {
- dialog.setState($.verto.enum.state.destroy);
- }
- break;
-
- case "verto.bye":
- dialog.hangup();
- break;
-
- case "verto.modify":
- if (e.holdState) {
- if (e.holdState == "held") {
- if (dialog.state != $.verto.enum.state.held) {
- dialog.setState($.verto.enum.state.held);
- }
- } else if (e.holdState == "active") {
- if (dialog.state != $.verto.enum.state.active) {
- dialog.setState($.verto.enum.state.active);
- }
- }
- }
-
- if (success) {}
-
- break;
-
- default:
- break;
- }
-
- };
-
- $.verto.dialog.prototype.hangup = function(params) {
- var dialog = this;
-
- if (params) {
- if (params.causeCode) {
- dialog.causeCode = params.causeCode;
- }
-
- if (params.cause) {
- dialog.cause = params.cause;
- }
- }
-
- if (!dialog.cause && !dialog.causeCode) {
- dialog.cause = "NORMAL_CLEARING";
- }
-
- if (dialog.state.val >= $.verto.enum.state.new.val && dialog.state.val < $.verto.enum.state.hangup.val) {
- dialog.setState($.verto.enum.state.hangup);
- } else if (dialog.state.val < $.verto.enum.state.destroy) {
- dialog.setState($.verto.enum.state.destroy);
- }
- };
-
- $.verto.dialog.prototype.stopRinging = function() {
- var dialog = this;
- if (dialog.verto.ringer) {
- dialog.verto.ringer.stop();
- }
- };
-
- $.verto.dialog.prototype.indicateRing = function() {
- var dialog = this;
-
- if (dialog.verto.ringer) {
- dialog.verto.ringer.attr("src", dialog.verto.options.ringFile)[0].play();
-
- setTimeout(function() {
- dialog.stopRinging();
- if (dialog.state == $.verto.enum.state.ringing) {
- dialog.indicateRing();
- }
- },
- dialog.verto.options.ringSleep);
- }
- };
-
- $.verto.dialog.prototype.ring = function() {
- var dialog = this;
-
- dialog.setState($.verto.enum.state.ringing);
- dialog.indicateRing();
- };
-
- $.verto.dialog.prototype.useVideo = function(on) {
- var dialog = this;
-
- dialog.params.useVideo = on;
-
- if (on) {
- dialog.videoStream = dialog.audioStream;
- } else {
- dialog.videoStream = null;
- }
-
- dialog.rtc.useVideo(dialog.videoStream, dialog.localVideo);
-
- };
-
- $.verto.dialog.prototype.setMute = function(what) {
- var dialog = this;
- return dialog.rtc.setMute(what);
- };
-
- $.verto.dialog.prototype.getMute = function() {
- var dialog = this;
- return dialog.rtc.getMute();
- };
-
- $.verto.dialog.prototype.setVideoMute = function(what) {
- var dialog = this;
- return dialog.rtc.setVideoMute(what);
- };
-
- $.verto.dialog.prototype.getVideoMute = function() {
- var dialog = this;
- return dialog.rtc.getVideoMute();
- };
-
- $.verto.dialog.prototype.useStereo = function(on) {
- var dialog = this;
-
- dialog.params.useStereo = on;
- dialog.rtc.useStereo(on);
- };
-
- $.verto.dialog.prototype.dtmf = function(digits) {
- var dialog = this;
- if (digits) {
- dialog.sendMethod("verto.info", {
- dtmf: digits
- });
- }
- };
-
- $.verto.dialog.prototype.rtt = function(obj) {
- var dialog = this;
- var pobj = {};
-
- if (!obj) {
- return false;
- }
-
- pobj.code = obj.code;
- pobj.chars = obj.chars;
-
-
- if (pobj.chars || pobj.code) {
- dialog.sendMethod("verto.info", {
- txt: obj,
- noDialogParams: true
- });
- }
- };
-
- $.verto.dialog.prototype.transfer = function(dest, params) {
- var dialog = this;
- if (dest) {
- dialog.sendMethod("verto.modify", {
- action: "transfer",
- destination: dest,
- params: params
- });
- }
- };
-
- $.verto.dialog.prototype.replace = function(replaceCallID, params) {
- var dialog = this;
- if (replaceCallID) {
- dialog.sendMethod("verto.modify", {
- action: "replace",
- replaceCallID: replaceCallID,
- params: params
- });
- }
- };
-
- $.verto.dialog.prototype.hold = function(params) {
- var dialog = this;
-
- dialog.sendMethod("verto.modify", {
- action: "hold",
- params: params
- });
- };
-
- $.verto.dialog.prototype.unhold = function(params) {
- var dialog = this;
-
- dialog.sendMethod("verto.modify", {
- action: "unhold",
- params: params
- });
- };
-
- $.verto.dialog.prototype.toggleHold = function(params) {
- var dialog = this;
-
- dialog.sendMethod("verto.modify", {
- action: "toggleHold",
- params: params
- });
- };
-
- $.verto.dialog.prototype.message = function(msg) {
- var dialog = this;
- var err = 0;
-
- msg.from = dialog.params.login;
-
- if (!msg.to) {
- console.error("Missing To");
- err++;
- }
-
- if (!msg.body) {
- console.error("Missing Body");
- err++;
- }
-
- if (err) {
- return false;
- }
-
- dialog.sendMethod("verto.info", {
- msg: msg
- });
-
- return true;
- };
-
- $.verto.dialog.prototype.answer = function(params) {
- var dialog = this;
-
- if (!dialog.answered) {
- if (!params) {
- params = {};
- }
-
- params.sdp = dialog.params.sdp;
-
- if (params) {
- if (params.useVideo) {
- dialog.useVideo(true);
- }
- dialog.params.callee_id_name = params.callee_id_name;
- dialog.params.callee_id_number = params.callee_id_number;
-
- if (params.useCamera) {
- dialog.useCamera = params.useCamera;
- }
-
- if (params.useMic) {
- dialog.useMic = params.useMic;
- }
-
- if (params.useSpeak) {
- dialog.useSpeak = params.useSpeak;
- }
- }
-
- dialog.rtc.createAnswer(params);
- dialog.answered = true;
- }
- };
-
- $.verto.dialog.prototype.handleAnswer = function(params) {
- var dialog = this;
-
- dialog.gotAnswer = true;
-
- if (dialog.state.val >= $.verto.enum.state.active.val) {
- return;
- }
-
- if (dialog.state.val >= $.verto.enum.state.early.val) {
- dialog.setState($.verto.enum.state.active);
- } else {
- if (dialog.gotEarly) {
- console.log("Dialog " + dialog.callID + " Got answer while still establishing early media, delaying...");
- } else {
- console.log("Dialog " + dialog.callID + " Answering Channel");
- dialog.rtc.answer(params.sdp, function() {
- dialog.setState($.verto.enum.state.active);
- }, function(e) {
- console.error(e);
- dialog.hangup();
- });
- console.log("Dialog " + dialog.callID + "ANSWER SDP", params.sdp);
- }
- }
-
-
- };
-
- $.verto.dialog.prototype.cidString = function(enc) {
- var dialog = this;
- var party = dialog.params.remote_caller_id_name + (enc ? " <" : " <") + dialog.params.remote_caller_id_number + (enc ? ">" : ">");
- return party;
- };
-
- $.verto.dialog.prototype.sendMessage = function(msg, params) {
- var dialog = this;
-
- if (dialog.callbacks.onMessage) {
- dialog.callbacks.onMessage(dialog.verto, dialog, msg, params);
- }
- };
-
- $.verto.dialog.prototype.handleInfo = function(params) {
- var dialog = this;
-
- dialog.sendMessage($.verto.enum.message.info, params);
-
- };
-
- $.verto.dialog.prototype.handleDisplay = function(params) {
- var dialog = this;
-
- if (params.display_name) {
- dialog.params.remote_caller_id_name = params.display_name;
- }
- if (params.display_number) {
- dialog.params.remote_caller_id_number = params.display_number;
- }
-
- dialog.sendMessage($.verto.enum.message.display, {});
- };
-
- $.verto.dialog.prototype.handleMedia = function(params) {
- var dialog = this;
-
- if (dialog.state.val >= $.verto.enum.state.early.val) {
- return;
- }
-
- dialog.gotEarly = true;
-
- dialog.rtc.answer(params.sdp, function() {
- console.log("Dialog " + dialog.callID + "Establishing early media");
- dialog.setState($.verto.enum.state.early);
-
- if (dialog.gotAnswer) {
- console.log("Dialog " + dialog.callID + "Answering Channel");
- dialog.setState($.verto.enum.state.active);
- }
- }, function(e) {
- console.error(e);
- dialog.hangup();
- });
- console.log("Dialog " + dialog.callID + "EARLY SDP", params.sdp);
- };
-
- $.verto.ENUM = function(s) {
- var i = 0,
- o = {};
- s.split(" ").map(function(x) {
- o[x] = {
- name: x,
- val: i++
- };
- });
- return Object.freeze(o);
- };
-
- $.verto.enum = {};
-
- $.verto.enum.states = Object.freeze({
- new: {
- requesting: 1,
- recovering: 1,
- ringing: 1,
- destroy: 1,
- answering: 1,
- hangup: 1
- },
- requesting: {
- trying: 1,
- hangup: 1,
- active: 1
- },
- recovering: {
- answering: 1,
- hangup: 1
- },
- trying: {
- active: 1,
- early: 1,
- hangup: 1
- },
- ringing: {
- answering: 1,
- hangup: 1
- },
- answering: {
- active: 1,
- hangup: 1
- },
- active: {
- answering: 1,
- requesting: 1,
- hangup: 1,
- held: 1
- },
- held: {
- hangup: 1,
- active: 1
- },
- early: {
- hangup: 1,
- active: 1
- },
- hangup: {
- destroy: 1
- },
- destroy: {},
- purge: {
- destroy: 1
- }
- });
-
- $.verto.enum.state = $.verto.ENUM("new requesting trying recovering ringing answering early active held hangup destroy purge");
- $.verto.enum.direction = $.verto.ENUM("inbound outbound");
- $.verto.enum.message = $.verto.ENUM("display info pvtEvent clientReady");
-
- $.verto.enum = Object.freeze($.verto.enum);
-
- $.verto.saved = [];
-
- $.verto.unloadJobs = [];
-
- var unloadEventName = 'beforeunload';
- // Hacks for Mobile Safari
- var iOS = ['iPad', 'iPhone', 'iPod'].indexOf(navigator.platform) >= 0;
- if (iOS) {
- unloadEventName = 'pagehide';
- }
-
- $(window).bind(unloadEventName, function() {
- for (var f in $.verto.unloadJobs) {
- $.verto.unloadJobs[f]();
- }
-
- if ($.verto.haltClosure)
- return $.verto.haltClosure();
-
- for (var i in $.verto.saved) {
- var verto = $.verto.saved[i];
- if (verto) {
- verto.purge();
- verto.logout();
- }
- }
-
- return $.verto.warnOnUnload;
- });
-
- $.verto.videoDevices = [];
- $.verto.audioInDevices = [];
- $.verto.audioOutDevices = [];
-
- var checkDevices = function(runtime) {
- console.info("enumerating devices");
- var aud_in = [], aud_out = [], vid = [];
- var has_video = 0, has_audio = 0;
- var Xstream;
-
- function gotDevices(deviceInfos) {
- // Handles being called several times to update labels. Preserve values.
- for (var i = 0; i !== deviceInfos.length; ++i) {
- var deviceInfo = deviceInfos[i];
- var text = "";
-
- console.log(deviceInfo);
- console.log(deviceInfo.kind + ": " + deviceInfo.label + " id = " + deviceInfo.deviceId);
-
- if (deviceInfo.kind === 'audioinput') {
- text = deviceInfo.label || 'microphone ' + (aud_in.length + 1);
- aud_in.push({id: deviceInfo.deviceId, kind: "audio_in", label: text});
- } else if (deviceInfo.kind === 'audiooutput') {
- text = deviceInfo.label || 'speaker ' + (aud_out.length + 1);
- aud_out.push({id: deviceInfo.deviceId, kind: "audio_out", label: text});
- } else if (deviceInfo.kind === 'videoinput') {
- text = deviceInfo.label || 'camera ' + (vid.length + 1);
- vid.push({id: deviceInfo.deviceId, kind: "video", label: text});
- } else {
- console.log('Some other kind of source/device: ', deviceInfo);
- }
- }
-
-
- $.verto.videoDevices = vid;
- $.verto.audioInDevices = aud_in;
- $.verto.audioOutDevices = aud_out;
-
- console.info("Audio IN Devices", $.verto.audioInDevices);
- console.info("Audio Out Devices", $.verto.audioOutDevices);
- console.info("Video Devices", $.verto.videoDevices);
-
- if (Xstream) {
- Xstream.getTracks().forEach(function(track) {track.stop();});
- }
-
- if (runtime) {
- runtime(true);
- }
- }
-
-
-
-
- function handleError(error) {
- console.log('device enumeration error: ', error);
- if (runtime) runtime(false);
- }
-
-
- function checkTypes(devs) {
- for (var i = 0; i !== devs.length; ++i) {
-
- if (devs[i].kind === 'audioinput') {
- has_audio++;
- } else if (devs[i].kind === 'videoinput') {
- has_video++;
- }
- }
-
- navigator.getUserMedia({ audio: (has_audio > 0 ? true : false), video: (has_video > 0 ? true : false)},
- function(stream) {
- Xstream = stream;
- navigator.mediaDevices.enumerateDevices().then(gotDevices).catch(handleError);
- },
- function(err) {
- console.log("The following error occurred: " + err.name);
- }
- );
- }
-
- navigator.mediaDevices.enumerateDevices().then(checkTypes).catch(handleError);
-
- };
-
- $.verto.refreshDevices = function(runtime) {
- checkDevices(runtime);
- }
-
- $.verto.init = function(obj, runtime) {
- if (!obj) {
- obj = {};
- }
-
- if (!obj.skipPermCheck && !obj.skipDeviceCheck) {
- $.FSRTC.checkPerms(function(status) {
- checkDevices(runtime);
- }, true, true);
- } else if (obj.skipPermCheck && !obj.skipDeviceCheck) {
- checkDevices(runtime);
- } else if (!obj.skipPermCheck && obj.skipDeviceCheck) {
- $.FSRTC.checkPerms(function(status) {
- runtime(status);
- }, true, true);
- } else {
- runtime(null);
- }
-
- }
-
- $.verto.genUUID = function () {
- return generateGUID();
- }
-
-
-})(jQuery);
-(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.adapter = 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= 14393 &&
- url.indexOf('?transport=udp') === -1;
- });
-
- delete server.url;
- server.urls = isString ? urls[0] : urls;
- return !!urls.length;
- }
- });
-}
-
-// Determines the intersection of local and remote capabilities.
-function getCommonCapabilities(localCapabilities, remoteCapabilities) {
- var commonCapabilities = {
- codecs: [],
- headerExtensions: [],
- fecMechanisms: []
- };
-
- var findCodecByPayloadType = function(pt, codecs) {
- pt = parseInt(pt, 10);
- for (var i = 0; i < codecs.length; i++) {
- if (codecs[i].payloadType === pt ||
- codecs[i].preferredPayloadType === pt) {
- return codecs[i];
- }
- }
- };
-
- var rtxCapabilityMatches = function(lRtx, rRtx, lCodecs, rCodecs) {
- var lCodec = findCodecByPayloadType(lRtx.parameters.apt, lCodecs);
- var rCodec = findCodecByPayloadType(rRtx.parameters.apt, rCodecs);
- return lCodec && rCodec &&
- lCodec.name.toLowerCase() === rCodec.name.toLowerCase();
- };
-
- localCapabilities.codecs.forEach(function(lCodec) {
- for (var i = 0; i < remoteCapabilities.codecs.length; i++) {
- var rCodec = remoteCapabilities.codecs[i];
- if (lCodec.name.toLowerCase() === rCodec.name.toLowerCase() &&
- lCodec.clockRate === rCodec.clockRate) {
- if (lCodec.name.toLowerCase() === 'rtx' &&
- lCodec.parameters && rCodec.parameters.apt) {
- // for RTX we need to find the local rtx that has a apt
- // which points to the same local codec as the remote one.
- if (!rtxCapabilityMatches(lCodec, rCodec,
- localCapabilities.codecs, remoteCapabilities.codecs)) {
- continue;
- }
- }
- rCodec = JSON.parse(JSON.stringify(rCodec)); // deepcopy
- // number of channels is the highest common number of channels
- rCodec.numChannels = Math.min(lCodec.numChannels,
- rCodec.numChannels);
- // push rCodec so we reply with offerer payload type
- commonCapabilities.codecs.push(rCodec);
-
- // determine common feedback mechanisms
- rCodec.rtcpFeedback = rCodec.rtcpFeedback.filter(function(fb) {
- for (var j = 0; j < lCodec.rtcpFeedback.length; j++) {
- if (lCodec.rtcpFeedback[j].type === fb.type &&
- lCodec.rtcpFeedback[j].parameter === fb.parameter) {
- return true;
- }
- }
- return false;
- });
- // FIXME: also need to determine .parameters
- // see https://github.com/openpeer/ortc/issues/569
- break;
- }
- }
- });
-
- localCapabilities.headerExtensions.forEach(function(lHeaderExtension) {
- for (var i = 0; i < remoteCapabilities.headerExtensions.length;
- i++) {
- var rHeaderExtension = remoteCapabilities.headerExtensions[i];
- if (lHeaderExtension.uri === rHeaderExtension.uri) {
- commonCapabilities.headerExtensions.push(rHeaderExtension);
- break;
- }
- }
- });
-
- // FIXME: fecMechanisms
- return commonCapabilities;
-}
-
-// is action=setLocalDescription with type allowed in signalingState
-function isActionAllowedInSignalingState(action, type, signalingState) {
- return {
- offer: {
- setLocalDescription: ['stable', 'have-local-offer'],
- setRemoteDescription: ['stable', 'have-remote-offer']
- },
- answer: {
- setLocalDescription: ['have-remote-offer', 'have-local-pranswer'],
- setRemoteDescription: ['have-local-offer', 'have-remote-pranswer']
- }
- }[type][action].indexOf(signalingState) !== -1;
-}
-
-function maybeAddCandidate(iceTransport, candidate) {
- // Edge's internal representation adds some fields therefore
- // not all fieldѕ are taken into account.
- var alreadyAdded = iceTransport.getRemoteCandidates()
- .find(function(remoteCandidate) {
- return candidate.foundation === remoteCandidate.foundation &&
- candidate.ip === remoteCandidate.ip &&
- candidate.port === remoteCandidate.port &&
- candidate.priority === remoteCandidate.priority &&
- candidate.protocol === remoteCandidate.protocol &&
- candidate.type === remoteCandidate.type;
- });
- if (!alreadyAdded) {
- iceTransport.addRemoteCandidate(candidate);
- }
- return !alreadyAdded;
-}
-
-
-// https://w3c.github.io/mediacapture-main/#mediastream
-// Helper function to add the track to the stream and
-// dispatch the event ourselves.
-function addTrackToStreamAndFireEvent(track, stream) {
- stream.addTrack(track);
- var e = new Event('addtrack'); // TODO: MediaStreamTrackEvent
- e.track = track;
- stream.dispatchEvent(e);
-}
-
-function removeTrackFromStreamAndFireEvent(track, stream) {
- stream.removeTrack(track);
- var e = new Event('removetrack'); // TODO: MediaStreamTrackEvent
- e.track = track;
- stream.dispatchEvent(e);
-}
-
-function fireAddTrack(pc, track, receiver, streams) {
- var trackEvent = new Event('track');
- trackEvent.track = track;
- trackEvent.receiver = receiver;
- trackEvent.transceiver = {receiver: receiver};
- trackEvent.streams = streams;
- window.setTimeout(function() {
- pc._dispatchEvent('track', trackEvent);
- });
-}
-
-function makeError(name, description) {
- var e = new Error(description);
- e.name = name;
- return e;
-}
-
-module.exports = function(window, edgeVersion) {
- var RTCPeerConnection = function(config) {
- var pc = this;
-
- var _eventTarget = document.createDocumentFragment();
- ['addEventListener', 'removeEventListener', 'dispatchEvent']
- .forEach(function(method) {
- pc[method] = _eventTarget[method].bind(_eventTarget);
- });
-
- this.canTrickleIceCandidates = null;
-
- this.needNegotiation = false;
-
- this.localStreams = [];
- this.remoteStreams = [];
-
- this.localDescription = null;
- this.remoteDescription = null;
-
- this.signalingState = 'stable';
- this.iceConnectionState = 'new';
- this.iceGatheringState = 'new';
-
- config = JSON.parse(JSON.stringify(config || {}));
-
- this.usingBundle = config.bundlePolicy === 'max-bundle';
- if (config.rtcpMuxPolicy === 'negotiate') {
- throw(makeError('NotSupportedError',
- 'rtcpMuxPolicy \'negotiate\' is not supported'));
- } else if (!config.rtcpMuxPolicy) {
- config.rtcpMuxPolicy = 'require';
- }
-
- switch (config.iceTransportPolicy) {
- case 'all':
- case 'relay':
- break;
- default:
- config.iceTransportPolicy = 'all';
- break;
- }
-
- switch (config.bundlePolicy) {
- case 'balanced':
- case 'max-compat':
- case 'max-bundle':
- break;
- default:
- config.bundlePolicy = 'balanced';
- break;
- }
-
- config.iceServers = filterIceServers(config.iceServers || [], edgeVersion);
-
- this._iceGatherers = [];
- if (config.iceCandidatePoolSize) {
- for (var i = config.iceCandidatePoolSize; i > 0; i--) {
- this._iceGatherers = new window.RTCIceGatherer({
- iceServers: config.iceServers,
- gatherPolicy: config.iceTransportPolicy
- });
- }
- } else {
- config.iceCandidatePoolSize = 0;
- }
-
- this._config = config;
-
- // per-track iceGathers, iceTransports, dtlsTransports, rtpSenders, ...
- // everything that is needed to describe a SDP m-line.
- this.transceivers = [];
-
- this._sdpSessionId = SDPUtils.generateSessionId();
- this._sdpSessionVersion = 0;
-
- this._dtlsRole = undefined; // role for a=setup to use in answers.
-
- this._isClosed = false;
- };
-
- // set up event handlers on prototype
- RTCPeerConnection.prototype.onicecandidate = null;
- RTCPeerConnection.prototype.onaddstream = null;
- RTCPeerConnection.prototype.ontrack = null;
- RTCPeerConnection.prototype.onremovestream = null;
- RTCPeerConnection.prototype.onsignalingstatechange = null;
- RTCPeerConnection.prototype.oniceconnectionstatechange = null;
- RTCPeerConnection.prototype.onicegatheringstatechange = null;
- RTCPeerConnection.prototype.onnegotiationneeded = null;
- RTCPeerConnection.prototype.ondatachannel = null;
-
- RTCPeerConnection.prototype._dispatchEvent = function(name, event) {
- if (this._isClosed) {
- return;
- }
- this.dispatchEvent(event);
- if (typeof this['on' + name] === 'function') {
- this['on' + name](event);
- }
- };
-
- RTCPeerConnection.prototype._emitGatheringStateChange = function() {
- var event = new Event('icegatheringstatechange');
- this._dispatchEvent('icegatheringstatechange', event);
- };
-
- RTCPeerConnection.prototype.getConfiguration = function() {
- return this._config;
- };
-
- RTCPeerConnection.prototype.getLocalStreams = function() {
- return this.localStreams;
- };
-
- RTCPeerConnection.prototype.getRemoteStreams = function() {
- return this.remoteStreams;
- };
-
- // internal helper to create a transceiver object.
- // (whih is not yet the same as the WebRTC 1.0 transceiver)
- RTCPeerConnection.prototype._createTransceiver = function(kind) {
- var hasBundleTransport = this.transceivers.length > 0;
- var transceiver = {
- track: null,
- iceGatherer: null,
- iceTransport: null,
- dtlsTransport: null,
- localCapabilities: null,
- remoteCapabilities: null,
- rtpSender: null,
- rtpReceiver: null,
- kind: kind,
- mid: null,
- sendEncodingParameters: null,
- recvEncodingParameters: null,
- stream: null,
- associatedRemoteMediaStreams: [],
- wantReceive: true
- };
- if (this.usingBundle && hasBundleTransport) {
- transceiver.iceTransport = this.transceivers[0].iceTransport;
- transceiver.dtlsTransport = this.transceivers[0].dtlsTransport;
- } else {
- var transports = this._createIceAndDtlsTransports();
- transceiver.iceTransport = transports.iceTransport;
- transceiver.dtlsTransport = transports.dtlsTransport;
- }
- this.transceivers.push(transceiver);
- return transceiver;
- };
-
- RTCPeerConnection.prototype.addTrack = function(track, stream) {
- var alreadyExists = this.transceivers.find(function(s) {
- return s.track === track;
- });
-
- if (alreadyExists) {
- throw makeError('InvalidAccessError', 'Track already exists.');
- }
-
- if (this.signalingState === 'closed') {
- throw makeError('InvalidStateError',
- 'Attempted to call addTrack on a closed peerconnection.');
- }
-
- var transceiver;
- for (var i = 0; i < this.transceivers.length; i++) {
- if (!this.transceivers[i].track &&
- this.transceivers[i].kind === track.kind) {
- transceiver = this.transceivers[i];
- }
- }
- if (!transceiver) {
- transceiver = this._createTransceiver(track.kind);
- }
-
- this._maybeFireNegotiationNeeded();
-
- if (this.localStreams.indexOf(stream) === -1) {
- this.localStreams.push(stream);
- }
-
- transceiver.track = track;
- transceiver.stream = stream;
- transceiver.rtpSender = new window.RTCRtpSender(track,
- transceiver.dtlsTransport);
- return transceiver.rtpSender;
- };
-
- RTCPeerConnection.prototype.addStream = function(stream) {
- var pc = this;
- if (edgeVersion >= 15025) {
- stream.getTracks().forEach(function(track) {
- pc.addTrack(track, stream);
- });
- } else {
- // Clone is necessary for local demos mostly, attaching directly
- // to two different senders does not work (build 10547).
- // Fixed in 15025 (or earlier)
- var clonedStream = stream.clone();
- stream.getTracks().forEach(function(track, idx) {
- var clonedTrack = clonedStream.getTracks()[idx];
- track.addEventListener('enabled', function(event) {
- clonedTrack.enabled = event.enabled;
- });
- });
- clonedStream.getTracks().forEach(function(track) {
- pc.addTrack(track, clonedStream);
- });
- }
- };
-
- RTCPeerConnection.prototype.removeTrack = function(sender) {
- if (!(sender instanceof window.RTCRtpSender)) {
- throw new TypeError('Argument 1 of RTCPeerConnection.removeTrack ' +
- 'does not implement interface RTCRtpSender.');
- }
-
- var transceiver = this.transceivers.find(function(t) {
- return t.rtpSender === sender;
- });
-
- if (!transceiver) {
- throw makeError('InvalidAccessError',
- 'Sender was not created by this connection.');
- }
- var stream = transceiver.stream;
-
- transceiver.rtpSender.stop();
- transceiver.rtpSender = null;
- transceiver.track = null;
- transceiver.stream = null;
-
- // remove the stream from the set of local streams
- var localStreams = this.transceivers.map(function(t) {
- return t.stream;
- });
- if (localStreams.indexOf(stream) === -1 &&
- this.localStreams.indexOf(stream) > -1) {
- this.localStreams.splice(this.localStreams.indexOf(stream), 1);
- }
-
- this._maybeFireNegotiationNeeded();
- };
-
- RTCPeerConnection.prototype.removeStream = function(stream) {
- var pc = this;
- stream.getTracks().forEach(function(track) {
- var sender = pc.getSenders().find(function(s) {
- return s.track === track;
- });
- if (sender) {
- pc.removeTrack(sender);
- }
- });
- };
-
- RTCPeerConnection.prototype.getSenders = function() {
- return this.transceivers.filter(function(transceiver) {
- return !!transceiver.rtpSender;
- })
- .map(function(transceiver) {
- return transceiver.rtpSender;
- });
- };
-
- RTCPeerConnection.prototype.getReceivers = function() {
- return this.transceivers.filter(function(transceiver) {
- return !!transceiver.rtpReceiver;
- })
- .map(function(transceiver) {
- return transceiver.rtpReceiver;
- });
- };
-
-
- RTCPeerConnection.prototype._createIceGatherer = function(sdpMLineIndex,
- usingBundle) {
- var pc = this;
- if (usingBundle && sdpMLineIndex > 0) {
- return this.transceivers[0].iceGatherer;
- } else if (this._iceGatherers.length) {
- return this._iceGatherers.shift();
- }
- var iceGatherer = new window.RTCIceGatherer({
- iceServers: this._config.iceServers,
- gatherPolicy: this._config.iceTransportPolicy
- });
- Object.defineProperty(iceGatherer, 'state',
- {value: 'new', writable: true}
- );
-
- this.transceivers[sdpMLineIndex].candidates = [];
- this.transceivers[sdpMLineIndex].bufferCandidates = function(event) {
- var end = !event.candidate || Object.keys(event.candidate).length === 0;
- // polyfill since RTCIceGatherer.state is not implemented in
- // Edge 10547 yet.
- iceGatherer.state = end ? 'completed' : 'gathering';
- if (pc.transceivers[sdpMLineIndex].candidates !== null) {
- pc.transceivers[sdpMLineIndex].candidates.push(event.candidate);
- }
- };
- iceGatherer.addEventListener('localcandidate',
- this.transceivers[sdpMLineIndex].bufferCandidates);
- return iceGatherer;
- };
-
- // start gathering from an RTCIceGatherer.
- RTCPeerConnection.prototype._gather = function(mid, sdpMLineIndex) {
- var pc = this;
- var iceGatherer = this.transceivers[sdpMLineIndex].iceGatherer;
- if (iceGatherer.onlocalcandidate) {
- return;
- }
- var candidates = this.transceivers[sdpMLineIndex].candidates;
- this.transceivers[sdpMLineIndex].candidates = null;
- iceGatherer.removeEventListener('localcandidate',
- this.transceivers[sdpMLineIndex].bufferCandidates);
- iceGatherer.onlocalcandidate = function(evt) {
- if (pc.usingBundle && sdpMLineIndex > 0) {
- // if we know that we use bundle we can drop candidates with
- // Ń•dpMLineIndex > 0. If we don't do this then our state gets
- // confused since we dispose the extra ice gatherer.
- return;
- }
- var event = new Event('icecandidate');
- event.candidate = {sdpMid: mid, sdpMLineIndex: sdpMLineIndex};
-
- var cand = evt.candidate;
- // Edge emits an empty object for RTCIceCandidateComplete‥
- var end = !cand || Object.keys(cand).length === 0;
- if (end) {
- // polyfill since RTCIceGatherer.state is not implemented in
- // Edge 10547 yet.
- if (iceGatherer.state === 'new' || iceGatherer.state === 'gathering') {
- iceGatherer.state = 'completed';
- }
- } else {
- if (iceGatherer.state === 'new') {
- iceGatherer.state = 'gathering';
- }
- // RTCIceCandidate doesn't have a component, needs to be added
- cand.component = 1;
- event.candidate.candidate = SDPUtils.writeCandidate(cand);
- }
-
- // update local description.
- var sections = SDPUtils.splitSections(pc.localDescription.sdp);
- if (!end) {
- sections[event.candidate.sdpMLineIndex + 1] +=
- 'a=' + event.candidate.candidate + '\r\n';
- } else {
- sections[event.candidate.sdpMLineIndex + 1] +=
- 'a=end-of-candidates\r\n';
- }
- pc.localDescription.sdp = sections.join('');
- var complete = pc.transceivers.every(function(transceiver) {
- return transceiver.iceGatherer &&
- transceiver.iceGatherer.state === 'completed';
- });
-
- if (pc.iceGatheringState !== 'gathering') {
- pc.iceGatheringState = 'gathering';
- pc._emitGatheringStateChange();
- }
-
- // Emit candidate. Also emit null candidate when all gatherers are
- // complete.
- if (!end) {
- pc._dispatchEvent('icecandidate', event);
- }
- if (complete) {
- pc._dispatchEvent('icecandidate', new Event('icecandidate'));
- pc.iceGatheringState = 'complete';
- pc._emitGatheringStateChange();
- }
- };
-
- // emit already gathered candidates.
- window.setTimeout(function() {
- candidates.forEach(function(candidate) {
- var e = new Event('RTCIceGatherEvent');
- e.candidate = candidate;
- iceGatherer.onlocalcandidate(e);
- });
- }, 0);
- };
-
- // Create ICE transport and DTLS transport.
- RTCPeerConnection.prototype._createIceAndDtlsTransports = function() {
- var pc = this;
- var iceTransport = new window.RTCIceTransport(null);
- iceTransport.onicestatechange = function() {
- pc._updateConnectionState();
- };
-
- var dtlsTransport = new window.RTCDtlsTransport(iceTransport);
- dtlsTransport.ondtlsstatechange = function() {
- pc._updateConnectionState();
- };
- dtlsTransport.onerror = function() {
- // onerror does not set state to failed by itpc.
- Object.defineProperty(dtlsTransport, 'state',
- {value: 'failed', writable: true});
- pc._updateConnectionState();
- };
-
- return {
- iceTransport: iceTransport,
- dtlsTransport: dtlsTransport
- };
- };
-
- // Destroy ICE gatherer, ICE transport and DTLS transport.
- // Without triggering the callbacks.
- RTCPeerConnection.prototype._disposeIceAndDtlsTransports = function(
- sdpMLineIndex) {
- var iceGatherer = this.transceivers[sdpMLineIndex].iceGatherer;
- if (iceGatherer) {
- delete iceGatherer.onlocalcandidate;
- delete this.transceivers[sdpMLineIndex].iceGatherer;
- }
- var iceTransport = this.transceivers[sdpMLineIndex].iceTransport;
- if (iceTransport) {
- delete iceTransport.onicestatechange;
- delete this.transceivers[sdpMLineIndex].iceTransport;
- }
- var dtlsTransport = this.transceivers[sdpMLineIndex].dtlsTransport;
- if (dtlsTransport) {
- delete dtlsTransport.ondtlsstatechange;
- delete dtlsTransport.onerror;
- delete this.transceivers[sdpMLineIndex].dtlsTransport;
- }
- };
-
- // Start the RTP Sender and Receiver for a transceiver.
- RTCPeerConnection.prototype._transceive = function(transceiver,
- send, recv) {
- var params = getCommonCapabilities(transceiver.localCapabilities,
- transceiver.remoteCapabilities);
- if (send && transceiver.rtpSender) {
- params.encodings = transceiver.sendEncodingParameters;
- params.rtcp = {
- cname: SDPUtils.localCName,
- compound: transceiver.rtcpParameters.compound
- };
- if (transceiver.recvEncodingParameters.length) {
- params.rtcp.ssrc = transceiver.recvEncodingParameters[0].ssrc;
- }
- transceiver.rtpSender.send(params);
- }
- if (recv && transceiver.rtpReceiver && params.codecs.length > 0) {
- // remove RTX field in Edge 14942
- if (transceiver.kind === 'video'
- && transceiver.recvEncodingParameters
- && edgeVersion < 15019) {
- transceiver.recvEncodingParameters.forEach(function(p) {
- delete p.rtx;
- });
- }
- if (transceiver.recvEncodingParameters.length) {
- params.encodings = transceiver.recvEncodingParameters;
- }
- params.rtcp = {
- compound: transceiver.rtcpParameters.compound
- };
- if (transceiver.rtcpParameters.cname) {
- params.rtcp.cname = transceiver.rtcpParameters.cname;
- }
- if (transceiver.sendEncodingParameters.length) {
- params.rtcp.ssrc = transceiver.sendEncodingParameters[0].ssrc;
- }
- transceiver.rtpReceiver.receive(params);
- }
- };
-
- RTCPeerConnection.prototype.setLocalDescription = function(description) {
- var pc = this;
-
- if (!isActionAllowedInSignalingState('setLocalDescription',
- description.type, this.signalingState) || this._isClosed) {
- return Promise.reject(makeError('InvalidStateError',
- 'Can not set local ' + description.type +
- ' in state ' + pc.signalingState));
- }
-
- var sections;
- var sessionpart;
- if (description.type === 'offer') {
- // VERY limited support for SDP munging. Limited to:
- // * changing the order of codecs
- sections = SDPUtils.splitSections(description.sdp);
- sessionpart = sections.shift();
- sections.forEach(function(mediaSection, sdpMLineIndex) {
- var caps = SDPUtils.parseRtpParameters(mediaSection);
- pc.transceivers[sdpMLineIndex].localCapabilities = caps;
- });
-
- this.transceivers.forEach(function(transceiver, sdpMLineIndex) {
- pc._gather(transceiver.mid, sdpMLineIndex);
- });
- } else if (description.type === 'answer') {
- sections = SDPUtils.splitSections(pc.remoteDescription.sdp);
- sessionpart = sections.shift();
- var isIceLite = SDPUtils.matchPrefix(sessionpart,
- 'a=ice-lite').length > 0;
- sections.forEach(function(mediaSection, sdpMLineIndex) {
- var transceiver = pc.transceivers[sdpMLineIndex];
- var iceGatherer = transceiver.iceGatherer;
- var iceTransport = transceiver.iceTransport;
- var dtlsTransport = transceiver.dtlsTransport;
- var localCapabilities = transceiver.localCapabilities;
- var remoteCapabilities = transceiver.remoteCapabilities;
-
- // treat bundle-only as not-rejected.
- var rejected = SDPUtils.isRejected(mediaSection) &&
- SDPUtils.matchPrefix(mediaSection, 'a=bundle-only').length === 0;
-
- if (!rejected && !transceiver.isDatachannel) {
- var remoteIceParameters = SDPUtils.getIceParameters(
- mediaSection, sessionpart);
- var remoteDtlsParameters = SDPUtils.getDtlsParameters(
- mediaSection, sessionpart);
- if (isIceLite) {
- remoteDtlsParameters.role = 'server';
- }
-
- if (!pc.usingBundle || sdpMLineIndex === 0) {
- pc._gather(transceiver.mid, sdpMLineIndex);
- if (iceTransport.state === 'new') {
- iceTransport.start(iceGatherer, remoteIceParameters,
- isIceLite ? 'controlling' : 'controlled');
- }
- if (dtlsTransport.state === 'new') {
- dtlsTransport.start(remoteDtlsParameters);
- }
- }
-
- // Calculate intersection of capabilities.
- var params = getCommonCapabilities(localCapabilities,
- remoteCapabilities);
-
- // Start the RTCRtpSender. The RTCRtpReceiver for this
- // transceiver has already been started in setRemoteDescription.
- pc._transceive(transceiver,
- params.codecs.length > 0,
- false);
- }
- });
- }
-
- this.localDescription = {
- type: description.type,
- sdp: description.sdp
- };
- switch (description.type) {
- case 'offer':
- this._updateSignalingState('have-local-offer');
- break;
- case 'answer':
- this._updateSignalingState('stable');
- break;
- default:
- throw new TypeError('unsupported type "' + description.type +
- '"');
- }
-
- return Promise.resolve();
- };
-
- RTCPeerConnection.prototype.setRemoteDescription = function(description) {
- var pc = this;
-
- if (!isActionAllowedInSignalingState('setRemoteDescription',
- description.type, this.signalingState) || this._isClosed) {
- return Promise.reject(makeError('InvalidStateError',
- 'Can not set remote ' + description.type +
- ' in state ' + pc.signalingState));
- }
-
- var streams = {};
- this.remoteStreams.forEach(function(stream) {
- streams[stream.id] = stream;
- });
- var receiverList = [];
- var sections = SDPUtils.splitSections(description.sdp);
- var sessionpart = sections.shift();
- var isIceLite = SDPUtils.matchPrefix(sessionpart,
- 'a=ice-lite').length > 0;
- var usingBundle = SDPUtils.matchPrefix(sessionpart,
- 'a=group:BUNDLE ').length > 0;
- this.usingBundle = usingBundle;
- var iceOptions = SDPUtils.matchPrefix(sessionpart,
- 'a=ice-options:')[0];
- if (iceOptions) {
- this.canTrickleIceCandidates = iceOptions.substr(14).split(' ')
- .indexOf('trickle') >= 0;
- } else {
- this.canTrickleIceCandidates = false;
- }
-
- sections.forEach(function(mediaSection, sdpMLineIndex) {
- var lines = SDPUtils.splitLines(mediaSection);
- var kind = SDPUtils.getKind(mediaSection);
- // treat bundle-only as not-rejected.
- var rejected = SDPUtils.isRejected(mediaSection) &&
- SDPUtils.matchPrefix(mediaSection, 'a=bundle-only').length === 0;
- var protocol = lines[0].substr(2).split(' ')[2];
-
- var direction = SDPUtils.getDirection(mediaSection, sessionpart);
- var remoteMsid = SDPUtils.parseMsid(mediaSection);
-
- var mid = SDPUtils.getMid(mediaSection) || SDPUtils.generateIdentifier();
-
- // Reject datachannels which are not implemented yet.
- if (kind === 'application' && protocol === 'DTLS/SCTP') {
- pc.transceivers[sdpMLineIndex] = {
- mid: mid,
- isDatachannel: true
- };
- return;
- }
-
- var transceiver;
- var iceGatherer;
- var iceTransport;
- var dtlsTransport;
- var rtpReceiver;
- var sendEncodingParameters;
- var recvEncodingParameters;
- var localCapabilities;
-
- var track;
- // FIXME: ensure the mediaSection has rtcp-mux set.
- var remoteCapabilities = SDPUtils.parseRtpParameters(mediaSection);
- var remoteIceParameters;
- var remoteDtlsParameters;
- if (!rejected) {
- remoteIceParameters = SDPUtils.getIceParameters(mediaSection,
- sessionpart);
- remoteDtlsParameters = SDPUtils.getDtlsParameters(mediaSection,
- sessionpart);
- remoteDtlsParameters.role = 'client';
- }
- recvEncodingParameters =
- SDPUtils.parseRtpEncodingParameters(mediaSection);
-
- var rtcpParameters = SDPUtils.parseRtcpParameters(mediaSection);
-
- var isComplete = SDPUtils.matchPrefix(mediaSection,
- 'a=end-of-candidates', sessionpart).length > 0;
- var cands = SDPUtils.matchPrefix(mediaSection, 'a=candidate:')
- .map(function(cand) {
- return SDPUtils.parseCandidate(cand);
- })
- .filter(function(cand) {
- return cand.component === 1;
- });
-
- // Check if we can use BUNDLE and dispose transports.
- if ((description.type === 'offer' || description.type === 'answer') &&
- !rejected && usingBundle && sdpMLineIndex > 0 &&
- pc.transceivers[sdpMLineIndex]) {
- pc._disposeIceAndDtlsTransports(sdpMLineIndex);
- pc.transceivers[sdpMLineIndex].iceGatherer =
- pc.transceivers[0].iceGatherer;
- pc.transceivers[sdpMLineIndex].iceTransport =
- pc.transceivers[0].iceTransport;
- pc.transceivers[sdpMLineIndex].dtlsTransport =
- pc.transceivers[0].dtlsTransport;
- if (pc.transceivers[sdpMLineIndex].rtpSender) {
- pc.transceivers[sdpMLineIndex].rtpSender.setTransport(
- pc.transceivers[0].dtlsTransport);
- }
- if (pc.transceivers[sdpMLineIndex].rtpReceiver) {
- pc.transceivers[sdpMLineIndex].rtpReceiver.setTransport(
- pc.transceivers[0].dtlsTransport);
- }
- }
- if (description.type === 'offer' && !rejected) {
- transceiver = pc.transceivers[sdpMLineIndex] ||
- pc._createTransceiver(kind);
- transceiver.mid = mid;
-
- if (!transceiver.iceGatherer) {
- transceiver.iceGatherer = pc._createIceGatherer(sdpMLineIndex,
- usingBundle);
- }
-
- if (cands.length && transceiver.iceTransport.state === 'new') {
- if (isComplete && (!usingBundle || sdpMLineIndex === 0)) {
- transceiver.iceTransport.setRemoteCandidates(cands);
- } else {
- cands.forEach(function(candidate) {
- maybeAddCandidate(transceiver.iceTransport, candidate);
- });
- }
- }
-
- localCapabilities = window.RTCRtpReceiver.getCapabilities(kind);
-
- // filter RTX until additional stuff needed for RTX is implemented
- // in adapter.js
- if (edgeVersion < 15019) {
- localCapabilities.codecs = localCapabilities.codecs.filter(
- function(codec) {
- return codec.name !== 'rtx';
- });
- }
-
- sendEncodingParameters = transceiver.sendEncodingParameters || [{
- ssrc: (2 * sdpMLineIndex + 2) * 1001
- }];
-
- // TODO: rewrite to use http://w3c.github.io/webrtc-pc/#set-associated-remote-streams
- var isNewTrack = false;
- if (direction === 'sendrecv' || direction === 'sendonly') {
- isNewTrack = !transceiver.rtpReceiver;
- rtpReceiver = transceiver.rtpReceiver ||
- new window.RTCRtpReceiver(transceiver.dtlsTransport, kind);
-
- if (isNewTrack) {
- var stream;
- track = rtpReceiver.track;
- // FIXME: does not work with Plan B.
- if (remoteMsid && remoteMsid.stream === '-') {
- // no-op. a stream id of '-' means: no associated stream.
- } else if (remoteMsid) {
- if (!streams[remoteMsid.stream]) {
- streams[remoteMsid.stream] = new window.MediaStream();
- Object.defineProperty(streams[remoteMsid.stream], 'id', {
- get: function() {
- return remoteMsid.stream;
- }
- });
- }
- Object.defineProperty(track, 'id', {
- get: function() {
- return remoteMsid.track;
- }
- });
- stream = streams[remoteMsid.stream];
- } else {
- if (!streams.default) {
- streams.default = new window.MediaStream();
- }
- stream = streams.default;
- }
- if (stream) {
- addTrackToStreamAndFireEvent(track, stream);
- transceiver.associatedRemoteMediaStreams.push(stream);
- }
- receiverList.push([track, rtpReceiver, stream]);
- }
- } else if (transceiver.rtpReceiver && transceiver.rtpReceiver.track) {
- transceiver.associatedRemoteMediaStreams.forEach(function(s) {
- var nativeTrack = s.getTracks().find(function(t) {
- return t.id === transceiver.rtpReceiver.track.id;
- });
- if (nativeTrack) {
- removeTrackFromStreamAndFireEvent(nativeTrack, s);
- }
- });
- transceiver.associatedRemoteMediaStreams = [];
- }
-
- transceiver.localCapabilities = localCapabilities;
- transceiver.remoteCapabilities = remoteCapabilities;
- transceiver.rtpReceiver = rtpReceiver;
- transceiver.rtcpParameters = rtcpParameters;
- transceiver.sendEncodingParameters = sendEncodingParameters;
- transceiver.recvEncodingParameters = recvEncodingParameters;
-
- // Start the RTCRtpReceiver now. The RTPSender is started in
- // setLocalDescription.
- pc._transceive(pc.transceivers[sdpMLineIndex],
- false,
- isNewTrack);
- } else if (description.type === 'answer' && !rejected) {
- transceiver = pc.transceivers[sdpMLineIndex];
- iceGatherer = transceiver.iceGatherer;
- iceTransport = transceiver.iceTransport;
- dtlsTransport = transceiver.dtlsTransport;
- rtpReceiver = transceiver.rtpReceiver;
- sendEncodingParameters = transceiver.sendEncodingParameters;
- localCapabilities = transceiver.localCapabilities;
-
- pc.transceivers[sdpMLineIndex].recvEncodingParameters =
- recvEncodingParameters;
- pc.transceivers[sdpMLineIndex].remoteCapabilities =
- remoteCapabilities;
- pc.transceivers[sdpMLineIndex].rtcpParameters = rtcpParameters;
-
- if (cands.length && iceTransport.state === 'new') {
- if ((isIceLite || isComplete) &&
- (!usingBundle || sdpMLineIndex === 0)) {
- iceTransport.setRemoteCandidates(cands);
- } else {
- cands.forEach(function(candidate) {
- maybeAddCandidate(transceiver.iceTransport, candidate);
- });
- }
- }
-
- if (!usingBundle || sdpMLineIndex === 0) {
- if (iceTransport.state === 'new') {
- iceTransport.start(iceGatherer, remoteIceParameters,
- 'controlling');
- }
- if (dtlsTransport.state === 'new') {
- dtlsTransport.start(remoteDtlsParameters);
- }
- }
-
- pc._transceive(transceiver,
- direction === 'sendrecv' || direction === 'recvonly',
- direction === 'sendrecv' || direction === 'sendonly');
-
- // TODO: rewrite to use http://w3c.github.io/webrtc-pc/#set-associated-remote-streams
- if (rtpReceiver &&
- (direction === 'sendrecv' || direction === 'sendonly')) {
- track = rtpReceiver.track;
- if (remoteMsid) {
- if (!streams[remoteMsid.stream]) {
- streams[remoteMsid.stream] = new window.MediaStream();
- }
- addTrackToStreamAndFireEvent(track, streams[remoteMsid.stream]);
- receiverList.push([track, rtpReceiver, streams[remoteMsid.stream]]);
- } else {
- if (!streams.default) {
- streams.default = new window.MediaStream();
- }
- addTrackToStreamAndFireEvent(track, streams.default);
- receiverList.push([track, rtpReceiver, streams.default]);
- }
- } else {
- // FIXME: actually the receiver should be created later.
- delete transceiver.rtpReceiver;
- }
- }
- });
-
- if (this._dtlsRole === undefined) {
- this._dtlsRole = description.type === 'offer' ? 'active' : 'passive';
- }
-
- this.remoteDescription = {
- type: description.type,
- sdp: description.sdp
- };
- switch (description.type) {
- case 'offer':
- this._updateSignalingState('have-remote-offer');
- break;
- case 'answer':
- this._updateSignalingState('stable');
- break;
- default:
- throw new TypeError('unsupported type "' + description.type +
- '"');
- }
- Object.keys(streams).forEach(function(sid) {
- var stream = streams[sid];
- if (stream.getTracks().length) {
- if (pc.remoteStreams.indexOf(stream) === -1) {
- pc.remoteStreams.push(stream);
- var event = new Event('addstream');
- event.stream = stream;
- window.setTimeout(function() {
- pc._dispatchEvent('addstream', event);
- });
- }
-
- receiverList.forEach(function(item) {
- var track = item[0];
- var receiver = item[1];
- if (stream.id !== item[2].id) {
- return;
- }
- fireAddTrack(pc, track, receiver, [stream]);
- });
- }
- });
- receiverList.forEach(function(item) {
- if (item[2]) {
- return;
- }
- fireAddTrack(pc, item[0], item[1], []);
- });
-
- // check whether addIceCandidate({}) was called within four seconds after
- // setRemoteDescription.
- window.setTimeout(function() {
- if (!(pc && pc.transceivers)) {
- return;
- }
- pc.transceivers.forEach(function(transceiver) {
- if (transceiver.iceTransport &&
- transceiver.iceTransport.state === 'new' &&
- transceiver.iceTransport.getRemoteCandidates().length > 0) {
- console.warn('Timeout for addRemoteCandidate. Consider sending ' +
- 'an end-of-candidates notification');
- transceiver.iceTransport.addRemoteCandidate({});
- }
- });
- }, 4000);
-
- return Promise.resolve();
- };
-
- RTCPeerConnection.prototype.close = function() {
- this.transceivers.forEach(function(transceiver) {
- /* not yet
- if (transceiver.iceGatherer) {
- transceiver.iceGatherer.close();
- }
- */
- if (transceiver.iceTransport) {
- transceiver.iceTransport.stop();
- }
- if (transceiver.dtlsTransport) {
- transceiver.dtlsTransport.stop();
- }
- if (transceiver.rtpSender) {
- transceiver.rtpSender.stop();
- }
- if (transceiver.rtpReceiver) {
- transceiver.rtpReceiver.stop();
- }
- });
- // FIXME: clean up tracks, local streams, remote streams, etc
- this._isClosed = true;
- this._updateSignalingState('closed');
- };
-
- // Update the signaling state.
- RTCPeerConnection.prototype._updateSignalingState = function(newState) {
- this.signalingState = newState;
- var event = new Event('signalingstatechange');
- this._dispatchEvent('signalingstatechange', event);
- };
-
- // Determine whether to fire the negotiationneeded event.
- RTCPeerConnection.prototype._maybeFireNegotiationNeeded = function() {
- var pc = this;
- if (this.signalingState !== 'stable' || this.needNegotiation === true) {
- return;
- }
- this.needNegotiation = true;
- window.setTimeout(function() {
- if (pc.needNegotiation === false) {
- return;
- }
- pc.needNegotiation = false;
- var event = new Event('negotiationneeded');
- pc._dispatchEvent('negotiationneeded', event);
- }, 0);
- };
-
- // Update the connection state.
- RTCPeerConnection.prototype._updateConnectionState = function() {
- var newState;
- var states = {
- 'new': 0,
- closed: 0,
- connecting: 0,
- checking: 0,
- connected: 0,
- completed: 0,
- disconnected: 0,
- failed: 0
- };
- this.transceivers.forEach(function(transceiver) {
- states[transceiver.iceTransport.state]++;
- states[transceiver.dtlsTransport.state]++;
- });
- // ICETransport.completed and connected are the same for this purpose.
- states.connected += states.completed;
-
- newState = 'new';
- if (states.failed > 0) {
- newState = 'failed';
- } else if (states.connecting > 0 || states.checking > 0) {
- newState = 'connecting';
- } else if (states.disconnected > 0) {
- newState = 'disconnected';
- } else if (states.new > 0) {
- newState = 'new';
- } else if (states.connected > 0 || states.completed > 0) {
- newState = 'connected';
- }
-
- if (newState !== this.iceConnectionState) {
- this.iceConnectionState = newState;
- var event = new Event('iceconnectionstatechange');
- this._dispatchEvent('iceconnectionstatechange', event);
- }
- };
-
- RTCPeerConnection.prototype.createOffer = function() {
- var pc = this;
-
- if (this._isClosed) {
- return Promise.reject(makeError('InvalidStateError',
- 'Can not call createOffer after close'));
- }
-
- var numAudioTracks = this.transceivers.filter(function(t) {
- return t.kind === 'audio';
- }).length;
- var numVideoTracks = this.transceivers.filter(function(t) {
- return t.kind === 'video';
- }).length;
-
- // Determine number of audio and video tracks we need to send/recv.
- var offerOptions = arguments[0];
- if (offerOptions) {
- // Reject Chrome legacy constraints.
- if (offerOptions.mandatory || offerOptions.optional) {
- throw new TypeError(
- 'Legacy mandatory/optional constraints not supported.');
- }
- if (offerOptions.offerToReceiveAudio !== undefined) {
- if (offerOptions.offerToReceiveAudio === true) {
- numAudioTracks = 1;
- } else if (offerOptions.offerToReceiveAudio === false) {
- numAudioTracks = 0;
- } else {
- numAudioTracks = offerOptions.offerToReceiveAudio;
- }
- }
- if (offerOptions.offerToReceiveVideo !== undefined) {
- if (offerOptions.offerToReceiveVideo === true) {
- numVideoTracks = 1;
- } else if (offerOptions.offerToReceiveVideo === false) {
- numVideoTracks = 0;
- } else {
- numVideoTracks = offerOptions.offerToReceiveVideo;
- }
- }
- }
-
- this.transceivers.forEach(function(transceiver) {
- if (transceiver.kind === 'audio') {
- numAudioTracks--;
- if (numAudioTracks < 0) {
- transceiver.wantReceive = false;
- }
- } else if (transceiver.kind === 'video') {
- numVideoTracks--;
- if (numVideoTracks < 0) {
- transceiver.wantReceive = false;
- }
- }
- });
-
- // Create M-lines for recvonly streams.
- while (numAudioTracks > 0 || numVideoTracks > 0) {
- if (numAudioTracks > 0) {
- this._createTransceiver('audio');
- numAudioTracks--;
- }
- if (numVideoTracks > 0) {
- this._createTransceiver('video');
- numVideoTracks--;
- }
- }
-
- var sdp = SDPUtils.writeSessionBoilerplate(this._sdpSessionId,
- this._sdpSessionVersion++);
- this.transceivers.forEach(function(transceiver, sdpMLineIndex) {
- // For each track, create an ice gatherer, ice transport,
- // dtls transport, potentially rtpsender and rtpreceiver.
- var track = transceiver.track;
- var kind = transceiver.kind;
- var mid = SDPUtils.generateIdentifier();
- transceiver.mid = mid;
-
- if (!transceiver.iceGatherer) {
- transceiver.iceGatherer = pc._createIceGatherer(sdpMLineIndex,
- pc.usingBundle);
- }
-
- var localCapabilities = window.RTCRtpSender.getCapabilities(kind);
- // filter RTX until additional stuff needed for RTX is implemented
- // in adapter.js
- if (edgeVersion < 15019) {
- localCapabilities.codecs = localCapabilities.codecs.filter(
- function(codec) {
- return codec.name !== 'rtx';
- });
- }
- localCapabilities.codecs.forEach(function(codec) {
- // work around https://bugs.chromium.org/p/webrtc/issues/detail?id=6552
- // by adding level-asymmetry-allowed=1
- if (codec.name === 'H264' &&
- codec.parameters['level-asymmetry-allowed'] === undefined) {
- codec.parameters['level-asymmetry-allowed'] = '1';
- }
- });
-
- // generate an ssrc now, to be used later in rtpSender.send
- var sendEncodingParameters = transceiver.sendEncodingParameters || [{
- ssrc: (2 * sdpMLineIndex + 1) * 1001
- }];
- if (track) {
- // add RTX
- if (edgeVersion >= 15019 && kind === 'video' &&
- !sendEncodingParameters[0].rtx) {
- sendEncodingParameters[0].rtx = {
- ssrc: sendEncodingParameters[0].ssrc + 1
- };
- }
- }
-
- if (transceiver.wantReceive) {
- transceiver.rtpReceiver = new window.RTCRtpReceiver(
- transceiver.dtlsTransport, kind);
- }
-
- transceiver.localCapabilities = localCapabilities;
- transceiver.sendEncodingParameters = sendEncodingParameters;
- });
-
- // always offer BUNDLE and dispose on return if not supported.
- if (this._config.bundlePolicy !== 'max-compat') {
- sdp += 'a=group:BUNDLE ' + this.transceivers.map(function(t) {
- return t.mid;
- }).join(' ') + '\r\n';
- }
- sdp += 'a=ice-options:trickle\r\n';
-
- this.transceivers.forEach(function(transceiver, sdpMLineIndex) {
- sdp += writeMediaSection(transceiver, transceiver.localCapabilities,
- 'offer', transceiver.stream, pc._dtlsRole);
- sdp += 'a=rtcp-rsize\r\n';
-
- if (transceiver.iceGatherer && pc.iceGatheringState !== 'new' &&
- (sdpMLineIndex === 0 || !pc.usingBundle)) {
- transceiver.iceGatherer.getLocalCandidates().forEach(function(cand) {
- cand.component = 1;
- sdp += 'a=' + SDPUtils.writeCandidate(cand) + '\r\n';
- });
-
- if (transceiver.iceGatherer.state === 'completed') {
- sdp += 'a=end-of-candidates\r\n';
- }
- }
- });
-
- var desc = new window.RTCSessionDescription({
- type: 'offer',
- sdp: sdp
- });
- return Promise.resolve(desc);
- };
-
- RTCPeerConnection.prototype.createAnswer = function() {
- var pc = this;
-
- if (this._isClosed) {
- return Promise.reject(makeError('InvalidStateError',
- 'Can not call createAnswer after close'));
- }
-
- var sdp = SDPUtils.writeSessionBoilerplate(this._sdpSessionId,
- this._sdpSessionVersion++);
- if (this.usingBundle) {
- sdp += 'a=group:BUNDLE ' + this.transceivers.map(function(t) {
- return t.mid;
- }).join(' ') + '\r\n';
- }
- var mediaSectionsInOffer = SDPUtils.splitSections(
- this.remoteDescription.sdp).length - 1;
- this.transceivers.forEach(function(transceiver, sdpMLineIndex) {
- if (sdpMLineIndex + 1 > mediaSectionsInOffer) {
- return;
- }
- if (transceiver.isDatachannel) {
- sdp += 'm=application 0 DTLS/SCTP 5000\r\n' +
- 'c=IN IP4 0.0.0.0\r\n' +
- 'a=mid:' + transceiver.mid + '\r\n';
- return;
- }
-
- // FIXME: look at direction.
- if (transceiver.stream) {
- var localTrack;
- if (transceiver.kind === 'audio') {
- localTrack = transceiver.stream.getAudioTracks()[0];
- } else if (transceiver.kind === 'video') {
- localTrack = transceiver.stream.getVideoTracks()[0];
- }
- if (localTrack) {
- // add RTX
- if (edgeVersion >= 15019 && transceiver.kind === 'video' &&
- !transceiver.sendEncodingParameters[0].rtx) {
- transceiver.sendEncodingParameters[0].rtx = {
- ssrc: transceiver.sendEncodingParameters[0].ssrc + 1
- };
- }
- }
- }
-
- // Calculate intersection of capabilities.
- var commonCapabilities = getCommonCapabilities(
- transceiver.localCapabilities,
- transceiver.remoteCapabilities);
-
- var hasRtx = commonCapabilities.codecs.filter(function(c) {
- return c.name.toLowerCase() === 'rtx';
- }).length;
- if (!hasRtx && transceiver.sendEncodingParameters[0].rtx) {
- delete transceiver.sendEncodingParameters[0].rtx;
- }
-
- sdp += writeMediaSection(transceiver, commonCapabilities,
- 'answer', transceiver.stream, pc._dtlsRole);
- if (transceiver.rtcpParameters &&
- transceiver.rtcpParameters.reducedSize) {
- sdp += 'a=rtcp-rsize\r\n';
- }
- });
-
- var desc = new window.RTCSessionDescription({
- type: 'answer',
- sdp: sdp
- });
- return Promise.resolve(desc);
- };
-
- RTCPeerConnection.prototype.addIceCandidate = function(candidate) {
- var sections;
- if (!candidate || candidate.candidate === '') {
- for (var j = 0; j < this.transceivers.length; j++) {
- if (this.transceivers[j].isDatachannel) {
- continue;
- }
- this.transceivers[j].iceTransport.addRemoteCandidate({});
- sections = SDPUtils.splitSections(this.remoteDescription.sdp);
- sections[j + 1] += 'a=end-of-candidates\r\n';
- this.remoteDescription.sdp = sections.join('');
- if (this.usingBundle) {
- break;
- }
- }
- } else if (!(candidate.sdpMLineIndex !== undefined || candidate.sdpMid)) {
- throw new TypeError('sdpMLineIndex or sdpMid required');
- } else if (!this.remoteDescription) {
- return Promise.reject(makeError('InvalidStateError',
- 'Can not add ICE candidate without a remote description'));
- } else {
- var sdpMLineIndex = candidate.sdpMLineIndex;
- if (candidate.sdpMid) {
- for (var i = 0; i < this.transceivers.length; i++) {
- if (this.transceivers[i].mid === candidate.sdpMid) {
- sdpMLineIndex = i;
- break;
- }
- }
- }
- var transceiver = this.transceivers[sdpMLineIndex];
- if (transceiver) {
- if (transceiver.isDatachannel) {
- return Promise.resolve();
- }
- var cand = Object.keys(candidate.candidate).length > 0 ?
- SDPUtils.parseCandidate(candidate.candidate) : {};
- // Ignore Chrome's invalid candidates since Edge does not like them.
- if (cand.protocol === 'tcp' && (cand.port === 0 || cand.port === 9)) {
- return Promise.resolve();
- }
- // Ignore RTCP candidates, we assume RTCP-MUX.
- if (cand.component && cand.component !== 1) {
- return Promise.resolve();
- }
- // when using bundle, avoid adding candidates to the wrong
- // ice transport. And avoid adding candidates added in the SDP.
- if (sdpMLineIndex === 0 || (sdpMLineIndex > 0 &&
- transceiver.iceTransport !== this.transceivers[0].iceTransport)) {
- if (!maybeAddCandidate(transceiver.iceTransport, cand)) {
- return Promise.reject(makeError('OperationError',
- 'Can not add ICE candidate'));
- }
- }
-
- // update the remoteDescription.
- var candidateString = candidate.candidate.trim();
- if (candidateString.indexOf('a=') === 0) {
- candidateString = candidateString.substr(2);
- }
- sections = SDPUtils.splitSections(this.remoteDescription.sdp);
- sections[sdpMLineIndex + 1] += 'a=' +
- (cand.type ? candidateString : 'end-of-candidates')
- + '\r\n';
- this.remoteDescription.sdp = sections.join('');
- } else {
- return Promise.reject(makeError('OperationError',
- 'Can not add ICE candidate'));
- }
- }
- return Promise.resolve();
- };
-
- RTCPeerConnection.prototype.getStats = function() {
- var promises = [];
- this.transceivers.forEach(function(transceiver) {
- ['rtpSender', 'rtpReceiver', 'iceGatherer', 'iceTransport',
- 'dtlsTransport'].forEach(function(method) {
- if (transceiver[method]) {
- promises.push(transceiver[method].getStats());
- }
- });
- });
- var fixStatsType = function(stat) {
- return {
- inboundrtp: 'inbound-rtp',
- outboundrtp: 'outbound-rtp',
- candidatepair: 'candidate-pair',
- localcandidate: 'local-candidate',
- remotecandidate: 'remote-candidate'
- }[stat.type] || stat.type;
- };
- return new Promise(function(resolve) {
- // shim getStats with maplike support
- var results = new Map();
- Promise.all(promises).then(function(res) {
- res.forEach(function(result) {
- Object.keys(result).forEach(function(id) {
- result[id].type = fixStatsType(result[id]);
- results.set(id, result[id]);
- });
- });
- resolve(results);
- });
- });
- };
-
- // legacy callback shims. Should be moved to adapter.js some days.
- var methods = ['createOffer', 'createAnswer'];
- methods.forEach(function(method) {
- var nativeMethod = RTCPeerConnection.prototype[method];
- RTCPeerConnection.prototype[method] = function() {
- var args = arguments;
- if (typeof args[0] === 'function' ||
- typeof args[1] === 'function') { // legacy
- return nativeMethod.apply(this, [arguments[2]])
- .then(function(description) {
- if (typeof args[0] === 'function') {
- args[0].apply(null, [description]);
- }
- }, function(error) {
- if (typeof args[1] === 'function') {
- args[1].apply(null, [error]);
- }
- });
- }
- return nativeMethod.apply(this, arguments);
- };
- });
-
- methods = ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate'];
- methods.forEach(function(method) {
- var nativeMethod = RTCPeerConnection.prototype[method];
- RTCPeerConnection.prototype[method] = function() {
- var args = arguments;
- if (typeof args[1] === 'function' ||
- typeof args[2] === 'function') { // legacy
- return nativeMethod.apply(this, arguments)
- .then(function() {
- if (typeof args[1] === 'function') {
- args[1].apply(null);
- }
- }, function(error) {
- if (typeof args[2] === 'function') {
- args[2].apply(null, [error]);
- }
- });
- }
- return nativeMethod.apply(this, arguments);
- };
- });
-
- // getStats is special. It doesn't have a spec legacy method yet we support
- // getStats(something, cb) without error callbacks.
- ['getStats'].forEach(function(method) {
- var nativeMethod = RTCPeerConnection.prototype[method];
- RTCPeerConnection.prototype[method] = function() {
- var args = arguments;
- if (typeof args[1] === 'function') {
- return nativeMethod.apply(this, arguments)
- .then(function() {
- if (typeof args[1] === 'function') {
- args[1].apply(null);
- }
- });
- }
- return nativeMethod.apply(this, arguments);
- };
- });
-
- return RTCPeerConnection;
-};
-
-},{"sdp":2}],2:[function(require,module,exports){
- /* eslint-env node */
-'use strict';
-
-// SDP helpers.
-var SDPUtils = {};
-
-// Generate an alphanumeric identifier for cname or mids.
-// TODO: use UUIDs instead? https://gist.github.com/jed/982883
-SDPUtils.generateIdentifier = function() {
- return Math.random().toString(36).substr(2, 10);
-};
-
-// The RTCP CNAME used by all peerconnections from the same JS.
-SDPUtils.localCName = SDPUtils.generateIdentifier();
-
-// Splits SDP into lines, dealing with both CRLF and LF.
-SDPUtils.splitLines = function(blob) {
- return blob.trim().split('\n').map(function(line) {
- return line.trim();
- });
-};
-// Splits SDP into sessionpart and mediasections. Ensures CRLF.
-SDPUtils.splitSections = function(blob) {
- var parts = blob.split('\nm=');
- return parts.map(function(part, index) {
- return (index > 0 ? 'm=' + part : part).trim() + '\r\n';
- });
-};
-
-// Returns lines that start with a certain prefix.
-SDPUtils.matchPrefix = function(blob, prefix) {
- return SDPUtils.splitLines(blob).filter(function(line) {
- return line.indexOf(prefix) === 0;
- });
-};
-
-// Parses an ICE candidate line. Sample input:
-// candidate:702786350 2 udp 41819902 8.8.8.8 60769 typ relay raddr 8.8.8.8
-// rport 55996"
-SDPUtils.parseCandidate = function(line) {
- var parts;
- // Parse both variants.
- if (line.indexOf('a=candidate:') === 0) {
- parts = line.substring(12).split(' ');
- } else {
- parts = line.substring(10).split(' ');
- }
-
- var candidate = {
- foundation: parts[0],
- component: parseInt(parts[1], 10),
- protocol: parts[2].toLowerCase(),
- priority: parseInt(parts[3], 10),
- ip: parts[4],
- port: parseInt(parts[5], 10),
- // skip parts[6] == 'typ'
- type: parts[7]
- };
-
- for (var i = 8; i < parts.length; i += 2) {
- switch (parts[i]) {
- case 'raddr':
- candidate.relatedAddress = parts[i + 1];
- break;
- case 'rport':
- candidate.relatedPort = parseInt(parts[i + 1], 10);
- break;
- case 'tcptype':
- candidate.tcpType = parts[i + 1];
- break;
- case 'ufrag':
- candidate.ufrag = parts[i + 1]; // for backward compability.
- candidate.usernameFragment = parts[i + 1];
- break;
- default: // extension handling, in particular ufrag
- candidate[parts[i]] = parts[i + 1];
- break;
- }
- }
- return candidate;
-};
-
-// Translates a candidate object into SDP candidate attribute.
-SDPUtils.writeCandidate = function(candidate) {
- var sdp = [];
- sdp.push(candidate.foundation);
- sdp.push(candidate.component);
- sdp.push(candidate.protocol.toUpperCase());
- sdp.push(candidate.priority);
- sdp.push(candidate.ip);
- sdp.push(candidate.port);
-
- var type = candidate.type;
- sdp.push('typ');
- sdp.push(type);
- if (type !== 'host' && candidate.relatedAddress &&
- candidate.relatedPort) {
- sdp.push('raddr');
- sdp.push(candidate.relatedAddress); // was: relAddr
- sdp.push('rport');
- sdp.push(candidate.relatedPort); // was: relPort
- }
- if (candidate.tcpType && candidate.protocol.toLowerCase() === 'tcp') {
- sdp.push('tcptype');
- sdp.push(candidate.tcpType);
- }
- if (candidate.ufrag) {
- sdp.push('ufrag');
- sdp.push(candidate.ufrag);
- }
- return 'candidate:' + sdp.join(' ');
-};
-
-// Parses an ice-options line, returns an array of option tags.
-// a=ice-options:foo bar
-SDPUtils.parseIceOptions = function(line) {
- return line.substr(14).split(' ');
-}
-
-// Parses an rtpmap line, returns RTCRtpCoddecParameters. Sample input:
-// a=rtpmap:111 opus/48000/2
-SDPUtils.parseRtpMap = function(line) {
- var parts = line.substr(9).split(' ');
- var parsed = {
- payloadType: parseInt(parts.shift(), 10) // was: id
- };
-
- parts = parts[0].split('/');
-
- parsed.name = parts[0];
- parsed.clockRate = parseInt(parts[1], 10); // was: clockrate
- // was: channels
- parsed.numChannels = parts.length === 3 ? parseInt(parts[2], 10) : 1;
- return parsed;
-};
-
-// Generate an a=rtpmap line from RTCRtpCodecCapability or
-// RTCRtpCodecParameters.
-SDPUtils.writeRtpMap = function(codec) {
- var pt = codec.payloadType;
- if (codec.preferredPayloadType !== undefined) {
- pt = codec.preferredPayloadType;
- }
- return 'a=rtpmap:' + pt + ' ' + codec.name + '/' + codec.clockRate +
- (codec.numChannels !== 1 ? '/' + codec.numChannels : '') + '\r\n';
-};
-
-// Parses an a=extmap line (headerextension from RFC 5285). Sample input:
-// a=extmap:2 urn:ietf:params:rtp-hdrext:toffset
-// a=extmap:2/sendonly urn:ietf:params:rtp-hdrext:toffset
-SDPUtils.parseExtmap = function(line) {
- var parts = line.substr(9).split(' ');
- return {
- id: parseInt(parts[0], 10),
- direction: parts[0].indexOf('/') > 0 ? parts[0].split('/')[1] : 'sendrecv',
- uri: parts[1]
- };
-};
-
-// Generates a=extmap line from RTCRtpHeaderExtensionParameters or
-// RTCRtpHeaderExtension.
-SDPUtils.writeExtmap = function(headerExtension) {
- return 'a=extmap:' + (headerExtension.id || headerExtension.preferredId) +
- (headerExtension.direction && headerExtension.direction !== 'sendrecv'
- ? '/' + headerExtension.direction
- : '') +
- ' ' + headerExtension.uri + '\r\n';
-};
-
-// Parses an ftmp line, returns dictionary. Sample input:
-// a=fmtp:96 vbr=on;cng=on
-// Also deals with vbr=on; cng=on
-SDPUtils.parseFmtp = function(line) {
- var parsed = {};
- var kv;
- var parts = line.substr(line.indexOf(' ') + 1).split(';');
- for (var j = 0; j < parts.length; j++) {
- kv = parts[j].trim().split('=');
- parsed[kv[0].trim()] = kv[1];
- }
- return parsed;
-};
-
-// Generates an a=ftmp line from RTCRtpCodecCapability or RTCRtpCodecParameters.
-SDPUtils.writeFmtp = function(codec) {
- var line = '';
- var pt = codec.payloadType;
- if (codec.preferredPayloadType !== undefined) {
- pt = codec.preferredPayloadType;
- }
- if (codec.parameters && Object.keys(codec.parameters).length) {
- var params = [];
- Object.keys(codec.parameters).forEach(function(param) {
- params.push(param + '=' + codec.parameters[param]);
- });
- line += 'a=fmtp:' + pt + ' ' + params.join(';') + '\r\n';
- }
- return line;
-};
-
-// Parses an rtcp-fb line, returns RTCPRtcpFeedback object. Sample input:
-// a=rtcp-fb:98 nack rpsi
-SDPUtils.parseRtcpFb = function(line) {
- var parts = line.substr(line.indexOf(' ') + 1).split(' ');
- return {
- type: parts.shift(),
- parameter: parts.join(' ')
- };
-};
-// Generate a=rtcp-fb lines from RTCRtpCodecCapability or RTCRtpCodecParameters.
-SDPUtils.writeRtcpFb = function(codec) {
- var lines = '';
- var pt = codec.payloadType;
- if (codec.preferredPayloadType !== undefined) {
- pt = codec.preferredPayloadType;
- }
- if (codec.rtcpFeedback && codec.rtcpFeedback.length) {
- // FIXME: special handling for trr-int?
- codec.rtcpFeedback.forEach(function(fb) {
- lines += 'a=rtcp-fb:' + pt + ' ' + fb.type +
- (fb.parameter && fb.parameter.length ? ' ' + fb.parameter : '') +
- '\r\n';
- });
- }
- return lines;
-};
-
-// Parses an RFC 5576 ssrc media attribute. Sample input:
-// a=ssrc:3735928559 cname:something
-SDPUtils.parseSsrcMedia = function(line) {
- var sp = line.indexOf(' ');
- var parts = {
- ssrc: parseInt(line.substr(7, sp - 7), 10)
- };
- var colon = line.indexOf(':', sp);
- if (colon > -1) {
- parts.attribute = line.substr(sp + 1, colon - sp - 1);
- parts.value = line.substr(colon + 1);
- } else {
- parts.attribute = line.substr(sp + 1);
- }
- return parts;
-};
-
-// Extracts the MID (RFC 5888) from a media section.
-// returns the MID or undefined if no mid line was found.
-SDPUtils.getMid = function(mediaSection) {
- var mid = SDPUtils.matchPrefix(mediaSection, 'a=mid:')[0];
- if (mid) {
- return mid.substr(6);
- }
-}
-
-SDPUtils.parseFingerprint = function(line) {
- var parts = line.substr(14).split(' ');
- return {
- algorithm: parts[0].toLowerCase(), // algorithm is case-sensitive in Edge.
- value: parts[1]
- };
-};
-
-// Extracts DTLS parameters from SDP media section or sessionpart.
-// FIXME: for consistency with other functions this should only
-// get the fingerprint line as input. See also getIceParameters.
-SDPUtils.getDtlsParameters = function(mediaSection, sessionpart) {
- var lines = SDPUtils.matchPrefix(mediaSection + sessionpart,
- 'a=fingerprint:');
- // Note: a=setup line is ignored since we use the 'auto' role.
- // Note2: 'algorithm' is not case sensitive except in Edge.
- return {
- role: 'auto',
- fingerprints: lines.map(SDPUtils.parseFingerprint)
- };
-};
-
-// Serializes DTLS parameters to SDP.
-SDPUtils.writeDtlsParameters = function(params, setupType) {
- var sdp = 'a=setup:' + setupType + '\r\n';
- params.fingerprints.forEach(function(fp) {
- sdp += 'a=fingerprint:' + fp.algorithm + ' ' + fp.value + '\r\n';
- });
- return sdp;
-};
-// Parses ICE information from SDP media section or sessionpart.
-// FIXME: for consistency with other functions this should only
-// get the ice-ufrag and ice-pwd lines as input.
-SDPUtils.getIceParameters = function(mediaSection, sessionpart) {
- var lines = SDPUtils.splitLines(mediaSection);
- // Search in session part, too.
- lines = lines.concat(SDPUtils.splitLines(sessionpart));
- var iceParameters = {
- usernameFragment: lines.filter(function(line) {
- return line.indexOf('a=ice-ufrag:') === 0;
- })[0].substr(12),
- password: lines.filter(function(line) {
- return line.indexOf('a=ice-pwd:') === 0;
- })[0].substr(10)
- };
- return iceParameters;
-};
-
-// Serializes ICE parameters to SDP.
-SDPUtils.writeIceParameters = function(params) {
- return 'a=ice-ufrag:' + params.usernameFragment + '\r\n' +
- 'a=ice-pwd:' + params.password + '\r\n';
-};
-
-// Parses the SDP media section and returns RTCRtpParameters.
-SDPUtils.parseRtpParameters = function(mediaSection) {
- var description = {
- codecs: [],
- headerExtensions: [],
- fecMechanisms: [],
- rtcp: []
- };
- var lines = SDPUtils.splitLines(mediaSection);
- var mline = lines[0].split(' ');
- for (var i = 3; i < mline.length; i++) { // find all codecs from mline[3..]
- var pt = mline[i];
- var rtpmapline = SDPUtils.matchPrefix(
- mediaSection, 'a=rtpmap:' + pt + ' ')[0];
- if (rtpmapline) {
- var codec = SDPUtils.parseRtpMap(rtpmapline);
- var fmtps = SDPUtils.matchPrefix(
- mediaSection, 'a=fmtp:' + pt + ' ');
- // Only the first a=fmtp: is considered.
- codec.parameters = fmtps.length ? SDPUtils.parseFmtp(fmtps[0]) : {};
- codec.rtcpFeedback = SDPUtils.matchPrefix(
- mediaSection, 'a=rtcp-fb:' + pt + ' ')
- .map(SDPUtils.parseRtcpFb);
- description.codecs.push(codec);
- // parse FEC mechanisms from rtpmap lines.
- switch (codec.name.toUpperCase()) {
- case 'RED':
- case 'ULPFEC':
- description.fecMechanisms.push(codec.name.toUpperCase());
- break;
- default: // only RED and ULPFEC are recognized as FEC mechanisms.
- break;
- }
- }
- }
- SDPUtils.matchPrefix(mediaSection, 'a=extmap:').forEach(function(line) {
- description.headerExtensions.push(SDPUtils.parseExtmap(line));
- });
- // FIXME: parse rtcp.
- return description;
-};
-
-// Generates parts of the SDP media section describing the capabilities /
-// parameters.
-SDPUtils.writeRtpDescription = function(kind, caps) {
- var sdp = '';
-
- // Build the mline.
- sdp += 'm=' + kind + ' ';
- sdp += caps.codecs.length > 0 ? '9' : '0'; // reject if no codecs.
- sdp += ' UDP/TLS/RTP/SAVPF ';
- sdp += caps.codecs.map(function(codec) {
- if (codec.preferredPayloadType !== undefined) {
- return codec.preferredPayloadType;
- }
- return codec.payloadType;
- }).join(' ') + '\r\n';
-
- sdp += 'c=IN IP4 0.0.0.0\r\n';
- sdp += 'a=rtcp:9 IN IP4 0.0.0.0\r\n';
-
- // Add a=rtpmap lines for each codec. Also fmtp and rtcp-fb.
- caps.codecs.forEach(function(codec) {
- sdp += SDPUtils.writeRtpMap(codec);
- sdp += SDPUtils.writeFmtp(codec);
- sdp += SDPUtils.writeRtcpFb(codec);
- });
- var maxptime = 0;
- caps.codecs.forEach(function(codec) {
- if (codec.maxptime > maxptime) {
- maxptime = codec.maxptime;
- }
- });
- if (maxptime > 0) {
- sdp += 'a=maxptime:' + maxptime + '\r\n';
- }
- sdp += 'a=rtcp-mux\r\n';
-
- caps.headerExtensions.forEach(function(extension) {
- sdp += SDPUtils.writeExtmap(extension);
- });
- // FIXME: write fecMechanisms.
- return sdp;
-};
-
-// Parses the SDP media section and returns an array of
-// RTCRtpEncodingParameters.
-SDPUtils.parseRtpEncodingParameters = function(mediaSection) {
- var encodingParameters = [];
- var description = SDPUtils.parseRtpParameters(mediaSection);
- var hasRed = description.fecMechanisms.indexOf('RED') !== -1;
- var hasUlpfec = description.fecMechanisms.indexOf('ULPFEC') !== -1;
-
- // filter a=ssrc:... cname:, ignore PlanB-msid
- var ssrcs = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:')
- .map(function(line) {
- return SDPUtils.parseSsrcMedia(line);
- })
- .filter(function(parts) {
- return parts.attribute === 'cname';
- });
- var primarySsrc = ssrcs.length > 0 && ssrcs[0].ssrc;
- var secondarySsrc;
-
- var flows = SDPUtils.matchPrefix(mediaSection, 'a=ssrc-group:FID')
- .map(function(line) {
- var parts = line.split(' ');
- parts.shift();
- return parts.map(function(part) {
- return parseInt(part, 10);
- });
- });
- if (flows.length > 0 && flows[0].length > 1 && flows[0][0] === primarySsrc) {
- secondarySsrc = flows[0][1];
- }
-
- description.codecs.forEach(function(codec) {
- if (codec.name.toUpperCase() === 'RTX' && codec.parameters.apt) {
- var encParam = {
- ssrc: primarySsrc,
- codecPayloadType: parseInt(codec.parameters.apt, 10),
- rtx: {
- ssrc: secondarySsrc
- }
- };
- encodingParameters.push(encParam);
- if (hasRed) {
- encParam = JSON.parse(JSON.stringify(encParam));
- encParam.fec = {
- ssrc: secondarySsrc,
- mechanism: hasUlpfec ? 'red+ulpfec' : 'red'
- };
- encodingParameters.push(encParam);
- }
- }
- });
- if (encodingParameters.length === 0 && primarySsrc) {
- encodingParameters.push({
- ssrc: primarySsrc
- });
- }
-
- // we support both b=AS and b=TIAS but interpret AS as TIAS.
- var bandwidth = SDPUtils.matchPrefix(mediaSection, 'b=');
- if (bandwidth.length) {
- if (bandwidth[0].indexOf('b=TIAS:') === 0) {
- bandwidth = parseInt(bandwidth[0].substr(7), 10);
- } else if (bandwidth[0].indexOf('b=AS:') === 0) {
- // use formula from JSEP to convert b=AS to TIAS value.
- bandwidth = parseInt(bandwidth[0].substr(5), 10) * 1000 * 0.95
- - (50 * 40 * 8);
- } else {
- bandwidth = undefined;
- }
- encodingParameters.forEach(function(params) {
- params.maxBitrate = bandwidth;
- });
- }
- return encodingParameters;
-};
-
-// parses http://draft.ortc.org/#rtcrtcpparameters*
-SDPUtils.parseRtcpParameters = function(mediaSection) {
- var rtcpParameters = {};
-
- var cname;
- // Gets the first SSRC. Note that with RTX there might be multiple
- // SSRCs.
- var remoteSsrc = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:')
- .map(function(line) {
- return SDPUtils.parseSsrcMedia(line);
- })
- .filter(function(obj) {
- return obj.attribute === 'cname';
- })[0];
- if (remoteSsrc) {
- rtcpParameters.cname = remoteSsrc.value;
- rtcpParameters.ssrc = remoteSsrc.ssrc;
- }
-
- // Edge uses the compound attribute instead of reducedSize
- // compound is !reducedSize
- var rsize = SDPUtils.matchPrefix(mediaSection, 'a=rtcp-rsize');
- rtcpParameters.reducedSize = rsize.length > 0;
- rtcpParameters.compound = rsize.length === 0;
-
- // parses the rtcp-mux attrŃ–bute.
- // Note that Edge does not support unmuxed RTCP.
- var mux = SDPUtils.matchPrefix(mediaSection, 'a=rtcp-mux');
- rtcpParameters.mux = mux.length > 0;
-
- return rtcpParameters;
-};
-
-// parses either a=msid: or a=ssrc:... msid lines and returns
-// the id of the MediaStream and MediaStreamTrack.
-SDPUtils.parseMsid = function(mediaSection) {
- var parts;
- var spec = SDPUtils.matchPrefix(mediaSection, 'a=msid:');
- if (spec.length === 1) {
- parts = spec[0].substr(7).split(' ');
- return {stream: parts[0], track: parts[1]};
- }
- var planB = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:')
- .map(function(line) {
- return SDPUtils.parseSsrcMedia(line);
- })
- .filter(function(parts) {
- return parts.attribute === 'msid';
- });
- if (planB.length > 0) {
- parts = planB[0].value.split(' ');
- return {stream: parts[0], track: parts[1]};
- }
-};
-
-// Generate a session ID for SDP.
-// https://tools.ietf.org/html/draft-ietf-rtcweb-jsep-20#section-5.2.1
-// recommends using a cryptographically random +ve 64-bit value
-// but right now this should be acceptable and within the right range
-SDPUtils.generateSessionId = function() {
- return Math.random().toString().substr(2, 21);
-};
-
-// Write boilder plate for start of SDP
-// sessId argument is optional - if not supplied it will
-// be generated randomly
-// sessVersion is optional and defaults to 2
-SDPUtils.writeSessionBoilerplate = function(sessId, sessVer) {
- var sessionId;
- var version = sessVer !== undefined ? sessVer : 2;
- if (sessId) {
- sessionId = sessId;
- } else {
- sessionId = SDPUtils.generateSessionId();
- }
- // FIXME: sess-id should be an NTP timestamp.
- return 'v=0\r\n' +
- 'o=thisisadapterortc ' + sessionId + ' ' + version + ' IN IP4 127.0.0.1\r\n' +
- 's=-\r\n' +
- 't=0 0\r\n';
-};
-
-SDPUtils.writeMediaSection = function(transceiver, caps, type, stream) {
- var sdp = SDPUtils.writeRtpDescription(transceiver.kind, caps);
-
- // Map ICE parameters (ufrag, pwd) to SDP.
- sdp += SDPUtils.writeIceParameters(
- transceiver.iceGatherer.getLocalParameters());
-
- // Map DTLS parameters to SDP.
- sdp += SDPUtils.writeDtlsParameters(
- transceiver.dtlsTransport.getLocalParameters(),
- type === 'offer' ? 'actpass' : 'active');
-
- sdp += 'a=mid:' + transceiver.mid + '\r\n';
-
- if (transceiver.direction) {
- sdp += 'a=' + transceiver.direction + '\r\n';
- } else if (transceiver.rtpSender && transceiver.rtpReceiver) {
- sdp += 'a=sendrecv\r\n';
- } else if (transceiver.rtpSender) {
- sdp += 'a=sendonly\r\n';
- } else if (transceiver.rtpReceiver) {
- sdp += 'a=recvonly\r\n';
- } else {
- sdp += 'a=inactive\r\n';
- }
-
- if (transceiver.rtpSender) {
- // spec.
- var msid = 'msid:' + stream.id + ' ' +
- transceiver.rtpSender.track.id + '\r\n';
- sdp += 'a=' + msid;
-
- // for Chrome.
- sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].ssrc +
- ' ' + msid;
- if (transceiver.sendEncodingParameters[0].rtx) {
- sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].rtx.ssrc +
- ' ' + msid;
- sdp += 'a=ssrc-group:FID ' +
- transceiver.sendEncodingParameters[0].ssrc + ' ' +
- transceiver.sendEncodingParameters[0].rtx.ssrc +
- '\r\n';
- }
- }
- // FIXME: this should be written by writeRtpDescription.
- sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].ssrc +
- ' cname:' + SDPUtils.localCName + '\r\n';
- if (transceiver.rtpSender && transceiver.sendEncodingParameters[0].rtx) {
- sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].rtx.ssrc +
- ' cname:' + SDPUtils.localCName + '\r\n';
- }
- return sdp;
-};
-
-// Gets the direction from the mediaSection or the sessionpart.
-SDPUtils.getDirection = function(mediaSection, sessionpart) {
- // Look for sendrecv, sendonly, recvonly, inactive, default to sendrecv.
- var lines = SDPUtils.splitLines(mediaSection);
- for (var i = 0; i < lines.length; i++) {
- switch (lines[i]) {
- case 'a=sendrecv':
- case 'a=sendonly':
- case 'a=recvonly':
- case 'a=inactive':
- return lines[i].substr(2);
- default:
- // FIXME: What should happen here?
- }
- }
- if (sessionpart) {
- return SDPUtils.getDirection(sessionpart);
- }
- return 'sendrecv';
-};
-
-SDPUtils.getKind = function(mediaSection) {
- var lines = SDPUtils.splitLines(mediaSection);
- var mline = lines[0].split(' ');
- return mline[0].substr(2);
-};
-
-SDPUtils.isRejected = function(mediaSection) {
- return mediaSection.split(' ', 2)[1] === '0';
-};
-
-SDPUtils.parseMLine = function(mediaSection) {
- var lines = SDPUtils.splitLines(mediaSection);
- var mline = lines[0].split(' ');
- return {
- kind: mline[0].substr(2),
- port: parseInt(mline[1], 10),
- protocol: mline[2],
- fmt: mline.slice(3).join(' ')
- };
-};
-
-// Expose public methods.
-if (typeof module === 'object') {
- module.exports = SDPUtils;
-}
-
-},{}],3:[function(require,module,exports){
-(function (global){
-/*
- * Copyright (c) 2016 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.
- */
- /* eslint-env node */
-
-'use strict';
-
-var adapterFactory = require('./adapter_factory.js');
-module.exports = adapterFactory({window: global.window});
-
-}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-},{"./adapter_factory.js":4}],4:[function(require,module,exports){
-/*
- * Copyright (c) 2016 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.
- */
- /* eslint-env node */
-
-'use strict';
-
-var utils = require('./utils');
-// Shimming starts here.
-module.exports = function(dependencies, opts) {
- var window = dependencies && dependencies.window;
-
- var options = {
- shimChrome: true,
- shimFirefox: true,
- shimEdge: true,
- shimSafari: true,
- };
-
- for (var key in opts) {
- if (hasOwnProperty.call(opts, key)) {
- options[key] = opts[key];
- }
- }
-
- // Utils.
- var logging = utils.log;
- var browserDetails = utils.detectBrowser(window);
-
- // Uncomment the line below if you want logging to occur, including logging
- // for the switch statement below. Can also be turned on in the browser via
- // adapter.disableLog(false), but then logging from the switch statement below
- // will not appear.
- // require('./utils').disableLog(false);
-
- // Browser shims.
- var chromeShim = require('./chrome/chrome_shim') || null;
- var edgeShim = require('./edge/edge_shim') || null;
- var firefoxShim = require('./firefox/firefox_shim') || null;
- var safariShim = require('./safari/safari_shim') || null;
- var commonShim = require('./common_shim') || null;
-
- // Export to the adapter global object visible in the browser.
- var adapter = {
- browserDetails: browserDetails,
- commonShim: commonShim,
- extractVersion: utils.extractVersion,
- disableLog: utils.disableLog,
- disableWarnings: utils.disableWarnings
- };
-
- // Shim browser if found.
- switch (browserDetails.browser) {
- case 'chrome':
- if (!chromeShim || !chromeShim.shimPeerConnection ||
- !options.shimChrome) {
- logging('Chrome shim is not included in this adapter release.');
- return adapter;
- }
- logging('adapter.js shimming chrome.');
- // Export to the adapter global object visible in the browser.
- adapter.browserShim = chromeShim;
- commonShim.shimCreateObjectURL(window);
-
- chromeShim.shimGetUserMedia(window);
- chromeShim.shimMediaStream(window);
- chromeShim.shimSourceObject(window);
- chromeShim.shimPeerConnection(window);
- chromeShim.shimOnTrack(window);
- chromeShim.shimAddTrackRemoveTrack(window);
- chromeShim.shimGetSendersWithDtmf(window);
-
- commonShim.shimRTCIceCandidate(window);
- commonShim.shimMaxMessageSize(window);
- commonShim.shimSendThrowTypeError(window);
- break;
- case 'firefox':
- if (!firefoxShim || !firefoxShim.shimPeerConnection ||
- !options.shimFirefox) {
- logging('Firefox shim is not included in this adapter release.');
- return adapter;
- }
- logging('adapter.js shimming firefox.');
- // Export to the adapter global object visible in the browser.
- adapter.browserShim = firefoxShim;
- commonShim.shimCreateObjectURL(window);
-
- firefoxShim.shimGetUserMedia(window);
- firefoxShim.shimSourceObject(window);
- firefoxShim.shimPeerConnection(window);
- firefoxShim.shimOnTrack(window);
- firefoxShim.shimRemoveStream(window);
-
- commonShim.shimRTCIceCandidate(window);
- commonShim.shimMaxMessageSize(window);
- commonShim.shimSendThrowTypeError(window);
- break;
- case 'edge':
- if (!edgeShim || !edgeShim.shimPeerConnection || !options.shimEdge) {
- logging('MS edge shim is not included in this adapter release.');
- return adapter;
- }
- logging('adapter.js shimming edge.');
- // Export to the adapter global object visible in the browser.
- adapter.browserShim = edgeShim;
- commonShim.shimCreateObjectURL(window);
-
- edgeShim.shimGetUserMedia(window);
- edgeShim.shimPeerConnection(window);
- edgeShim.shimReplaceTrack(window);
-
- // the edge shim implements the full RTCIceCandidate object.
-
- commonShim.shimMaxMessageSize(window);
- commonShim.shimSendThrowTypeError(window);
- break;
- case 'safari':
- if (!safariShim || !options.shimSafari) {
- logging('Safari shim is not included in this adapter release.');
- return adapter;
- }
- logging('adapter.js shimming safari.');
- // Export to the adapter global object visible in the browser.
- adapter.browserShim = safariShim;
- commonShim.shimCreateObjectURL(window);
-
- safariShim.shimRTCIceServerUrls(window);
- safariShim.shimCallbacksAPI(window);
- safariShim.shimLocalStreamsAPI(window);
- safariShim.shimRemoteStreamsAPI(window);
- safariShim.shimTrackEventTransceiver(window);
- safariShim.shimGetUserMedia(window);
- safariShim.shimCreateOfferLegacy(window);
-
- commonShim.shimRTCIceCandidate(window);
- commonShim.shimMaxMessageSize(window);
- commonShim.shimSendThrowTypeError(window);
- break;
- default:
- logging('Unsupported browser!');
- break;
- }
-
- return adapter;
-};
-
-},{"./chrome/chrome_shim":5,"./common_shim":7,"./edge/edge_shim":8,"./firefox/firefox_shim":10,"./safari/safari_shim":12,"./utils":13}],5:[function(require,module,exports){
-
-/*
- * Copyright (c) 2016 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.
- */
- /* eslint-env node */
-'use strict';
-var utils = require('../utils.js');
-var logging = utils.log;
-
-module.exports = {
- shimGetUserMedia: require('./getusermedia'),
- shimMediaStream: function(window) {
- window.MediaStream = window.MediaStream || window.webkitMediaStream;
- },
-
- shimOnTrack: function(window) {
- if (typeof window === 'object' && window.RTCPeerConnection && !('ontrack' in
- window.RTCPeerConnection.prototype)) {
- Object.defineProperty(window.RTCPeerConnection.prototype, 'ontrack', {
- get: function() {
- return this._ontrack;
- },
- set: function(f) {
- if (this._ontrack) {
- this.removeEventListener('track', this._ontrack);
- }
- this.addEventListener('track', this._ontrack = f);
- }
- });
- var origSetRemoteDescription =
- window.RTCPeerConnection.prototype.setRemoteDescription;
- window.RTCPeerConnection.prototype.setRemoteDescription = function() {
- var pc = this;
- if (!pc._ontrackpoly) {
- pc._ontrackpoly = function(e) {
- // onaddstream does not fire when a track is added to an existing
- // stream. But stream.onaddtrack is implemented so we use that.
- e.stream.addEventListener('addtrack', function(te) {
- var receiver;
- if (window.RTCPeerConnection.prototype.getReceivers) {
- receiver = pc.getReceivers().find(function(r) {
- return r.track && r.track.id === te.track.id;
- });
- } else {
- receiver = {track: te.track};
- }
-
- var event = new Event('track');
- event.track = te.track;
- event.receiver = receiver;
- event.transceiver = {receiver: receiver};
- event.streams = [e.stream];
- pc.dispatchEvent(event);
- });
- e.stream.getTracks().forEach(function(track) {
- var receiver;
- if (window.RTCPeerConnection.prototype.getReceivers) {
- receiver = pc.getReceivers().find(function(r) {
- return r.track && r.track.id === track.id;
- });
- } else {
- receiver = {track: track};
- }
- var event = new Event('track');
- event.track = track;
- event.receiver = receiver;
- event.transceiver = {receiver: receiver};
- event.streams = [e.stream];
- pc.dispatchEvent(event);
- });
- };
- pc.addEventListener('addstream', pc._ontrackpoly);
- }
- return origSetRemoteDescription.apply(pc, arguments);
- };
- } else if (!('RTCRtpTransceiver' in window)) {
- utils.wrapPeerConnectionEvent(window, 'track', function(e) {
- if (!e.transceiver) {
- e.transceiver = {receiver: e.receiver};
- }
- return e;
- });
- }
- },
-
- shimGetSendersWithDtmf: function(window) {
- // Overrides addTrack/removeTrack, depends on shimAddTrackRemoveTrack.
- if (typeof window === 'object' && window.RTCPeerConnection &&
- !('getSenders' in window.RTCPeerConnection.prototype) &&
- 'createDTMFSender' in window.RTCPeerConnection.prototype) {
- var shimSenderWithDtmf = function(pc, track) {
- return {
- track: track,
- get dtmf() {
- if (this._dtmf === undefined) {
- if (track.kind === 'audio') {
- this._dtmf = pc.createDTMFSender(track);
- } else {
- this._dtmf = null;
- }
- }
- return this._dtmf;
- },
- _pc: pc
- };
- };
-
- // augment addTrack when getSenders is not available.
- if (!window.RTCPeerConnection.prototype.getSenders) {
- window.RTCPeerConnection.prototype.getSenders = function() {
- this._senders = this._senders || [];
- return this._senders.slice(); // return a copy of the internal state.
- };
- var origAddTrack = window.RTCPeerConnection.prototype.addTrack;
- window.RTCPeerConnection.prototype.addTrack = function(track, stream) {
- var pc = this;
- var sender = origAddTrack.apply(pc, arguments);
- if (!sender) {
- sender = shimSenderWithDtmf(pc, track);
- pc._senders.push(sender);
- }
- return sender;
- };
-
- var origRemoveTrack = window.RTCPeerConnection.prototype.removeTrack;
- window.RTCPeerConnection.prototype.removeTrack = function(sender) {
- var pc = this;
- origRemoveTrack.apply(pc, arguments);
- var idx = pc._senders.indexOf(sender);
- if (idx !== -1) {
- pc._senders.splice(idx, 1);
- }
- };
- }
- var origAddStream = window.RTCPeerConnection.prototype.addStream;
- window.RTCPeerConnection.prototype.addStream = function(stream) {
- var pc = this;
- pc._senders = pc._senders || [];
- origAddStream.apply(pc, [stream]);
- stream.getTracks().forEach(function(track) {
- pc._senders.push(shimSenderWithDtmf(pc, track));
- });
- };
-
- var origRemoveStream = window.RTCPeerConnection.prototype.removeStream;
- window.RTCPeerConnection.prototype.removeStream = function(stream) {
- var pc = this;
- pc._senders = pc._senders || [];
- origRemoveStream.apply(pc, [stream]);
-
- stream.getTracks().forEach(function(track) {
- var sender = pc._senders.find(function(s) {
- return s.track === track;
- });
- if (sender) {
- pc._senders.splice(pc._senders.indexOf(sender), 1); // remove sender
- }
- });
- };
- } else if (typeof window === 'object' && window.RTCPeerConnection &&
- 'getSenders' in window.RTCPeerConnection.prototype &&
- 'createDTMFSender' in window.RTCPeerConnection.prototype &&
- window.RTCRtpSender &&
- !('dtmf' in window.RTCRtpSender.prototype)) {
- var origGetSenders = window.RTCPeerConnection.prototype.getSenders;
- window.RTCPeerConnection.prototype.getSenders = function() {
- var pc = this;
- var senders = origGetSenders.apply(pc, []);
- senders.forEach(function(sender) {
- sender._pc = pc;
- });
- return senders;
- };
-
- Object.defineProperty(window.RTCRtpSender.prototype, 'dtmf', {
- get: function() {
- if (this._dtmf === undefined) {
- if (this.track.kind === 'audio') {
- this._dtmf = this._pc.createDTMFSender(this.track);
- } else {
- this._dtmf = null;
- }
- }
- return this._dtmf;
- }
- });
- }
- },
-
- shimSourceObject: function(window) {
- var URL = window && window.URL;
-
- 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() {
- return this._srcObject;
- },
- set: function(stream) {
- var self = this;
- // Use _srcObject as a private property for this shim
- this._srcObject = stream;
- if (this.src) {
- URL.revokeObjectURL(this.src);
- }
-
- if (!stream) {
- this.src = '';
- return undefined;
- }
- this.src = URL.createObjectURL(stream);
- // We need to recreate the blob url when a track is added or
- // removed. Doing it manually since we want to avoid a recursion.
- stream.addEventListener('addtrack', function() {
- if (self.src) {
- URL.revokeObjectURL(self.src);
- }
- self.src = URL.createObjectURL(stream);
- });
- stream.addEventListener('removetrack', function() {
- if (self.src) {
- URL.revokeObjectURL(self.src);
- }
- self.src = URL.createObjectURL(stream);
- });
- }
- });
- }
- }
- },
-
- shimAddTrackRemoveTrackWithNative: function(window) {
- // shim addTrack/removeTrack with native variants in order to make
- // the interactions with legacy getLocalStreams behave as in other browsers.
- // Keeps a mapping stream.id => [stream, rtpsenders...]
- window.RTCPeerConnection.prototype.getLocalStreams = function() {
- var pc = this;
- this._shimmedLocalStreams = this._shimmedLocalStreams || {};
- return Object.keys(this._shimmedLocalStreams).map(function(streamId) {
- return pc._shimmedLocalStreams[streamId][0];
- });
- };
-
- var origAddTrack = window.RTCPeerConnection.prototype.addTrack;
- window.RTCPeerConnection.prototype.addTrack = function(track, stream) {
- if (!stream) {
- return origAddTrack.apply(this, arguments);
- }
- this._shimmedLocalStreams = this._shimmedLocalStreams || {};
-
- var sender = origAddTrack.apply(this, arguments);
- if (!this._shimmedLocalStreams[stream.id]) {
- this._shimmedLocalStreams[stream.id] = [stream, sender];
- } else if (this._shimmedLocalStreams[stream.id].indexOf(sender) === -1) {
- this._shimmedLocalStreams[stream.id].push(sender);
- }
- return sender;
- };
-
- var origAddStream = window.RTCPeerConnection.prototype.addStream;
- window.RTCPeerConnection.prototype.addStream = function(stream) {
- var pc = this;
- this._shimmedLocalStreams = this._shimmedLocalStreams || {};
-
- stream.getTracks().forEach(function(track) {
- var alreadyExists = pc.getSenders().find(function(s) {
- return s.track === track;
- });
- if (alreadyExists) {
- throw new DOMException('Track already exists.',
- 'InvalidAccessError');
- }
- });
- var existingSenders = pc.getSenders();
- origAddStream.apply(this, arguments);
- var newSenders = pc.getSenders().filter(function(newSender) {
- return existingSenders.indexOf(newSender) === -1;
- });
- this._shimmedLocalStreams[stream.id] = [stream].concat(newSenders);
- };
-
- var origRemoveStream = window.RTCPeerConnection.prototype.removeStream;
- window.RTCPeerConnection.prototype.removeStream = function(stream) {
- this._shimmedLocalStreams = this._shimmedLocalStreams || {};
- delete this._shimmedLocalStreams[stream.id];
- return origRemoveStream.apply(this, arguments);
- };
-
- var origRemoveTrack = window.RTCPeerConnection.prototype.removeTrack;
- window.RTCPeerConnection.prototype.removeTrack = function(sender) {
- var pc = this;
- this._shimmedLocalStreams = this._shimmedLocalStreams || {};
- if (sender) {
- Object.keys(this._shimmedLocalStreams).forEach(function(streamId) {
- var idx = pc._shimmedLocalStreams[streamId].indexOf(sender);
- if (idx !== -1) {
- pc._shimmedLocalStreams[streamId].splice(idx, 1);
- }
- if (pc._shimmedLocalStreams[streamId].length === 1) {
- delete pc._shimmedLocalStreams[streamId];
- }
- });
- }
- return origRemoveTrack.apply(this, arguments);
- };
- },
-
- shimAddTrackRemoveTrack: function(window) {
- var browserDetails = utils.detectBrowser(window);
- // shim addTrack and removeTrack.
- if (window.RTCPeerConnection.prototype.addTrack &&
- browserDetails.version >= 65) {
- return this.shimAddTrackRemoveTrackWithNative(window);
- }
-
- // also shim pc.getLocalStreams when addTrack is shimmed
- // to return the original streams.
- var origGetLocalStreams = window.RTCPeerConnection.prototype
- .getLocalStreams;
- window.RTCPeerConnection.prototype.getLocalStreams = function() {
- var pc = this;
- var nativeStreams = origGetLocalStreams.apply(this);
- pc._reverseStreams = pc._reverseStreams || {};
- return nativeStreams.map(function(stream) {
- return pc._reverseStreams[stream.id];
- });
- };
-
- var origAddStream = window.RTCPeerConnection.prototype.addStream;
- window.RTCPeerConnection.prototype.addStream = function(stream) {
- var pc = this;
- pc._streams = pc._streams || {};
- pc._reverseStreams = pc._reverseStreams || {};
-
- stream.getTracks().forEach(function(track) {
- var alreadyExists = pc.getSenders().find(function(s) {
- return s.track === track;
- });
- if (alreadyExists) {
- throw new DOMException('Track already exists.',
- 'InvalidAccessError');
- }
- });
- // Add identity mapping for consistency with addTrack.
- // Unless this is being used with a stream from addTrack.
- if (!pc._reverseStreams[stream.id]) {
- var newStream = new window.MediaStream(stream.getTracks());
- pc._streams[stream.id] = newStream;
- pc._reverseStreams[newStream.id] = stream;
- stream = newStream;
- }
- origAddStream.apply(pc, [stream]);
- };
-
- var origRemoveStream = window.RTCPeerConnection.prototype.removeStream;
- window.RTCPeerConnection.prototype.removeStream = function(stream) {
- var pc = this;
- pc._streams = pc._streams || {};
- pc._reverseStreams = pc._reverseStreams || {};
-
- origRemoveStream.apply(pc, [(pc._streams[stream.id] || stream)]);
- delete pc._reverseStreams[(pc._streams[stream.id] ?
- pc._streams[stream.id].id : stream.id)];
- delete pc._streams[stream.id];
- };
-
- window.RTCPeerConnection.prototype.addTrack = function(track, stream) {
- var pc = this;
- if (pc.signalingState === 'closed') {
- throw new DOMException(
- 'The RTCPeerConnection\'s signalingState is \'closed\'.',
- 'InvalidStateError');
- }
- var streams = [].slice.call(arguments, 1);
- if (streams.length !== 1 ||
- !streams[0].getTracks().find(function(t) {
- return t === track;
- })) {
- // this is not fully correct but all we can manage without
- // [[associated MediaStreams]] internal slot.
- throw new DOMException(
- 'The adapter.js addTrack polyfill only supports a single ' +
- ' stream which is associated with the specified track.',
- 'NotSupportedError');
- }
-
- var alreadyExists = pc.getSenders().find(function(s) {
- return s.track === track;
- });
- if (alreadyExists) {
- throw new DOMException('Track already exists.',
- 'InvalidAccessError');
- }
-
- pc._streams = pc._streams || {};
- pc._reverseStreams = pc._reverseStreams || {};
- var oldStream = pc._streams[stream.id];
- if (oldStream) {
- // this is using odd Chrome behaviour, use with caution:
- // https://bugs.chromium.org/p/webrtc/issues/detail?id=7815
- // Note: we rely on the high-level addTrack/dtmf shim to
- // create the sender with a dtmf sender.
- oldStream.addTrack(track);
-
- // Trigger ONN async.
- Promise.resolve().then(function() {
- pc.dispatchEvent(new Event('negotiationneeded'));
- });
- } else {
- var newStream = new window.MediaStream([track]);
- pc._streams[stream.id] = newStream;
- pc._reverseStreams[newStream.id] = stream;
- pc.addStream(newStream);
- }
- return pc.getSenders().find(function(s) {
- return s.track === track;
- });
- };
-
- // replace the internal stream id with the external one and
- // vice versa.
- function replaceInternalStreamId(pc, description) {
- var sdp = description.sdp;
- Object.keys(pc._reverseStreams || []).forEach(function(internalId) {
- var externalStream = pc._reverseStreams[internalId];
- var internalStream = pc._streams[externalStream.id];
- sdp = sdp.replace(new RegExp(internalStream.id, 'g'),
- externalStream.id);
- });
- return new RTCSessionDescription({
- type: description.type,
- sdp: sdp
- });
- }
- function replaceExternalStreamId(pc, description) {
- var sdp = description.sdp;
- Object.keys(pc._reverseStreams || []).forEach(function(internalId) {
- var externalStream = pc._reverseStreams[internalId];
- var internalStream = pc._streams[externalStream.id];
- sdp = sdp.replace(new RegExp(externalStream.id, 'g'),
- internalStream.id);
- });
- return new RTCSessionDescription({
- type: description.type,
- sdp: sdp
- });
- }
- ['createOffer', 'createAnswer'].forEach(function(method) {
- var nativeMethod = window.RTCPeerConnection.prototype[method];
- window.RTCPeerConnection.prototype[method] = function() {
- var pc = this;
- var args = arguments;
- var isLegacyCall = arguments.length &&
- typeof arguments[0] === 'function';
- if (isLegacyCall) {
- return nativeMethod.apply(pc, [
- function(description) {
- var desc = replaceInternalStreamId(pc, description);
- args[0].apply(null, [desc]);
- },
- function(err) {
- if (args[1]) {
- args[1].apply(null, err);
- }
- }, arguments[2]
- ]);
- }
- return nativeMethod.apply(pc, arguments)
- .then(function(description) {
- return replaceInternalStreamId(pc, description);
- });
- };
- });
-
- var origSetLocalDescription =
- window.RTCPeerConnection.prototype.setLocalDescription;
- window.RTCPeerConnection.prototype.setLocalDescription = function() {
- var pc = this;
- if (!arguments.length || !arguments[0].type) {
- return origSetLocalDescription.apply(pc, arguments);
- }
- arguments[0] = replaceExternalStreamId(pc, arguments[0]);
- return origSetLocalDescription.apply(pc, arguments);
- };
-
- // TODO: mangle getStats: https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamstats-streamidentifier
-
- var origLocalDescription = Object.getOwnPropertyDescriptor(
- window.RTCPeerConnection.prototype, 'localDescription');
- Object.defineProperty(window.RTCPeerConnection.prototype,
- 'localDescription', {
- get: function() {
- var pc = this;
- var description = origLocalDescription.get.apply(this);
- if (description.type === '') {
- return description;
- }
- return replaceInternalStreamId(pc, description);
- }
- });
-
- window.RTCPeerConnection.prototype.removeTrack = function(sender) {
- var pc = this;
- if (pc.signalingState === 'closed') {
- throw new DOMException(
- 'The RTCPeerConnection\'s signalingState is \'closed\'.',
- 'InvalidStateError');
- }
- // We can not yet check for sender instanceof RTCRtpSender
- // since we shim RTPSender. So we check if sender._pc is set.
- if (!sender._pc) {
- throw new DOMException('Argument 1 of RTCPeerConnection.removeTrack ' +
- 'does not implement interface RTCRtpSender.', 'TypeError');
- }
- var isLocal = sender._pc === pc;
- if (!isLocal) {
- throw new DOMException('Sender was not created by this connection.',
- 'InvalidAccessError');
- }
-
- // Search for the native stream the senders track belongs to.
- pc._streams = pc._streams || {};
- var stream;
- Object.keys(pc._streams).forEach(function(streamid) {
- var hasTrack = pc._streams[streamid].getTracks().find(function(track) {
- return sender.track === track;
- });
- if (hasTrack) {
- stream = pc._streams[streamid];
- }
- });
-
- if (stream) {
- if (stream.getTracks().length === 1) {
- // if this is the last track of the stream, remove the stream. This
- // takes care of any shimmed _senders.
- pc.removeStream(pc._reverseStreams[stream.id]);
- } else {
- // relying on the same odd chrome behaviour as above.
- stream.removeTrack(sender.track);
- }
- pc.dispatchEvent(new Event('negotiationneeded'));
- }
- };
- },
-
- shimPeerConnection: function(window) {
- var browserDetails = utils.detectBrowser(window);
-
- // The RTCPeerConnection object.
- if (!window.RTCPeerConnection && window.webkitRTCPeerConnection) {
- window.RTCPeerConnection = function(pcConfig, pcConstraints) {
- // Translate iceTransportPolicy to iceTransports,
- // see https://code.google.com/p/webrtc/issues/detail?id=4869
- // this was fixed in M56 along with unprefixing RTCPeerConnection.
- logging('PeerConnection');
- if (pcConfig && pcConfig.iceTransportPolicy) {
- pcConfig.iceTransports = pcConfig.iceTransportPolicy;
- }
-
- return new window.webkitRTCPeerConnection(pcConfig, pcConstraints);
- };
- window.RTCPeerConnection.prototype =
- window.webkitRTCPeerConnection.prototype;
- // wrap static methods. Currently just generateCertificate.
- if (window.webkitRTCPeerConnection.generateCertificate) {
- Object.defineProperty(window.RTCPeerConnection, 'generateCertificate', {
- get: function() {
- return window.webkitRTCPeerConnection.generateCertificate;
- }
- });
- }
- } else {
- // migrate from non-spec RTCIceServer.url to RTCIceServer.urls
- var OrigPeerConnection = window.RTCPeerConnection;
- window.RTCPeerConnection = function(pcConfig, pcConstraints) {
- if (pcConfig && pcConfig.iceServers) {
- var newIceServers = [];
- for (var i = 0; i < pcConfig.iceServers.length; i++) {
- var server = pcConfig.iceServers[i];
- if (!server.hasOwnProperty('urls') &&
- server.hasOwnProperty('url')) {
- utils.deprecated('RTCIceServer.url', 'RTCIceServer.urls');
- server = JSON.parse(JSON.stringify(server));
- server.urls = server.url;
- newIceServers.push(server);
- } else {
- newIceServers.push(pcConfig.iceServers[i]);
- }
- }
- pcConfig.iceServers = newIceServers;
- }
- return new OrigPeerConnection(pcConfig, pcConstraints);
- };
- window.RTCPeerConnection.prototype = OrigPeerConnection.prototype;
- // wrap static methods. Currently just generateCertificate.
- Object.defineProperty(window.RTCPeerConnection, 'generateCertificate', {
- get: function() {
- return OrigPeerConnection.generateCertificate;
- }
- });
- }
-
- var origGetStats = window.RTCPeerConnection.prototype.getStats;
- window.RTCPeerConnection.prototype.getStats = function(selector,
- successCallback, errorCallback) {
- var pc = 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.apply(this, arguments);
- }
-
- // When spec-style getStats is supported, return those when called with
- // either no arguments or the selector argument is null.
- if (origGetStats.length === 0 && (arguments.length === 0 ||
- typeof arguments[0] !== 'function')) {
- return origGetStats.apply(this, []);
- }
-
- var fixChromeStats_ = function(response) {
- var standardReport = {};
- var reports = response.result();
- reports.forEach(function(report) {
- var standardStats = {
- id: report.id,
- timestamp: report.timestamp,
- type: {
- localcandidate: 'local-candidate',
- remotecandidate: 'remote-candidate'
- }[report.type] || report.type
- };
- report.names().forEach(function(name) {
- standardStats[name] = report.stat(name);
- });
- standardReport[standardStats.id] = standardStats;
- });
-
- return standardReport;
- };
-
- // shim getStats with maplike support
- var makeMapStats = function(stats) {
- return new Map(Object.keys(stats).map(function(key) {
- return [key, stats[key]];
- }));
- };
-
- if (arguments.length >= 2) {
- var successCallbackWrapper_ = function(response) {
- args[1](makeMapStats(fixChromeStats_(response)));
- };
-
- return origGetStats.apply(this, [successCallbackWrapper_,
- arguments[0]]);
- }
-
- // promise-support
- return new Promise(function(resolve, reject) {
- origGetStats.apply(pc, [
- function(response) {
- resolve(makeMapStats(fixChromeStats_(response)));
- }, reject]);
- }).then(successCallback, errorCallback);
- };
-
- // add promise support -- natively available in Chrome 51
- if (browserDetails.version < 51) {
- ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate']
- .forEach(function(method) {
- var nativeMethod = window.RTCPeerConnection.prototype[method];
- window.RTCPeerConnection.prototype[method] = function() {
- var args = arguments;
- var pc = this;
- var promise = new Promise(function(resolve, reject) {
- nativeMethod.apply(pc, [args[0], resolve, reject]);
- });
- if (args.length < 2) {
- return promise;
- }
- return promise.then(function() {
- args[1].apply(null, []);
- },
- function(err) {
- if (args.length >= 3) {
- args[2].apply(null, [err]);
- }
- });
- };
- });
- }
-
- // promise support for createOffer and createAnswer. Available (without
- // bugs) since M52: crbug/619289
- if (browserDetails.version < 52) {
- ['createOffer', 'createAnswer'].forEach(function(method) {
- var nativeMethod = window.RTCPeerConnection.prototype[method];
- window.RTCPeerConnection.prototype[method] = function() {
- var pc = 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(pc, [resolve, reject, opts]);
- });
- }
- return nativeMethod.apply(this, arguments);
- };
- });
- }
-
- // shim implicit creation of RTCSessionDescription/RTCIceCandidate
- ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate']
- .forEach(function(method) {
- var nativeMethod = window.RTCPeerConnection.prototype[method];
- window.RTCPeerConnection.prototype[method] = function() {
- arguments[0] = new ((method === 'addIceCandidate') ?
- window.RTCIceCandidate :
- window.RTCSessionDescription)(arguments[0]);
- return nativeMethod.apply(this, arguments);
- };
- });
-
- // support for addIceCandidate(null or undefined)
- var nativeAddIceCandidate =
- window.RTCPeerConnection.prototype.addIceCandidate;
- window.RTCPeerConnection.prototype.addIceCandidate = function() {
- if (!arguments[0]) {
- if (arguments[1]) {
- arguments[1].apply(null);
- }
- return Promise.resolve();
- }
- return nativeAddIceCandidate.apply(this, arguments);
- };
- }
-};
-
-},{"../utils.js":13,"./getusermedia":6}],6:[function(require,module,exports){
-/*
- * Copyright (c) 2016 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.
- */
- /* eslint-env node */
-'use strict';
-var utils = require('../utils.js');
-var logging = utils.log;
-
-// Expose public methods.
-module.exports = function(window) {
- var browserDetails = utils.detectBrowser(window);
- var navigator = window && window.navigator;
-
- 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;
- };
-
- var shimConstraints_ = function(constraints, func) {
- if (browserDetails.version >= 61) {
- return func(constraints);
- }
- constraints = JSON.parse(JSON.stringify(constraints));
- if (constraints && typeof constraints.audio === 'object') {
- var remap = function(obj, a, b) {
- if (a in obj && !(b in obj)) {
- obj[b] = obj[a];
- delete obj[a];
- }
- };
- constraints = JSON.parse(JSON.stringify(constraints));
- remap(constraints.audio, 'autoGainControl', 'googAutoGainControl');
- remap(constraints.audio, 'noiseSuppression', 'googNoiseSuppression');
- constraints.audio = constraintsToChrome_(constraints.audio);
- }
- if (constraints && typeof constraints.video === 'object') {
- // Shim facingMode for mobile & surface pro.
- var face = constraints.video.facingMode;
- face = face && ((typeof face === 'object') ? face : {ideal: face});
- var getSupportedFacingModeLies = browserDetails.version < 66;
-
- if ((face && (face.exact === 'user' || face.exact === 'environment' ||
- face.ideal === 'user' || face.ideal === 'environment')) &&
- !(navigator.mediaDevices.getSupportedConstraints &&
- navigator.mediaDevices.getSupportedConstraints().facingMode &&
- !getSupportedFacingModeLies)) {
- delete constraints.video.facingMode;
- var matches;
- if (face.exact === 'environment' || face.ideal === 'environment') {
- matches = ['back', 'rear'];
- } else if (face.exact === 'user' || face.ideal === 'user') {
- matches = ['front'];
- }
- if (matches) {
- // Look for matches in label, or use last cam for back (typical).
- return navigator.mediaDevices.enumerateDevices()
- .then(function(devices) {
- devices = devices.filter(function(d) {
- return d.kind === 'videoinput';
- });
- var dev = devices.find(function(d) {
- return matches.some(function(match) {
- return d.label.toLowerCase().indexOf(match) !== -1;
- });
- });
- if (!dev && devices.length && matches.indexOf('back') !== -1) {
- dev = devices[devices.length - 1]; // more likely the back cam
- }
- if (dev) {
- constraints.video.deviceId = face.exact ? {exact: dev.deviceId} :
- {ideal: dev.deviceId};
- }
- constraints.video = constraintsToChrome_(constraints.video);
- logging('chrome: ' + JSON.stringify(constraints));
- return func(constraints);
- });
- }
- }
- constraints.video = constraintsToChrome_(constraints.video);
- }
- logging('chrome: ' + JSON.stringify(constraints));
- return func(constraints);
- };
-
- var shimError_ = function(e) {
- return {
- name: {
- PermissionDeniedError: 'NotAllowedError',
- InvalidStateError: 'NotReadableError',
- DevicesNotFoundError: 'NotFoundError',
- ConstraintNotSatisfiedError: 'OverconstrainedError',
- TrackStartError: 'NotReadableError',
- MediaDeviceFailedDueToShutdown: 'NotReadableError',
- MediaDeviceKillSwitchOn: 'NotReadableError'
- }[e.name] || e.name,
- message: e.message,
- constraint: e.constraintName,
- toString: function() {
- return this.name + (this.message && ': ') + this.message;
- }
- };
- };
-
- var getUserMedia_ = function(constraints, onSuccess, onError) {
- shimConstraints_(constraints, function(c) {
- navigator.webkitGetUserMedia(c, onSuccess, function(e) {
- if (onError) {
- onError(shimError_(e));
- }
- });
- });
- };
-
- navigator.getUserMedia = getUserMedia_;
-
- // Returns the result of getUserMedia as a Promise.
- var getUserMediaPromise_ = function(constraints) {
- return new Promise(function(resolve, reject) {
- navigator.getUserMedia(constraints, resolve, reject);
- });
- };
-
- if (!navigator.mediaDevices) {
- navigator.mediaDevices = {
- getUserMedia: getUserMediaPromise_,
- enumerateDevices: function() {
- return new Promise(function(resolve) {
- var kinds = {audio: 'audioinput', video: 'videoinput'};
- return window.MediaStreamTrack.getSources(function(devices) {
- resolve(devices.map(function(device) {
- return {label: device.label,
- kind: kinds[device.kind],
- deviceId: device.id,
- groupId: ''};
- }));
- });
- });
- },
- getSupportedConstraints: function() {
- return {
- deviceId: true, echoCancellation: true, facingMode: true,
- frameRate: true, height: true, width: true
- };
- }
- };
- }
-
- // 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 getUserMediaPromise_(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(cs) {
- return shimConstraints_(cs, function(c) {
- return origGetUserMedia(c).then(function(stream) {
- if (c.audio && !stream.getAudioTracks().length ||
- c.video && !stream.getVideoTracks().length) {
- stream.getTracks().forEach(function(track) {
- track.stop();
- });
- throw new DOMException('', 'NotFoundError');
- }
- return stream;
- }, function(e) {
- return Promise.reject(shimError_(e));
- });
- });
- };
- }
-
- // Dummy devicechange event methods.
- // TODO(KaptenJansson) remove once implemented in Chrome stable.
- if (typeof navigator.mediaDevices.addEventListener === 'undefined') {
- navigator.mediaDevices.addEventListener = function() {
- logging('Dummy mediaDevices.addEventListener called.');
- };
- }
- if (typeof navigator.mediaDevices.removeEventListener === 'undefined') {
- navigator.mediaDevices.removeEventListener = function() {
- logging('Dummy mediaDevices.removeEventListener called.');
- };
- }
-};
-
-},{"../utils.js":13}],7:[function(require,module,exports){
-/*
- * Copyright (c) 2017 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.
- */
- /* eslint-env node */
-'use strict';
-
-var SDPUtils = require('sdp');
-var utils = require('./utils');
-
-module.exports = {
- shimRTCIceCandidate: function(window) {
- // foundation is arbitrarily chosen as an indicator for full support for
- // https://w3c.github.io/webrtc-pc/#rtcicecandidate-interface
- if (window.RTCIceCandidate && 'foundation' in
- window.RTCIceCandidate.prototype) {
- return;
- }
-
- var NativeRTCIceCandidate = window.RTCIceCandidate;
- window.RTCIceCandidate = function(args) {
- // Remove the a= which shouldn't be part of the candidate string.
- if (typeof args === 'object' && args.candidate &&
- args.candidate.indexOf('a=') === 0) {
- args = JSON.parse(JSON.stringify(args));
- args.candidate = args.candidate.substr(2);
- }
-
- // Augment the native candidate with the parsed fields.
- var nativeCandidate = new NativeRTCIceCandidate(args);
- var parsedCandidate = SDPUtils.parseCandidate(args.candidate);
- var augmentedCandidate = Object.assign(nativeCandidate,
- parsedCandidate);
-
- // Add a serializer that does not serialize the extra attributes.
- augmentedCandidate.toJSON = function() {
- return {
- candidate: augmentedCandidate.candidate,
- sdpMid: augmentedCandidate.sdpMid,
- sdpMLineIndex: augmentedCandidate.sdpMLineIndex,
- usernameFragment: augmentedCandidate.usernameFragment,
- };
- };
- return augmentedCandidate;
- };
-
- // Hook up the augmented candidate in onicecandidate and
- // addEventListener('icecandidate', ...)
- utils.wrapPeerConnectionEvent(window, 'icecandidate', function(e) {
- if (e.candidate) {
- Object.defineProperty(e, 'candidate', {
- value: new window.RTCIceCandidate(e.candidate),
- writable: 'false'
- });
- }
- return e;
- });
- },
-
- // shimCreateObjectURL must be called before shimSourceObject to avoid loop.
-
- shimCreateObjectURL: function(window) {
- var URL = window && window.URL;
-
- if (!(typeof window === 'object' && window.HTMLMediaElement &&
- 'srcObject' in window.HTMLMediaElement.prototype &&
- URL.createObjectURL && URL.revokeObjectURL)) {
- // Only shim CreateObjectURL using srcObject if srcObject exists.
- return undefined;
- }
-
- var nativeCreateObjectURL = URL.createObjectURL.bind(URL);
- var nativeRevokeObjectURL = URL.revokeObjectURL.bind(URL);
- var streams = new Map(), newId = 0;
-
- URL.createObjectURL = function(stream) {
- if ('getTracks' in stream) {
- var url = 'polyblob:' + (++newId);
- streams.set(url, stream);
- utils.deprecated('URL.createObjectURL(stream)',
- 'elem.srcObject = stream');
- return url;
- }
- return nativeCreateObjectURL(stream);
- };
- URL.revokeObjectURL = function(url) {
- nativeRevokeObjectURL(url);
- streams.delete(url);
- };
-
- var dsc = Object.getOwnPropertyDescriptor(window.HTMLMediaElement.prototype,
- 'src');
- Object.defineProperty(window.HTMLMediaElement.prototype, 'src', {
- get: function() {
- return dsc.get.apply(this);
- },
- set: function(url) {
- this.srcObject = streams.get(url) || null;
- return dsc.set.apply(this, [url]);
- }
- });
-
- var nativeSetAttribute = window.HTMLMediaElement.prototype.setAttribute;
- window.HTMLMediaElement.prototype.setAttribute = function() {
- if (arguments.length === 2 &&
- ('' + arguments[0]).toLowerCase() === 'src') {
- this.srcObject = streams.get(arguments[1]) || null;
- }
- return nativeSetAttribute.apply(this, arguments);
- };
- },
-
- shimMaxMessageSize: function(window) {
- if (window.RTCSctpTransport || !window.RTCPeerConnection) {
- return;
- }
- var browserDetails = utils.detectBrowser(window);
-
- if (!('sctp' in window.RTCPeerConnection.prototype)) {
- Object.defineProperty(window.RTCPeerConnection.prototype, 'sctp', {
- get: function() {
- return typeof this._sctp === 'undefined' ? null : this._sctp;
- }
- });
- }
-
- var sctpInDescription = function(description) {
- var sections = SDPUtils.splitSections(description.sdp);
- sections.shift();
- return sections.some(function(mediaSection) {
- var mLine = SDPUtils.parseMLine(mediaSection);
- return mLine && mLine.kind === 'application'
- && mLine.protocol.indexOf('SCTP') !== -1;
- });
- };
-
- var getRemoteFirefoxVersion = function(description) {
- // TODO: Is there a better solution for detecting Firefox?
- var match = description.sdp.match(/mozilla...THIS_IS_SDPARTA-(\d+)/);
- if (match === null || match.length < 2) {
- return -1;
- }
- var version = parseInt(match[1], 10);
- // Test for NaN (yes, this is ugly)
- return version !== version ? -1 : version;
- };
-
- var getCanSendMaxMessageSize = function(remoteIsFirefox) {
- // Every implementation we know can send at least 64 KiB.
- // Note: Although Chrome is technically able to send up to 256 KiB, the
- // data does not reach the other peer reliably.
- // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=8419
- var canSendMaxMessageSize = 65536;
- if (browserDetails.browser === 'firefox') {
- if (browserDetails.version < 57) {
- if (remoteIsFirefox === -1) {
- // FF < 57 will send in 16 KiB chunks using the deprecated PPID
- // fragmentation.
- canSendMaxMessageSize = 16384;
- } else {
- // However, other FF (and RAWRTC) can reassemble PPID-fragmented
- // messages. Thus, supporting ~2 GiB when sending.
- canSendMaxMessageSize = 2147483637;
- }
- } else {
- // Currently, all FF >= 57 will reset the remote maximum message size
- // to the default value when a data channel is created at a later
- // stage. :(
- // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1426831
- canSendMaxMessageSize =
- browserDetails.version === 57 ? 65535 : 65536;
- }
- }
- return canSendMaxMessageSize;
- };
-
- var getMaxMessageSize = function(description, remoteIsFirefox) {
- // Note: 65536 bytes is the default value from the SDP spec. Also,
- // every implementation we know supports receiving 65536 bytes.
- var maxMessageSize = 65536;
-
- // FF 57 has a slightly incorrect default remote max message size, so
- // we need to adjust it here to avoid a failure when sending.
- // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1425697
- if (browserDetails.browser === 'firefox'
- && browserDetails.version === 57) {
- maxMessageSize = 65535;
- }
-
- var match = SDPUtils.matchPrefix(description.sdp, 'a=max-message-size:');
- if (match.length > 0) {
- maxMessageSize = parseInt(match[0].substr(19), 10);
- } else if (browserDetails.browser === 'firefox' &&
- remoteIsFirefox !== -1) {
- // If the maximum message size is not present in the remote SDP and
- // both local and remote are Firefox, the remote peer can receive
- // ~2 GiB.
- maxMessageSize = 2147483637;
- }
- return maxMessageSize;
- };
-
- var origSetRemoteDescription =
- window.RTCPeerConnection.prototype.setRemoteDescription;
- window.RTCPeerConnection.prototype.setRemoteDescription = function() {
- var pc = this;
- pc._sctp = null;
-
- if (sctpInDescription(arguments[0])) {
- // Check if the remote is FF.
- var isFirefox = getRemoteFirefoxVersion(arguments[0]);
-
- // Get the maximum message size the local peer is capable of sending
- var canSendMMS = getCanSendMaxMessageSize(isFirefox);
-
- // Get the maximum message size of the remote peer.
- var remoteMMS = getMaxMessageSize(arguments[0], isFirefox);
-
- // Determine final maximum message size
- var maxMessageSize;
- if (canSendMMS === 0 && remoteMMS === 0) {
- maxMessageSize = Number.POSITIVE_INFINITY;
- } else if (canSendMMS === 0 || remoteMMS === 0) {
- maxMessageSize = Math.max(canSendMMS, remoteMMS);
- } else {
- maxMessageSize = Math.min(canSendMMS, remoteMMS);
- }
-
- // Create a dummy RTCSctpTransport object and the 'maxMessageSize'
- // attribute.
- var sctp = {};
- Object.defineProperty(sctp, 'maxMessageSize', {
- get: function() {
- return maxMessageSize;
- }
- });
- pc._sctp = sctp;
- }
-
- return origSetRemoteDescription.apply(pc, arguments);
- };
- },
-
- shimSendThrowTypeError: function(window) {
- // Note: Although Firefox >= 57 has a native implementation, the maximum
- // message size can be reset for all data channels at a later stage.
- // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1426831
-
- var origCreateDataChannel =
- window.RTCPeerConnection.prototype.createDataChannel;
- window.RTCPeerConnection.prototype.createDataChannel = function() {
- var pc = this;
- var dataChannel = origCreateDataChannel.apply(pc, arguments);
- var origDataChannelSend = dataChannel.send;
-
- // Patch 'send' method
- dataChannel.send = function() {
- var dc = this;
- var data = arguments[0];
- var length = data.length || data.size || data.byteLength;
- if (length > pc.sctp.maxMessageSize) {
- throw new DOMException('Message too large (can send a maximum of ' +
- pc.sctp.maxMessageSize + ' bytes)', 'TypeError');
- }
- return origDataChannelSend.apply(dc, arguments);
- };
-
- return dataChannel;
- };
- }
-};
-
-},{"./utils":13,"sdp":2}],8:[function(require,module,exports){
-/*
- * Copyright (c) 2016 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.
- */
- /* eslint-env node */
-'use strict';
-
-var utils = require('../utils');
-var shimRTCPeerConnection = require('rtcpeerconnection-shim');
-
-module.exports = {
- shimGetUserMedia: require('./getusermedia'),
- shimPeerConnection: function(window) {
- var browserDetails = utils.detectBrowser(window);
-
- if (window.RTCIceGatherer) {
- // ORTC defines an RTCIceCandidate object but no constructor.
- // Not implemented in Edge.
- if (!window.RTCIceCandidate) {
- window.RTCIceCandidate = function(args) {
- return args;
- };
- }
- // ORTC does not have a session description object but
- // other browsers (i.e. Chrome) that will support both PC and ORTC
- // in the future might have this defined already.
- if (!window.RTCSessionDescription) {
- window.RTCSessionDescription = function(args) {
- return args;
- };
- }
- // this adds an additional event listener to MediaStrackTrack that signals
- // when a tracks enabled property was changed. Workaround for a bug in
- // addStream, see below. No longer required in 15025+
- if (browserDetails.version < 15025) {
- var origMSTEnabled = Object.getOwnPropertyDescriptor(
- window.MediaStreamTrack.prototype, 'enabled');
- Object.defineProperty(window.MediaStreamTrack.prototype, 'enabled', {
- set: function(value) {
- origMSTEnabled.set.call(this, value);
- var ev = new Event('enabled');
- ev.enabled = value;
- this.dispatchEvent(ev);
- }
- });
- }
- }
-
- // ORTC defines the DTMF sender a bit different.
- // https://github.com/w3c/ortc/issues/714
- if (window.RTCRtpSender && !('dtmf' in window.RTCRtpSender.prototype)) {
- Object.defineProperty(window.RTCRtpSender.prototype, 'dtmf', {
- get: function() {
- if (this._dtmf === undefined) {
- if (this.track.kind === 'audio') {
- this._dtmf = new window.RTCDtmfSender(this);
- } else if (this.track.kind === 'video') {
- this._dtmf = null;
- }
- }
- return this._dtmf;
- }
- });
- }
-
- window.RTCPeerConnection =
- shimRTCPeerConnection(window, browserDetails.version);
- },
- shimReplaceTrack: function(window) {
- // ORTC has replaceTrack -- https://github.com/w3c/ortc/issues/614
- if (window.RTCRtpSender &&
- !('replaceTrack' in window.RTCRtpSender.prototype)) {
- window.RTCRtpSender.prototype.replaceTrack =
- window.RTCRtpSender.prototype.setTrack;
- }
- }
-};
-
-},{"../utils":13,"./getusermedia":9,"rtcpeerconnection-shim":1}],9:[function(require,module,exports){
-/*
- * Copyright (c) 2016 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.
- */
- /* eslint-env node */
-'use strict';
-
-// Expose public methods.
-module.exports = function(window) {
- var navigator = window && window.navigator;
-
- var shimError_ = function(e) {
- return {
- name: {PermissionDeniedError: 'NotAllowedError'}[e.name] || e.name,
- message: e.message,
- constraint: e.constraint,
- toString: function() {
- return this.name;
- }
- };
- };
-
- // getUserMedia error shim.
- var origGetUserMedia = navigator.mediaDevices.getUserMedia.
- bind(navigator.mediaDevices);
- navigator.mediaDevices.getUserMedia = function(c) {
- return origGetUserMedia(c).catch(function(e) {
- return Promise.reject(shimError_(e));
- });
- };
-};
-
-},{}],10:[function(require,module,exports){
-/*
- * Copyright (c) 2016 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.
- */
- /* eslint-env node */
-'use strict';
-
-var utils = require('../utils');
-
-module.exports = {
- shimGetUserMedia: require('./getusermedia'),
- shimOnTrack: function(window) {
- if (typeof window === 'object' && window.RTCPeerConnection && !('ontrack' in
- window.RTCPeerConnection.prototype)) {
- Object.defineProperty(window.RTCPeerConnection.prototype, 'ontrack', {
- get: function() {
- return this._ontrack;
- },
- set: function(f) {
- if (this._ontrack) {
- this.removeEventListener('track', this._ontrack);
- this.removeEventListener('addstream', this._ontrackpoly);
- }
- this.addEventListener('track', this._ontrack = f);
- this.addEventListener('addstream', this._ontrackpoly = function(e) {
- e.stream.getTracks().forEach(function(track) {
- var event = new Event('track');
- event.track = track;
- event.receiver = {track: track};
- event.transceiver = {receiver: event.receiver};
- event.streams = [e.stream];
- this.dispatchEvent(event);
- }.bind(this));
- }.bind(this));
- }
- });
- }
- if (typeof window === 'object' && window.RTCTrackEvent &&
- ('receiver' in window.RTCTrackEvent.prototype) &&
- !('transceiver' in window.RTCTrackEvent.prototype)) {
- Object.defineProperty(window.RTCTrackEvent.prototype, 'transceiver', {
- get: function() {
- return {receiver: this.receiver};
- }
- });
- }
- },
-
- shimSourceObject: function(window) {
- // Firefox has supported mozSrcObject since FF22, unprefixed in 42.
- 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() {
- return this.mozSrcObject;
- },
- set: function(stream) {
- this.mozSrcObject = stream;
- }
- });
- }
- }
- },
-
- shimPeerConnection: function(window) {
- var browserDetails = utils.detectBrowser(window);
-
- if (typeof window !== 'object' || !(window.RTCPeerConnection ||
- window.mozRTCPeerConnection)) {
- return; // probably media.peerconnection.enabled=false in about:config
- }
- // The RTCPeerConnection object.
- if (!window.RTCPeerConnection) {
- window.RTCPeerConnection = function(pcConfig, pcConstraints) {
- if (browserDetails.version < 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 window.mozRTCPeerConnection(pcConfig, pcConstraints);
- };
- window.RTCPeerConnection.prototype =
- window.mozRTCPeerConnection.prototype;
-
- // wrap static methods. Currently just generateCertificate.
- if (window.mozRTCPeerConnection.generateCertificate) {
- Object.defineProperty(window.RTCPeerConnection, 'generateCertificate', {
- get: function() {
- return window.mozRTCPeerConnection.generateCertificate;
- }
- });
- }
-
- window.RTCSessionDescription = window.mozRTCSessionDescription;
- window.RTCIceCandidate = window.mozRTCIceCandidate;
- }
-
- // shim away need for obsolete RTCIceCandidate/RTCSessionDescription.
- ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate']
- .forEach(function(method) {
- var nativeMethod = window.RTCPeerConnection.prototype[method];
- window.RTCPeerConnection.prototype[method] = function() {
- arguments[0] = new ((method === 'addIceCandidate') ?
- window.RTCIceCandidate :
- window.RTCSessionDescription)(arguments[0]);
- return nativeMethod.apply(this, arguments);
- };
- });
-
- // support for addIceCandidate(null or undefined)
- var nativeAddIceCandidate =
- window.RTCPeerConnection.prototype.addIceCandidate;
- window.RTCPeerConnection.prototype.addIceCandidate = function() {
- if (!arguments[0]) {
- if (arguments[1]) {
- arguments[1].apply(null);
- }
- return Promise.resolve();
- }
- return nativeAddIceCandidate.apply(this, arguments);
- };
-
- // shim getStats with maplike support
- var makeMapStats = function(stats) {
- var map = new Map();
- Object.keys(stats).forEach(function(key) {
- map.set(key, stats[key]);
- map[key] = stats[key];
- });
- return map;
- };
-
- var modernStatsTypes = {
- inboundrtp: 'inbound-rtp',
- outboundrtp: 'outbound-rtp',
- candidatepair: 'candidate-pair',
- localcandidate: 'local-candidate',
- remotecandidate: 'remote-candidate'
- };
-
- var nativeGetStats = window.RTCPeerConnection.prototype.getStats;
- window.RTCPeerConnection.prototype.getStats = function(
- selector,
- onSucc,
- onErr
- ) {
- return nativeGetStats.apply(this, [selector || null])
- .then(function(stats) {
- if (browserDetails.version < 48) {
- stats = makeMapStats(stats);
- }
- if (browserDetails.version < 53 && !onSucc) {
- // Shim only promise getStats with spec-hyphens in type names
- // Leave callback version alone; misc old uses of forEach before Map
- try {
- stats.forEach(function(stat) {
- stat.type = modernStatsTypes[stat.type] || stat.type;
- });
- } catch (e) {
- if (e.name !== 'TypeError') {
- throw e;
- }
- // Avoid TypeError: "type" is read-only, in old versions. 34-43ish
- stats.forEach(function(stat, i) {
- stats.set(i, Object.assign({}, stat, {
- type: modernStatsTypes[stat.type] || stat.type
- }));
- });
- }
- }
- return stats;
- })
- .then(onSucc, onErr);
- };
- },
-
- shimRemoveStream: function(window) {
- if (!window.RTCPeerConnection ||
- 'removeStream' in window.RTCPeerConnection.prototype) {
- return;
- }
- window.RTCPeerConnection.prototype.removeStream = function(stream) {
- var pc = this;
- utils.deprecated('removeStream', 'removeTrack');
- this.getSenders().forEach(function(sender) {
- if (sender.track && stream.getTracks().indexOf(sender.track) !== -1) {
- pc.removeTrack(sender);
- }
- });
- };
- }
-};
-
-},{"../utils":13,"./getusermedia":11}],11:[function(require,module,exports){
-/*
- * Copyright (c) 2016 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.
- */
- /* eslint-env node */
-'use strict';
-
-var utils = require('../utils');
-var logging = utils.log;
-
-// Expose public methods.
-module.exports = function(window) {
- var browserDetails = utils.detectBrowser(window);
- var navigator = window && window.navigator;
- var MediaStreamTrack = window && window.MediaStreamTrack;
-
- var shimError_ = function(e) {
- return {
- name: {
- InternalError: 'NotReadableError',
- NotSupportedError: 'TypeError',
- PermissionDeniedError: 'NotAllowedError',
- SecurityError: 'NotAllowedError'
- }[e.name] || e.name,
- message: {
- 'The operation is insecure.': 'The request is not allowed by the ' +
- 'user agent or the platform in the current context.'
- }[e.message] || e.message,
- constraint: e.constraint,
- toString: function() {
- return this.name + (this.message && ': ') + this.message;
- }
- };
- };
-
- // getUserMedia constraints shim.
- var 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;
- };
- constraints = JSON.parse(JSON.stringify(constraints));
- if (browserDetails.version < 38) {
- logging('spec: ' + JSON.stringify(constraints));
- if (constraints.audio) {
- constraints.audio = constraintsToFF37_(constraints.audio);
- }
- if (constraints.video) {
- constraints.video = constraintsToFF37_(constraints.video);
- }
- logging('ff37: ' + JSON.stringify(constraints));
- }
- return navigator.mozGetUserMedia(constraints, onSuccess, function(e) {
- onError(shimError_(e));
- });
- };
-
- // Returns the result of getUserMedia as a Promise.
- var getUserMediaPromise_ = function(constraints) {
- return new Promise(function(resolve, reject) {
- getUserMedia_(constraints, resolve, reject);
- });
- };
-
- // Shim for mediaDevices on older versions.
- if (!navigator.mediaDevices) {
- navigator.mediaDevices = {getUserMedia: getUserMediaPromise_,
- 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 (browserDetails.version < 41) {
- // Work around http://bugzil.la/1169665
- var orgEnumerateDevices =
- navigator.mediaDevices.enumerateDevices.bind(navigator.mediaDevices);
- navigator.mediaDevices.enumerateDevices = function() {
- return orgEnumerateDevices().then(undefined, function(e) {
- if (e.name === 'NotFoundError') {
- return [];
- }
- throw e;
- });
- };
- }
- if (browserDetails.version < 49) {
- var origGetUserMedia = navigator.mediaDevices.getUserMedia.
- bind(navigator.mediaDevices);
- navigator.mediaDevices.getUserMedia = function(c) {
- return origGetUserMedia(c).then(function(stream) {
- // Work around https://bugzil.la/802326
- if (c.audio && !stream.getAudioTracks().length ||
- c.video && !stream.getVideoTracks().length) {
- stream.getTracks().forEach(function(track) {
- track.stop();
- });
- throw new DOMException('The object can not be found here.',
- 'NotFoundError');
- }
- return stream;
- }, function(e) {
- return Promise.reject(shimError_(e));
- });
- };
- }
- if (!(browserDetails.version > 55 &&
- 'autoGainControl' in navigator.mediaDevices.getSupportedConstraints())) {
- var remap = function(obj, a, b) {
- if (a in obj && !(b in obj)) {
- obj[b] = obj[a];
- delete obj[a];
- }
- };
-
- var nativeGetUserMedia = navigator.mediaDevices.getUserMedia.
- bind(navigator.mediaDevices);
- navigator.mediaDevices.getUserMedia = function(c) {
- if (typeof c === 'object' && typeof c.audio === 'object') {
- c = JSON.parse(JSON.stringify(c));
- remap(c.audio, 'autoGainControl', 'mozAutoGainControl');
- remap(c.audio, 'noiseSuppression', 'mozNoiseSuppression');
- }
- return nativeGetUserMedia(c);
- };
-
- if (MediaStreamTrack && MediaStreamTrack.prototype.getSettings) {
- var nativeGetSettings = MediaStreamTrack.prototype.getSettings;
- MediaStreamTrack.prototype.getSettings = function() {
- var obj = nativeGetSettings.apply(this, arguments);
- remap(obj, 'mozAutoGainControl', 'autoGainControl');
- remap(obj, 'mozNoiseSuppression', 'noiseSuppression');
- return obj;
- };
- }
-
- if (MediaStreamTrack && MediaStreamTrack.prototype.applyConstraints) {
- var nativeApplyConstraints = MediaStreamTrack.prototype.applyConstraints;
- MediaStreamTrack.prototype.applyConstraints = function(c) {
- if (this.kind === 'audio' && typeof c === 'object') {
- c = JSON.parse(JSON.stringify(c));
- remap(c, 'autoGainControl', 'mozAutoGainControl');
- remap(c, 'noiseSuppression', 'mozNoiseSuppression');
- }
- return nativeApplyConstraints.apply(this, [c]);
- };
- }
- }
- navigator.getUserMedia = function(constraints, onSuccess, onError) {
- if (browserDetails.version < 44) {
- return getUserMedia_(constraints, onSuccess, onError);
- }
- // Replace Firefox 44+'s deprecation warning with unprefixed version.
- utils.deprecated('navigator.getUserMedia',
- 'navigator.mediaDevices.getUserMedia');
- navigator.mediaDevices.getUserMedia(constraints).then(onSuccess, onError);
- };
-};
-
-},{"../utils":13}],12:[function(require,module,exports){
-/*
- * Copyright (c) 2016 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.
- */
-'use strict';
-var utils = require('../utils');
-
-module.exports = {
- shimLocalStreamsAPI: function(window) {
- if (typeof window !== 'object' || !window.RTCPeerConnection) {
- return;
- }
- if (!('getLocalStreams' in window.RTCPeerConnection.prototype)) {
- window.RTCPeerConnection.prototype.getLocalStreams = function() {
- if (!this._localStreams) {
- this._localStreams = [];
- }
- return this._localStreams;
- };
- }
- if (!('getStreamById' in window.RTCPeerConnection.prototype)) {
- window.RTCPeerConnection.prototype.getStreamById = function(id) {
- var result = null;
- if (this._localStreams) {
- this._localStreams.forEach(function(stream) {
- if (stream.id === id) {
- result = stream;
- }
- });
- }
- if (this._remoteStreams) {
- this._remoteStreams.forEach(function(stream) {
- if (stream.id === id) {
- result = stream;
- }
- });
- }
- return result;
- };
- }
- if (!('addStream' in window.RTCPeerConnection.prototype)) {
- var _addTrack = window.RTCPeerConnection.prototype.addTrack;
- window.RTCPeerConnection.prototype.addStream = function(stream) {
- if (!this._localStreams) {
- this._localStreams = [];
- }
- if (this._localStreams.indexOf(stream) === -1) {
- this._localStreams.push(stream);
- }
- var pc = this;
- stream.getTracks().forEach(function(track) {
- _addTrack.call(pc, track, stream);
- });
- };
-
- window.RTCPeerConnection.prototype.addTrack = function(track, stream) {
- if (stream) {
- if (!this._localStreams) {
- this._localStreams = [stream];
- } else if (this._localStreams.indexOf(stream) === -1) {
- this._localStreams.push(stream);
- }
- }
- return _addTrack.call(this, track, stream);
- };
- }
- if (!('removeStream' in window.RTCPeerConnection.prototype)) {
- window.RTCPeerConnection.prototype.removeStream = function(stream) {
- if (!this._localStreams) {
- this._localStreams = [];
- }
- var index = this._localStreams.indexOf(stream);
- if (index === -1) {
- return;
- }
- this._localStreams.splice(index, 1);
- var pc = this;
- var tracks = stream.getTracks();
- this.getSenders().forEach(function(sender) {
- if (tracks.indexOf(sender.track) !== -1) {
- pc.removeTrack(sender);
- }
- });
- };
- }
- },
- shimRemoteStreamsAPI: function(window) {
- if (typeof window !== 'object' || !window.RTCPeerConnection) {
- return;
- }
- if (!('getRemoteStreams' in window.RTCPeerConnection.prototype)) {
- window.RTCPeerConnection.prototype.getRemoteStreams = function() {
- return this._remoteStreams ? this._remoteStreams : [];
- };
- }
- if (!('onaddstream' in window.RTCPeerConnection.prototype)) {
- Object.defineProperty(window.RTCPeerConnection.prototype, 'onaddstream', {
- get: function() {
- return this._onaddstream;
- },
- set: function(f) {
- var pc = this;
- if (this._onaddstream) {
- this.removeEventListener('addstream', this._onaddstream);
- this.removeEventListener('track', this._onaddstreampoly);
- }
- this.addEventListener('addstream', this._onaddstream = f);
- this.addEventListener('track', this._onaddstreampoly = function(e) {
- e.streams.forEach(function(stream) {
- if (!pc._remoteStreams) {
- pc._remoteStreams = [];
- }
- if (pc._remoteStreams.indexOf(stream) >= 0) {
- return;
- }
- pc._remoteStreams.push(stream);
- var event = new Event('addstream');
- event.stream = stream;
- pc.dispatchEvent(event);
- });
- });
- }
- });
- }
- },
- shimCallbacksAPI: function(window) {
- if (typeof window !== 'object' || !window.RTCPeerConnection) {
- return;
- }
- var prototype = window.RTCPeerConnection.prototype;
- var createOffer = prototype.createOffer;
- var createAnswer = prototype.createAnswer;
- var setLocalDescription = prototype.setLocalDescription;
- var setRemoteDescription = prototype.setRemoteDescription;
- var addIceCandidate = prototype.addIceCandidate;
-
- prototype.createOffer = function(successCallback, failureCallback) {
- var options = (arguments.length >= 2) ? arguments[2] : arguments[0];
- var promise = createOffer.apply(this, [options]);
- if (!failureCallback) {
- return promise;
- }
- promise.then(successCallback, failureCallback);
- return Promise.resolve();
- };
-
- prototype.createAnswer = function(successCallback, failureCallback) {
- var options = (arguments.length >= 2) ? arguments[2] : arguments[0];
- var promise = createAnswer.apply(this, [options]);
- if (!failureCallback) {
- return promise;
- }
- promise.then(successCallback, failureCallback);
- return Promise.resolve();
- };
-
- var withCallback = function(description, successCallback, failureCallback) {
- var promise = setLocalDescription.apply(this, [description]);
- if (!failureCallback) {
- return promise;
- }
- promise.then(successCallback, failureCallback);
- return Promise.resolve();
- };
- prototype.setLocalDescription = withCallback;
-
- withCallback = function(description, successCallback, failureCallback) {
- var promise = setRemoteDescription.apply(this, [description]);
- if (!failureCallback) {
- return promise;
- }
- promise.then(successCallback, failureCallback);
- return Promise.resolve();
- };
- prototype.setRemoteDescription = withCallback;
-
- withCallback = function(candidate, successCallback, failureCallback) {
- var promise = addIceCandidate.apply(this, [candidate]);
- if (!failureCallback) {
- return promise;
- }
- promise.then(successCallback, failureCallback);
- return Promise.resolve();
- };
- prototype.addIceCandidate = withCallback;
- },
- shimGetUserMedia: function(window) {
- var navigator = window && window.navigator;
-
- if (!navigator.getUserMedia) {
- if (navigator.webkitGetUserMedia) {
- navigator.getUserMedia = navigator.webkitGetUserMedia.bind(navigator);
- } else if (navigator.mediaDevices &&
- navigator.mediaDevices.getUserMedia) {
- navigator.getUserMedia = function(constraints, cb, errcb) {
- navigator.mediaDevices.getUserMedia(constraints)
- .then(cb, errcb);
- }.bind(navigator);
- }
- }
- },
- shimRTCIceServerUrls: function(window) {
- // migrate from non-spec RTCIceServer.url to RTCIceServer.urls
- var OrigPeerConnection = window.RTCPeerConnection;
- window.RTCPeerConnection = function(pcConfig, pcConstraints) {
- if (pcConfig && pcConfig.iceServers) {
- var newIceServers = [];
- for (var i = 0; i < pcConfig.iceServers.length; i++) {
- var server = pcConfig.iceServers[i];
- if (!server.hasOwnProperty('urls') &&
- server.hasOwnProperty('url')) {
- utils.deprecated('RTCIceServer.url', 'RTCIceServer.urls');
- server = JSON.parse(JSON.stringify(server));
- server.urls = server.url;
- delete server.url;
- newIceServers.push(server);
- } else {
- newIceServers.push(pcConfig.iceServers[i]);
- }
- }
- pcConfig.iceServers = newIceServers;
- }
- return new OrigPeerConnection(pcConfig, pcConstraints);
- };
- window.RTCPeerConnection.prototype = OrigPeerConnection.prototype;
- // wrap static methods. Currently just generateCertificate.
- if ('generateCertificate' in window.RTCPeerConnection) {
- Object.defineProperty(window.RTCPeerConnection, 'generateCertificate', {
- get: function() {
- return OrigPeerConnection.generateCertificate;
- }
- });
- }
- },
- shimTrackEventTransceiver: function(window) {
- // Add event.transceiver member over deprecated event.receiver
- if (typeof window === 'object' && window.RTCPeerConnection &&
- ('receiver' in window.RTCTrackEvent.prototype) &&
- // can't check 'transceiver' in window.RTCTrackEvent.prototype, as it is
- // defined for some reason even when window.RTCTransceiver is not.
- !window.RTCTransceiver) {
- Object.defineProperty(window.RTCTrackEvent.prototype, 'transceiver', {
- get: function() {
- return {receiver: this.receiver};
- }
- });
- }
- },
-
- shimCreateOfferLegacy: function(window) {
- var origCreateOffer = window.RTCPeerConnection.prototype.createOffer;
- window.RTCPeerConnection.prototype.createOffer = function(offerOptions) {
- var pc = this;
- if (offerOptions) {
- var audioTransceiver = pc.getTransceivers().find(function(transceiver) {
- return transceiver.sender.track &&
- transceiver.sender.track.kind === 'audio';
- });
- if (offerOptions.offerToReceiveAudio === false && audioTransceiver) {
- if (audioTransceiver.direction === 'sendrecv') {
- if (audioTransceiver.setDirection) {
- audioTransceiver.setDirection('sendonly');
- } else {
- audioTransceiver.direction = 'sendonly';
- }
- } else if (audioTransceiver.direction === 'recvonly') {
- if (audioTransceiver.setDirection) {
- audioTransceiver.setDirection('inactive');
- } else {
- audioTransceiver.direction = 'inactive';
- }
- }
- } else if (offerOptions.offerToReceiveAudio === true &&
- !audioTransceiver) {
- pc.addTransceiver('audio');
- }
-
- var videoTransceiver = pc.getTransceivers().find(function(transceiver) {
- return transceiver.sender.track &&
- transceiver.sender.track.kind === 'video';
- });
- if (offerOptions.offerToReceiveVideo === false && videoTransceiver) {
- if (videoTransceiver.direction === 'sendrecv') {
- videoTransceiver.setDirection('sendonly');
- } else if (videoTransceiver.direction === 'recvonly') {
- videoTransceiver.setDirection('inactive');
- }
- } else if (offerOptions.offerToReceiveVideo === true &&
- !videoTransceiver) {
- pc.addTransceiver('video');
- }
- }
- return origCreateOffer.apply(pc, arguments);
- };
- }
-};
-
-},{"../utils":13}],13:[function(require,module,exports){
-/*
- * Copyright (c) 2016 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.
- */
- /* eslint-env node */
-'use strict';
-
-var logDisabled_ = true;
-var deprecationWarnings_ = true;
-
-/**
- * Extract browser version out of the provided user agent string.
- *
- * @param {!string} uastring userAgent string.
- * @param {!string} expr Regular expression used as match criteria.
- * @param {!number} pos position in the version string to be returned.
- * @return {!number} browser version.
- */
-function extractVersion(uastring, expr, pos) {
- var match = uastring.match(expr);
- return match && match.length >= pos && parseInt(match[pos], 10);
-}
-
-// Wraps the peerconnection event eventNameToWrap in a function
-// which returns the modified event object.
-function wrapPeerConnectionEvent(window, eventNameToWrap, wrapper) {
- if (!window.RTCPeerConnection) {
- return;
- }
- var proto = window.RTCPeerConnection.prototype;
- var nativeAddEventListener = proto.addEventListener;
- proto.addEventListener = function(nativeEventName, cb) {
- if (nativeEventName !== eventNameToWrap) {
- return nativeAddEventListener.apply(this, arguments);
- }
- var wrappedCallback = function(e) {
- cb(wrapper(e));
- };
- this._eventMap = this._eventMap || {};
- this._eventMap[cb] = wrappedCallback;
- return nativeAddEventListener.apply(this, [nativeEventName,
- wrappedCallback]);
- };
-
- var nativeRemoveEventListener = proto.removeEventListener;
- proto.removeEventListener = function(nativeEventName, cb) {
- if (nativeEventName !== eventNameToWrap || !this._eventMap
- || !this._eventMap[cb]) {
- return nativeRemoveEventListener.apply(this, arguments);
- }
- var unwrappedCb = this._eventMap[cb];
- delete this._eventMap[cb];
- return nativeRemoveEventListener.apply(this, [nativeEventName,
- unwrappedCb]);
- };
-
- Object.defineProperty(proto, 'on' + eventNameToWrap, {
- get: function() {
- return this['_on' + eventNameToWrap];
- },
- set: function(cb) {
- if (this['_on' + eventNameToWrap]) {
- this.removeEventListener(eventNameToWrap,
- this['_on' + eventNameToWrap]);
- delete this['_on' + eventNameToWrap];
- }
- if (cb) {
- this.addEventListener(eventNameToWrap,
- this['_on' + eventNameToWrap] = cb);
- }
- }
- });
-}
-
-// Utility methods.
-module.exports = {
- extractVersion: extractVersion,
- wrapPeerConnectionEvent: wrapPeerConnectionEvent,
- disableLog: function(bool) {
- if (typeof bool !== 'boolean') {
- return new Error('Argument type: ' + typeof bool +
- '. Please use a boolean.');
- }
- logDisabled_ = bool;
- return (bool) ? 'adapter.js logging disabled' :
- 'adapter.js logging enabled';
- },
-
- /**
- * Disable or enable deprecation warnings
- * @param {!boolean} bool set to true to disable warnings.
- */
- disableWarnings: function(bool) {
- if (typeof bool !== 'boolean') {
- return new Error('Argument type: ' + typeof bool +
- '. Please use a boolean.');
- }
- deprecationWarnings_ = !bool;
- return 'adapter.js deprecation warnings ' + (bool ? 'disabled' : 'enabled');
- },
-
- log: function() {
- if (typeof window === 'object') {
- if (logDisabled_) {
- return;
- }
- if (typeof console !== 'undefined' && typeof console.log === 'function') {
- console.log.apply(console, arguments);
- }
- }
- },
-
- /**
- * Shows a deprecation warning suggesting the modern and spec-compatible API.
- */
- deprecated: function(oldMethod, newMethod) {
- if (!deprecationWarnings_) {
- return;
- }
- console.warn(oldMethod + ' is deprecated, please use ' + newMethod +
- ' instead.');
- },
-
- /**
- * Browser detector.
- *
- * @return {object} result containing browser and version
- * properties.
- */
- detectBrowser: function(window) {
- var navigator = window && window.navigator;
-
- // Returned result object.
- var result = {};
- result.browser = null;
- result.version = null;
-
- // Fail early if it's not a browser
- if (typeof window === 'undefined' || !window.navigator) {
- result.browser = 'Not a browser.';
- return result;
- }
-
- if (navigator.mozGetUserMedia) { // Firefox.
- result.browser = 'firefox';
- result.version = extractVersion(navigator.userAgent,
- /Firefox\/(\d+)\./, 1);
- } else if (navigator.webkitGetUserMedia) {
- // Chrome, Chromium, Webview, Opera.
- // Version matches Chrome/WebRTC version.
- result.browser = 'chrome';
- result.version = extractVersion(navigator.userAgent,
- /Chrom(e|ium)\/(\d+)\./, 2);
- } else if (navigator.mediaDevices &&
- navigator.userAgent.match(/Edge\/(\d+).(\d+)$/)) { // Edge.
- result.browser = 'edge';
- result.version = extractVersion(navigator.userAgent,
- /Edge\/(\d+).(\d+)$/, 2);
- } else if (navigator.mediaDevices &&
- navigator.userAgent.match(/AppleWebKit\/(\d+)\./)) { // Safari.
- result.browser = 'safari';
- result.version = extractVersion(navigator.userAgent,
- /AppleWebKit\/(\d+)\./, 1);
- } else { // Default fallthrough: not supported.
- result.browser = 'Not a supported browser.';
- return result;
- }
-
- return result;
- }
-};
-
-},{}]},{},[3])(3)
-});
\ No newline at end of file
+(function($){function findLine(sdpLines,prefix,substr){return findLineInRange(sdpLines,0,-1,prefix,substr);}
+function findLineInRange(sdpLines,startLine,endLine,prefix,substr){var realEndLine=(endLine!=-1)?endLine:sdpLines.length;for(var i=startLine;i=0;if(iOS){self.options.useVideo.setAttribute("playsinline",true);}}
+var element=self.options.useAudio;console.log("REMOTE STREAM",stream,element);FSRTCattachMediaStream(element,stream);self.remoteStream=stream;onRemoteStreamSuccess(self,stream);}
+function onOfferSDP(self,sdp){self.mediaData.SDP=self.stereoHack(sdp.sdp);console.log("Offer SDP");doCallback(self,"onOfferSDP");}
+$.FSRTC.prototype.answer=function(sdp,onSuccess,onError){this.peer.addAnswerSDP({type:"answer",sdp:sdp},onSuccess,onError);};$.FSRTC.prototype.stopPeer=function(){if(self.peer){console.log("stopping peer");self.peer.stop();}}
+$.FSRTC.prototype.stop=function(){var self=this;if(self.options.useVideo){self.options.useVideo.style.display='none';self.options.useVideo['src']='';}
+if(self.localStream&&!self.options.useStream){if(typeof self.localStream.stop=='function'){self.localStream.stop();}else{if(self.localStream.active){var tracks=self.localStream.getTracks();console.log(tracks);tracks.forEach(function(track,index){console.log(track);track.stop();})}}
+self.localStream=null;}
+if(self.options.localVideo){deactivateLocalVideo(self.options.localVideo);}
+if(self.options.localVideoStream&&!self.options.useStream){if(typeof self.options.localVideoStream.stop=='function'){self.options.localVideoStream.stop();}else{if(self.options.localVideoStream.active){var tracks=self.options.localVideoStream.getTracks();console.log(tracks);tracks.forEach(function(track,index){console.log(track);track.stop();})}}}
+if(self.peer){console.log("stopping peer");self.peer.stop();}};$.FSRTC.prototype.getMute=function(){var self=this;return self.audioEnabled;}
+$.FSRTC.prototype.setMute=function(what){var self=this;if(!self.localStream){return false;}
+var audioTracks=self.localStream.getAudioTracks();for(var i=0,len=audioTracks.length;i=w&&$.FSRTC.validRes[i][1]>=h){w=$.FSRTC.validRes[i][0];h=$.FSRTC.validRes[i][1];}}
+return[w,h];}
+var resList=[[160,120],[320,180],[320,240],[640,360],[640,480],[1280,720],[1920,1080]];var resI=0;var ttl=0;var checkRes=function(cam,func){if(resI>=resList.length){var res={'validRes':$.FSRTC.validRes,'bestResSupported':$.FSRTC.bestResSupported()};localStorage.setItem("res_"+cam,$.toJSON(res));if(func)return func(res);return;}
+w=resList[resI][0];h=resList[resI][1];resI++;var video={width:{exact:w},height:{exact:h}};if(cam!=="any"){video=assignMediaIdToConstraint(cam,video);}
+getUserMedia({constraints:{audio:ttl++==0,video:video},onsuccess:function(e){e.getTracks().forEach(function(track){track.stop();});console.info(w+"x"+h+" supported.");$.FSRTC.validRes.push([w,h]);checkRes(cam,func);},onerror:function(e){console.warn(w+"x"+h+" not supported.");checkRes(cam,func);}});}
+$.FSRTC.getValidRes=function(cam,func){var used=[];var cached=localStorage.getItem("res_"+cam);if(cached){var cache=$.parseJSON(cached);if(cache){$.FSRTC.validRes=cache.validRes;console.log("CACHED RES FOR CAM "+cam,cache);}else{console.error("INVALID CACHE");}
+return func?func(cache):null;}
+$.FSRTC.validRes=[];resI=0;checkRes(cam,func);}
+$.FSRTC.checkPerms=function(runtime,check_audio,check_video){getUserMedia({constraints:{audio:check_audio,video:check_video,},onsuccess:function(e){e.getTracks().forEach(function(track){track.stop();});console.info("media perm init complete");if(runtime){setTimeout(runtime,100,true);}},onerror:function(e){if(check_video&&check_audio){console.error("error, retesting with audio params only");return $.FSRTC.checkPerms(runtime,check_audio,false);}
+console.error("media perm init error");if(runtime){runtime(false)}}});}})(jQuery);(function($){$.JsonRpcClient=function(options){var self=this;this.options=$.extend({ajaxUrl:null,socketUrl:null,onmessage:null,login:null,passwd:null,sessid:null,loginParams:null,userVariables:null,getSocket:function(onmessage_cb){return self._getSocket(onmessage_cb);}},options);self.ws_cnt=0;this.wsOnMessage=function(event){self._wsOnMessage(event);};};$.JsonRpcClient.prototype._ws_socket=null;$.JsonRpcClient.prototype._ws_callbacks={};$.JsonRpcClient.prototype._current_id=1;$.JsonRpcClient.prototype.speedTest=function(bytes,cb){var socket=this.options.getSocket(this.wsOnMessage);if(socket!==null){this.speedCB=cb;this.speedBytes=bytes;socket.send("#SPU "+bytes);var loops=bytes/1024;var rem=bytes%1024;var i;var data=new Array(1024).join(".");for(i=0;i1){return false;}
+return true;};$.JsonRpcClient.prototype.closeSocket=function(){var self=this;if(self.socketReady()){self._ws_socket.onclose=function(w){console.log("Closing Socket");};self._ws_socket.close();}};$.JsonRpcClient.prototype.loginData=function(params){var self=this;self.options.login=params.login;self.options.passwd=params.passwd;self.options.loginParams=params.loginParams;self.options.userVariables=params.userVariables;};$.JsonRpcClient.prototype.connectSocket=function(onmessage_cb){var self=this;if(self.to){clearTimeout(self.to);}
+if(!self.socketReady()){self.authing=false;if(self._ws_socket){delete self._ws_socket;}
+self._ws_socket=new WebSocket(self.options.socketUrl);if(self._ws_socket){self._ws_socket.onmessage=onmessage_cb;self._ws_socket.onclose=function(w){if(!self.ws_sleep){self.ws_sleep=1000;}
+if(self.options.onWSClose){self.options.onWSClose(self);}
+if(self.ws_cnt>10&&self.options.wsFallbackURL){self.options.socketUrl=self.options.wsFallbackURL;}
+console.error("Websocket Lost "+self.ws_cnt+" sleep: "+self.ws_sleep+"msec");self.to=setTimeout(function(){console.log("Attempting Reconnection....");self.connectSocket(onmessage_cb);},self.ws_sleep);self.ws_cnt++;if(self.ws_sleep<3000&&(self.ws_cnt%10)===0){self.ws_sleep+=1000;}};self._ws_socket.onopen=function(){if(self.to){clearTimeout(self.to);}
+self.ws_sleep=1000;self.ws_cnt=0;if(self.options.onWSConnect){self.options.onWSConnect(self);}
+var req;while((req=$.JsonRpcClient.q.pop())){self._ws_socket.send(req);}};}}
+return self._ws_socket?true:false;};$.JsonRpcClient.prototype.stopRetrying=function(){if(self.to)
+clearTimeout(self.to);}
+$.JsonRpcClient.prototype._getSocket=function(onmessage_cb){if(this.options.socketUrl===null||!("WebSocket"in window))return null;this.connectSocket(onmessage_cb);return this._ws_socket;};$.JsonRpcClient.q=[];$.JsonRpcClient.prototype._wsCall=function(socket,request,success_cb,error_cb){var request_json=$.toJSON(request);if(socket.readyState<1){self=this;$.JsonRpcClient.q.push(request_json);}else{socket.send(request_json);}
+if('id'in request&&typeof success_cb!=='undefined'){this._ws_callbacks[request.id]={request:request_json,request_obj:request,success_cb:success_cb,error_cb:error_cb};}};$.JsonRpcClient.prototype._wsOnMessage=function(event){var response;if(event.data[0]=="#"&&event.data[1]=="S"&&event.data[2]=="P"){if(event.data[3]=="U"){this.up_dur=parseInt(event.data.substring(4));}else if(this.speedCB&&event.data[3]=="D"){this.down_dur=parseInt(event.data.substring(4));var up_kps=(((this.speedBytes*8)/(this.up_dur/1000))/1024).toFixed(0);var down_kps=(((this.speedBytes*8)/(this.down_dur/1000))/1024).toFixed(0);console.info("Speed Test: Up: "+up_kps+" Down: "+down_kps);var cb=this.speedCB;this.speedCB=null;cb(event,{upDur:this.up_dur,downDur:this.down_dur,upKPS:up_kps,downKPS:down_kps});}
+return;}
+try{response=$.parseJSON(event.data);if(typeof response==='object'&&'jsonrpc'in response&&response.jsonrpc==='2.0'){if('result'in response&&this._ws_callbacks[response.id]){var success_cb=this._ws_callbacks[response.id].success_cb;delete this._ws_callbacks[response.id];success_cb(response.result,this);return;}else if('error'in response&&this._ws_callbacks[response.id]){var error_cb=this._ws_callbacks[response.id].error_cb;var orig_req=this._ws_callbacks[response.id].request;if(!self.authing&&response.error.code==-32000&&self.options.login&&self.options.passwd){self.authing=true;this.call("login",{login:self.options.login,passwd:self.options.passwd,loginParams:self.options.loginParams,userVariables:self.options.userVariables},this._ws_callbacks[response.id].request_obj.method=="login"?function(e){self.authing=false;console.log("logged in");delete self._ws_callbacks[response.id];if(self.options.onWSLogin){self.options.onWSLogin(true,self);}}:function(e){self.authing=false;console.log("logged in, resending request id: "+response.id);var socket=self.options.getSocket(self.wsOnMessage);if(socket!==null){socket.send(orig_req);}
+if(self.options.onWSLogin){self.options.onWSLogin(true,self);}},function(e){console.log("error logging in, request id:",response.id);delete self._ws_callbacks[response.id];error_cb(response.error,this);if(self.options.onWSLogin){self.options.onWSLogin(false,self);}});return;}
+delete this._ws_callbacks[response.id];error_cb(response.error,this);return;}}}catch(err){console.log("ERROR: "+err);return;}
+if(typeof this.options.onmessage==='function'){event.eventData=response;if(!event.eventData){event.eventData={};}
+var reply=this.options.onmessage(event);if(reply&&typeof reply==="object"&&event.eventData.id){var msg={jsonrpc:"2.0",id:event.eventData.id,result:reply};var socket=self.options.getSocket(self.wsOnMessage);if(socket!==null){socket.send($.toJSON(msg));}}}};$.JsonRpcClient._batchObject=function(jsonrpcclient,all_done_cb,error_cb){this._requests=[];this.jsonrpcclient=jsonrpcclient;this.all_done_cb=all_done_cb;this.error_cb=typeof error_cb==='function'?error_cb:function(){};};$.JsonRpcClient._batchObject.prototype.call=function(method,params,success_cb,error_cb){if(!params){params={};}
+if(this.options.sessid){params.sessid=this.options.sessid;}
+if(!success_cb){success_cb=function(e){console.log("Success: ",e);};}
+if(!error_cb){error_cb=function(e){console.log("Error: ",e);};}
+this._requests.push({request:{jsonrpc:'2.0',method:method,params:params,id:this.jsonrpcclient._current_id++},success_cb:success_cb,error_cb:error_cb});};$.JsonRpcClient._batchObject.prototype.notify=function(method,params){if(this.options.sessid){params.sessid=this.options.sessid;}
+this._requests.push({request:{jsonrpc:'2.0',method:method,params:params}});};$.JsonRpcClient._batchObject.prototype._execute=function(){var self=this;if(this._requests.length===0)return;var batch_request=[];var handlers={};var i=0;var call;var success_cb;var error_cb;var socket=self.jsonrpcclient.options.getSocket(self.jsonrpcclient.wsOnMessage);if(socket!==null){for(i=0;i0){data.params.useVideo=true;}
+if(data.params.sdp&&data.params.sdp.indexOf("stereo=1")>0){data.params.useStereo=true;}
+dialog=new $.verto.dialog($.verto.enum.direction.inbound,verto,data.params);dialog.setState($.verto.enum.state.recovering);break;case'verto.invite':if(data.params.sdp&&data.params.sdp.indexOf("m=video")>0){data.params.wantVideo=true;}
+if(data.params.sdp&&data.params.sdp.indexOf("stereo=1")>0){data.params.useStereo=true;}
+dialog=new $.verto.dialog($.verto.enum.direction.inbound,verto,data.params);break;default:console.debug("INVALID METHOD OR NON-EXISTANT CALL REFERENCE IGNORED");break;}}
+return{method:data.method};}else{switch(data.method){case'verto.punt':verto.purge();verto.logout();break;case'verto.event':var list=null;var key=null;if(data.params){key=data.params.eventChannel;}
+if(key){list=verto.eventSUBS[key];if(!list){list=verto.eventSUBS[key.split(".")[0]];}}
+if(!list&&key&&key===verto.sessid){if(verto.callbacks.onMessage){verto.callbacks.onMessage(verto,null,$.verto.enum.message.pvtEvent,data.params);}}else if(!list&&key&&verto.dialogs[key]){verto.dialogs[key].sendMessage($.verto.enum.message.pvtEvent,data.params);}else if(!list){if(!key){key="UNDEFINED";}
+console.error("UNSUBBED or invalid EVENT "+key+" IGNORED");}else{for(var i in list){var sub=list[i];if(!sub||!sub.ready){console.error("invalid EVENT for "+key+" IGNORED");}else if(sub.handler){sub.handler(verto,data.params,sub.userData);}else if(verto.callbacks.onEvent){verto.callbacks.onEvent(verto,data.params,sub.userData);}else{console.log("EVENT:",data.params);}}}
+break;case"verto.info":if(verto.callbacks.onMessage){verto.callbacks.onMessage(verto,null,$.verto.enum.message.info,data.params.msg);}
+console.debug("MESSAGE from: "+data.params.msg.from,data.params.msg.body);break;case'verto.clientReady':if(verto.callbacks.onMessage){verto.callbacks.onMessage(verto,null,$.verto.enum.message.clientReady,data.params);}
+console.debug("CLIENT READY",data.params);break;default:console.error("INVALID METHOD OR NON-EXISTANT CALL REFERENCE IGNORED",data.method);break;}}};var del_array=function(array,name){var r=[];var len=array.length;for(var i=0;i=array.length){array.push(name);}else{var x=0;var n=[];var len=array.length;for(var i=0;i":"\n");});return str;};};$.verto.liveArray=function(verto,context,name,config){var la=this;var lastSerno=0;var binding=null;var user_obj=config.userObj;var local=false;hashArray.call(la);la._add=la.add;la._del=la.del;la._reorder=la.reorder;la._clear=la.clear;la.context=context;la.name=name;la.user_obj=user_obj;la.verto=verto;la.broadcast=function(channel,obj){verto.broadcast(channel,obj);};la.errs=0;la.clear=function(){la._clear();lastSerno=0;if(la.onChange){la.onChange(la,{action:"clear"});}};la.checkSerno=function(serno){if(serno<0){return true;}
+if(lastSerno>0&&serno!=(lastSerno+1)){if(la.onErr){la.onErr(la,{lastSerno:lastSerno,serno:serno});}
+la.errs++;console.debug(la.errs);if(la.errs<3){la.bootstrap(la.user_obj);}
+return false;}else{lastSerno=serno;return true;}};la.reorder=function(serno,a){if(la.checkSerno(serno)){la._reorder(a);if(la.onChange){la.onChange(la,{serno:serno,action:"reorder"});}}};la.init=function(serno,val,key,index){if(key===null||key===undefined){key=serno;}
+if(la.checkSerno(serno)){if(la.onChange){la.onChange(la,{serno:serno,action:"init",index:index,key:key,data:val});}}};la.bootObj=function(serno,val){if(la.checkSerno(serno)){for(var i in val){la._add(val[i][0],val[i][1]);}
+if(la.onChange){la.onChange(la,{serno:serno,action:"bootObj",data:val,redraw:true});}}};la.add=function(serno,val,key,index){if(key===null||key===undefined){key=serno;}
+if(la.checkSerno(serno)){var redraw=la._add(key,val,index);if(la.onChange){la.onChange(la,{serno:serno,action:"add",index:index,key:key,data:val,redraw:redraw});}}};la.modify=function(serno,val,key,index){if(key===null||key===undefined){key=serno;}
+if(la.checkSerno(serno)){la._add(key,val,index);if(la.onChange){la.onChange(la,{serno:serno,action:"modify",key:key,data:val,index:index});}}};la.del=function(serno,key,index){if(key===null||key===undefined){key=serno;}
+if(la.checkSerno(serno)){if(index===null||index<0||index===undefined){index=la.indexOf(key);}
+var ok=la._del(key);if(ok&&la.onChange){la.onChange(la,{serno:serno,action:"del",key:key,index:index});}}};var eventHandler=function(v,e,la){var packet=e.data;if(packet.name!=la.name){return;}
+switch(packet.action){case"init":la.init(packet.wireSerno,packet.data,packet.hashKey,packet.arrIndex);break;case"bootObj":la.bootObj(packet.wireSerno,packet.data);break;case"add":la.add(packet.wireSerno,packet.data,packet.hashKey,packet.arrIndex);break;case"modify":if(!(packet.arrIndex||packet.hashKey)){console.error("Invalid Packet",packet);}else{la.modify(packet.wireSerno,packet.data,packet.hashKey,packet.arrIndex);}
+break;case"del":if(!(packet.arrIndex||packet.hashKey)){console.error("Invalid Packet",packet);}else{la.del(packet.wireSerno,packet.hashKey,packet.arrIndex);}
+break;case"clear":la.clear();break;case"reorder":la.reorder(packet.wireSerno,packet.order);break;default:if(la.checkSerno(packet.wireSerno)){if(la.onChange){la.onChange(la,{serno:packet.wireSerno,action:packet.action,data:packet.data});}}
+break;}};if(la.context){binding=la.verto.subscribe(la.context,{handler:eventHandler,userData:la,subParams:config.subParams});}
+la.destroy=function(){la._clear();la.verto.unsubscribe(binding);};la.sendCommand=function(cmd,obj){var self=la;self.broadcast(self.context,{liveArray:{command:cmd,context:self.context,name:self.name,obj:obj}});};la.bootstrap=function(obj){var self=la;la.sendCommand("bootstrap",obj);};la.changepage=function(obj){var self=la;self.clear();self.broadcast(self.context,{liveArray:{command:"changepage",context:la.context,name:la.name,obj:obj}});};la.heartbeat=function(obj){var self=la;var callback=function(){self.heartbeat.call(self,obj);};self.broadcast(self.context,{liveArray:{command:"heartbeat",context:self.context,name:self.name,obj:obj}});self.hb_pid=setTimeout(callback,30000);};la.bootstrap(la.user_obj);};$.verto.liveTable=function(verto,context,name,jq,config){var dt;var la=new $.verto.liveArray(verto,context,name,{subParams:config.subParams});var lt=this;lt.liveArray=la;lt.dataTable=dt;lt.verto=verto;lt.destroy=function(){if(dt){dt.fnDestroy();}
+if(la){la.destroy();}
+dt=null;la=null;};la.onErr=function(obj,args){console.error("Error: ",obj,args);};function genRow(data){if(typeof(data[4])==="string"&&data[4].indexOf("{")>-1){var tmp=$.parseJSON(data[4]);data[4]=tmp.oldStatus;data[5]=null;}
+return data;}
+function genArray(obj){var data=obj.asArray();for(var i in data){data[i]=genRow(data[i]);}
+return data;}
+la.onChange=function(obj,args){var index=0;var iserr=0;if(!dt){if(!config.aoColumns){if(args.action!="init"){return;}
+config.aoColumns=[];for(var i in args.data){config.aoColumns.push({"sTitle":args.data[i]});}}
+dt=jq.dataTable(config);}
+if(dt&&(args.action=="del"||args.action=="modify")){index=args.index;if(index===undefined&&args.key){index=la.indexOf(args.key);}
+if(index===undefined){console.error("INVALID PACKET Missing INDEX\n",args);return;}}
+if(config.onChange){config.onChange(obj,args);}
+try{switch(args.action){case"bootObj":if(!args.data){console.error("missing data");return;}
+dt.fnClearTable();dt.fnAddData(genArray(obj));dt.fnAdjustColumnSizing();break;case"add":if(!args.data){console.error("missing data");return;}
+if(args.redraw>-1){dt.fnClearTable();dt.fnAddData(genArray(obj));}else{dt.fnAddData(genRow(args.data));}
+dt.fnAdjustColumnSizing();break;case"modify":if(!args.data){return;}
+dt.fnUpdate(genRow(args.data),index);dt.fnAdjustColumnSizing();break;case"del":dt.fnDeleteRow(index);dt.fnAdjustColumnSizing();break;case"clear":dt.fnClearTable();break;case"reorder":dt.fnClearTable();dt.fnAddData(genArray(obj));break;case"hide":jq.hide();break;case"show":jq.show();break;}}catch(err){console.error("ERROR: "+err);iserr++;}
+if(iserr){obj.errs++;if(obj.errs<3){obj.bootstrap(obj.user_obj);}}else{obj.errs=0;}};la.onChange(la,{action:"init"});};var CONFMAN_SERNO=1;$.verto.conf=function(verto,params){var conf=this;conf.params=$.extend({dialog:null,hasVid:false,laData:null,onBroadcast:null,onLaChange:null,onLaRow:null},params);conf.verto=verto;conf.serno=CONFMAN_SERNO++;createMainModeratorMethods();verto.subscribe(conf.params.laData.modChannel,{handler:function(v,e){if(conf.params.onBroadcast){conf.params.onBroadcast(verto,conf,e.data);}}});verto.subscribe(conf.params.laData.infoChannel,{handler:function(v,e){if(typeof(conf.params.infoCallback)==="function"){conf.params.infoCallback(v,e);}}});verto.subscribe(conf.params.laData.chatChannel,{handler:function(v,e){if(typeof(conf.params.chatCallback)==="function"){conf.params.chatCallback(v,e);}}});};$.verto.conf.prototype.modCommand=function(cmd,id,value){var conf=this;conf.verto.rpcClient.call("verto.broadcast",{"eventChannel":conf.params.laData.modChannel,"data":{"application":"conf-control","command":cmd,"id":id,"value":value}});};$.verto.conf.prototype.destroy=function(){var conf=this;conf.destroyed=true;conf.params.onBroadcast(conf.verto,conf,'destroy');if(conf.params.laData.modChannel){conf.verto.unsubscribe(conf.params.laData.modChannel);}
+if(conf.params.laData.chatChannel){conf.verto.unsubscribe(conf.params.laData.chatChannel);}
+if(conf.params.laData.infoChannel){conf.verto.unsubscribe(conf.params.laData.infoChannel);}};function createMainModeratorMethods(){$.verto.conf.prototype.listVideoLayouts=function(){this.modCommand("list-videoLayouts",null,null);};$.verto.conf.prototype.play=function(file){this.modCommand("play",null,file);};$.verto.conf.prototype.stop=function(){this.modCommand("stop",null,"all");};$.verto.conf.prototype.deaf=function(memberID){this.modCommand("deaf",parseInt(memberID));};$.verto.conf.prototype.undeaf=function(memberID){this.modCommand("undeaf",parseInt(memberID));};$.verto.conf.prototype.record=function(file){this.modCommand("recording",null,["start",file]);};$.verto.conf.prototype.stopRecord=function(){this.modCommand("recording",null,["stop","all"]);};$.verto.conf.prototype.snapshot=function(file){if(!this.params.hasVid){throw'Conference has no video';}
+this.modCommand("vid-write-png",null,file);};$.verto.conf.prototype.setVideoLayout=function(layout,canvasID){if(!this.params.hasVid){throw'Conference has no video';}
+if(canvasID){this.modCommand("vid-layout",null,[layout,canvasID]);}else{this.modCommand("vid-layout",null,layout);}};$.verto.conf.prototype.kick=function(memberID){this.modCommand("kick",parseInt(memberID));};$.verto.conf.prototype.muteMic=function(memberID){this.modCommand("tmute",parseInt(memberID));};$.verto.conf.prototype.muteVideo=function(memberID){if(!this.params.hasVid){throw'Conference has no video';}
+this.modCommand("tvmute",parseInt(memberID));};$.verto.conf.prototype.presenter=function(memberID){if(!this.params.hasVid){throw'Conference has no video';}
+this.modCommand("vid-res-id",parseInt(memberID),"presenter");};$.verto.conf.prototype.videoFloor=function(memberID){if(!this.params.hasVid){throw'Conference has no video';}
+this.modCommand("vid-floor",parseInt(memberID),"force");};$.verto.conf.prototype.banner=function(memberID,text){if(!this.params.hasVid){throw'Conference has no video';}
+this.modCommand("vid-banner",parseInt(memberID),escape(text));};$.verto.conf.prototype.volumeDown=function(memberID){this.modCommand("volume_out",parseInt(memberID),"down");};$.verto.conf.prototype.volumeUp=function(memberID){this.modCommand("volume_out",parseInt(memberID),"up");};$.verto.conf.prototype.gainDown=function(memberID){this.modCommand("volume_in",parseInt(memberID),"down");};$.verto.conf.prototype.gainUp=function(memberID){this.modCommand("volume_in",parseInt(memberID),"up");};$.verto.conf.prototype.transfer=function(memberID,exten){this.modCommand("transfer",parseInt(memberID),exten);};$.verto.conf.prototype.sendChat=function(message,type){var conf=this;conf.verto.rpcClient.call("verto.broadcast",{"eventChannel":conf.params.laData.chatChannel,"data":{"action":"send","message":message,"type":type}});};}
+$.verto.modfuncs={};$.verto.confMan=function(verto,params){var confMan=this;confMan.params=$.extend({tableID:null,statusID:null,mainModID:null,dialog:null,hasVid:false,laData:null,onBroadcast:null,onLaChange:null,onLaRow:null},params);confMan.verto=verto;confMan.serno=CONFMAN_SERNO++;confMan.canvasCount=confMan.params.laData.canvasCount;function genMainMod(jq){var play_id="play_"+confMan.serno;var stop_id="stop_"+confMan.serno;var recording_id="recording_"+confMan.serno;var snapshot_id="snapshot_"+confMan.serno;var rec_stop_id="recording_stop"+confMan.serno;var div_id="confman_"+confMan.serno;var html=" "+"Play "+"Stop "+"Record "+"Record Stop "+
+(confMan.params.hasVid?"PNG Snapshot ":"")+"
";jq.html(html);$.verto.modfuncs.change_video_layout=function(id,canvas_id){var val=$("#"+id+" option:selected").text();if(val!=="none"){confMan.modCommand("vid-layout",null,[val,canvas_id]);}};if(confMan.params.hasVid){for(var j=0;j "+"Video Layout Canvas "+(j+1)+" "+" ";jq.append(vlhtml);}
+$("#"+snapshot_id).click(function(){var file=prompt("Please enter file name","");if(file){confMan.modCommand("vid-write-png",null,file);}});}
+$("#"+play_id).click(function(){var file=prompt("Please enter file name","");if(file){confMan.modCommand("play",null,file);}});$("#"+stop_id).click(function(){confMan.modCommand("stop",null,"all");});$("#"+recording_id).click(function(){var file=prompt("Please enter file name","");if(file){confMan.modCommand("recording",null,["start",file]);}});$("#"+rec_stop_id).click(function(){confMan.modCommand("recording",null,["stop","all"]);});}
+function genControls(jq,rowid){var x=parseInt(rowid);var kick_id="kick_"+x;var canvas_in_next_id="canvas_in_next_"+x;var canvas_in_prev_id="canvas_in_prev_"+x;var canvas_out_next_id="canvas_out_next_"+x;var canvas_out_prev_id="canvas_out_prev_"+x;var canvas_in_set_id="canvas_in_set_"+x;var canvas_out_set_id="canvas_out_set_"+x;var layer_set_id="layer_set_"+x;var layer_next_id="layer_next_"+x;var layer_prev_id="layer_prev_"+x;var tmute_id="tmute_"+x;var tvmute_id="tvmute_"+x;var vbanner_id="vbanner_"+x;var tvpresenter_id="tvpresenter_"+x;var tvfloor_id="tvfloor_"+x;var box_id="box_"+x;var gainup_id="gain_in_up"+x;var gaindn_id="gain_in_dn"+x;var volup_id="vol_in_up"+x;var voldn_id="vol_in_dn"+x;var transfer_id="transfer"+x;var html="";html+="General Controls
";html+="Kick "+"Mute "+"Gain - "+"Gain + "+"Vol - "+"Vol + "+"Transfer ";if(confMan.params.hasVid){html+="Video Controls ";html+="VMute "+"Presenter "+"Vid Floor "+"Banner ";if(confMan.canvasCount>1){html+="Canvas Controls "+"Set Input Canvas "+"Prev Input Canvas "+"Next Input Canvas "+" "+"Set Watching Canvas "+"Prev Watching Canvas "+"Next Watching Canvas ";}
+html+=" "+"Set Layer "+"Prev Layer "+"Next Layer "+"";}
+jq.html(html);if(!jq.data("mouse")){$("#"+box_id).hide();}
+jq.mouseover(function(e){jq.data({"mouse":true});$("#"+box_id).show();});jq.mouseout(function(e){jq.data({"mouse":false});$("#"+box_id).hide();});$("#"+transfer_id).click(function(){var xten=prompt("Enter Extension");if(xten){confMan.modCommand("transfer",x,xten);}});$("#"+kick_id).click(function(){confMan.modCommand("kick",x);});$("#"+layer_set_id).click(function(){var cid=prompt("Please enter layer ID","");if(cid){confMan.modCommand("vid-layer",x,cid);}});$("#"+layer_next_id).click(function(){confMan.modCommand("vid-layer",x,"next");});$("#"+layer_prev_id).click(function(){confMan.modCommand("vid-layer",x,"prev");});$("#"+canvas_in_set_id).click(function(){var cid=prompt("Please enter canvas ID","");if(cid){confMan.modCommand("vid-canvas",x,cid);}});$("#"+canvas_out_set_id).click(function(){var cid=prompt("Please enter canvas ID","");if(cid){confMan.modCommand("vid-watching-canvas",x,cid);}});$("#"+canvas_in_next_id).click(function(){confMan.modCommand("vid-canvas",x,"next");});$("#"+canvas_in_prev_id).click(function(){confMan.modCommand("vid-canvas",x,"prev");});$("#"+canvas_out_next_id).click(function(){confMan.modCommand("vid-watching-canvas",x,"next");});$("#"+canvas_out_prev_id).click(function(){confMan.modCommand("vid-watching-canvas",x,"prev");});$("#"+tmute_id).click(function(){confMan.modCommand("tmute",x);});if(confMan.params.hasVid){$("#"+tvmute_id).click(function(){confMan.modCommand("tvmute",x);});$("#"+tvpresenter_id).click(function(){confMan.modCommand("vid-res-id",x,"presenter");});$("#"+tvfloor_id).click(function(){confMan.modCommand("vid-floor",x,"force");});$("#"+vbanner_id).click(function(){var text=prompt("Please enter text","");if(text){confMan.modCommand("vid-banner",x,escape(text));}});}
+$("#"+gainup_id).click(function(){confMan.modCommand("volume_in",x,"up");});$("#"+gaindn_id).click(function(){confMan.modCommand("volume_in",x,"down");});$("#"+volup_id).click(function(){confMan.modCommand("volume_out",x,"up");});$("#"+voldn_id).click(function(){confMan.modCommand("volume_out",x,"down");});return html;}
+var atitle="";var awidth=0;verto.subscribe(confMan.params.laData.infoChannel,{handler:function(v,e){if(typeof(confMan.params.infoCallback)==="function"){confMan.params.infoCallback(v,e);}}});verto.subscribe(confMan.params.laData.chatChannel,{handler:function(v,e){if(typeof(confMan.params.chatCallback)==="function"){confMan.params.chatCallback(v,e);}}});if(confMan.params.laData.role==="moderator"){atitle="Action";awidth=600;if(confMan.params.mainModID){genMainMod($(confMan.params.mainModID));$(confMan.params.displayID).html("Moderator Controls Ready ");}else{$(confMan.params.mainModID).html("");}
+verto.subscribe(confMan.params.laData.modChannel,{handler:function(v,e){if(confMan.params.onBroadcast){confMan.params.onBroadcast(verto,confMan,e.data);}
+if(e.data["conf-command"]==="list-videoLayouts"){for(var j=0;jb)?1:-1));});for(var i in options){$(vlselect_id).append(new Option(options[i],options[i]));x++;}}
+if(x){$(vlselect_id).selectmenu('refresh',true);}else{$(vlayout_id).hide();}}}else{if(!confMan.destroyed&&confMan.params.displayID){$(confMan.params.displayID).html(e.data.response+" ");if(confMan.lastTimeout){clearTimeout(confMan.lastTimeout);confMan.lastTimeout=0;}
+confMan.lastTimeout=setTimeout(function(){$(confMan.params.displayID).html(confMan.destroyed?"":"Moderator Controls Ready ");},4000);}}}});if(confMan.params.hasVid){confMan.modCommand("list-videoLayouts",null,null);}}
+var row_callback=null;if(confMan.params.laData.role==="moderator"){row_callback=function(nRow,aData,iDisplayIndex,iDisplayIndexFull){if(!aData[5]){var $row=$('td:eq(5)',nRow);genControls($row,aData);if(confMan.params.onLaRow){confMan.params.onLaRow(verto,confMan,$row,aData);}}};}
+confMan.lt=new $.verto.liveTable(verto,confMan.params.laData.laChannel,confMan.params.laData.laName,$(confMan.params.tableID),{subParams:{callID:confMan.params.dialog?confMan.params.dialog.callID:null},"onChange":function(obj,args){$(confMan.params.statusID).text("Conference Members: "+" ("+obj.arrayLen()+" Total)");if(confMan.params.onLaChange){confMan.params.onLaChange(verto,confMan,$.verto.enum.confEvent.laChange,obj,args);}},"aaData":[],"aoColumns":[{"sTitle":"ID","sWidth":"50"},{"sTitle":"Number","sWidth":"250"},{"sTitle":"Name","sWidth":"250"},{"sTitle":"Codec","sWidth":"100"},{"sTitle":"Status","sWidth":confMan.params.hasVid?"200px":"150px"},{"sTitle":atitle,"sWidth":awidth,}],"bAutoWidth":true,"bDestroy":true,"bSort":false,"bInfo":false,"bFilter":false,"bLengthChange":false,"bPaginate":false,"iDisplayLength":1400,"oLanguage":{"sEmptyTable":"The Conference is Empty....."},"fnRowCallback":row_callback});};$.verto.confMan.prototype.modCommand=function(cmd,id,value){var confMan=this;confMan.verto.rpcClient.call("verto.broadcast",{"eventChannel":confMan.params.laData.modChannel,"data":{"application":"conf-control","command":cmd,"id":id,"value":value}});};$.verto.confMan.prototype.sendChat=function(message,type){var confMan=this;confMan.verto.rpcClient.call("verto.broadcast",{"eventChannel":confMan.params.laData.chatChannel,"data":{"action":"send","message":message,"type":type}});};$.verto.confMan.prototype.destroy=function(){var confMan=this;confMan.destroyed=true;if(confMan.lt){confMan.lt.destroy();}
+if(confMan.params.laData.chatChannel){confMan.verto.unsubscribe(confMan.params.laData.chatChannel);}
+if(confMan.params.laData.modChannel){confMan.verto.unsubscribe(confMan.params.laData.modChannel);}
+if(confMan.params.mainModID){$(confMan.params.mainModID).html("");}};$.verto.dialog=function(direction,verto,params){var dialog=this;dialog.params=$.extend({useVideo:verto.options.useVideo,useStereo:verto.options.useStereo,screenShare:false,useCamera:false,useMic:verto.options.deviceParams.useMic,useMicLabel:verto.options.deviceParams.useMicLabel,useSpeak:verto.options.deviceParams.useSpeak,tag:verto.options.tag,localTag:verto.options.localTag,login:verto.options.login,videoParams:verto.options.videoParams,useStream:verto.options.useStream,},params);if(!dialog.params.screenShare){dialog.params.useCamera=verto.options.deviceParams.useCamera;dialog.params.useCameraLabel=verto.options.deviceParams.useCameraLabel;}
+dialog.verto=verto;dialog.direction=direction;dialog.lastState=null;dialog.state=dialog.lastState=$.verto.enum.state.new;dialog.callbacks=verto.callbacks;dialog.answered=false;dialog.attach=params.attach||false;dialog.screenShare=params.screenShare||false;dialog.useCamera=dialog.params.useCamera;dialog.useCameraLabel=dialog.params.useCameraLabel;dialog.useMic=dialog.params.useMic;dialog.useMicLabel=dialog.params.useMicLabel;dialog.useSpeak=dialog.params.useSpeak;if(dialog.params.callID){dialog.callID=dialog.params.callID;}else{dialog.callID=dialog.params.callID=generateGUID();}
+if(typeof(dialog.params.tag)==="function"){dialog.params.tag=dialog.params.tag();}
+if(dialog.params.tag){dialog.audioStream=document.getElementById(dialog.params.tag);if(dialog.params.useVideo){dialog.videoStream=dialog.audioStream;}}
+if(dialog.params.localTag){dialog.localVideo=document.getElementById(dialog.params.localTag);}
+dialog.verto.dialogs[dialog.callID]=dialog;var RTCcallbacks={};if(dialog.direction==$.verto.enum.direction.inbound){if(dialog.params.display_direction==="outbound"){dialog.params.remote_caller_id_name=dialog.params.caller_id_name;dialog.params.remote_caller_id_number=dialog.params.caller_id_number;}else{dialog.params.remote_caller_id_name=dialog.params.callee_id_name;dialog.params.remote_caller_id_number=dialog.params.callee_id_number;}
+if(!dialog.params.remote_caller_id_name){dialog.params.remote_caller_id_name="Nobody";}
+if(!dialog.params.remote_caller_id_number){dialog.params.remote_caller_id_number="UNKNOWN";}
+RTCcallbacks.onMessage=function(rtc,msg){console.debug(msg);};RTCcallbacks.onAnswerSDP=function(rtc,sdp){console.error("answer sdp",sdp);};}else{dialog.params.remote_caller_id_name="Outbound Call";dialog.params.remote_caller_id_number=dialog.params.destination_number;}
+RTCcallbacks.onICESDP=function(rtc){console.log("RECV "+rtc.type+" SDP",rtc.mediaData.SDP);if(dialog.state==$.verto.enum.state.requesting||dialog.state==$.verto.enum.state.answering||dialog.state==$.verto.enum.state.active){location.reload();return;}
+if(rtc.type=="offer"){if(dialog.state==$.verto.enum.state.active){dialog.setState($.verto.enum.state.requesting);dialog.sendMethod("verto.attach",{sdp:rtc.mediaData.SDP});}else{dialog.setState($.verto.enum.state.requesting);dialog.sendMethod("verto.invite",{sdp:rtc.mediaData.SDP});}}else{dialog.setState($.verto.enum.state.answering);dialog.sendMethod(dialog.attach?"verto.attach":"verto.answer",{sdp:dialog.rtc.mediaData.SDP});}};RTCcallbacks.onICE=function(rtc){if(rtc.type=="offer"){console.log("offer",rtc.mediaData.candidate);return;}};RTCcallbacks.onStream=function(rtc,stream){if(dialog.callbacks.permissionCallback&&typeof dialog.callbacks.permissionCallback.onGranted==='function'){dialog.callbacks.permissionCallback.onGranted(stream);}
+else if(dialog.verto.options.permissionCallback&&typeof dialog.verto.options.permissionCallback.onGranted==='function'){dialog.verto.options.permissionCallback.onGranted(stream);}
+console.log("stream started");};RTCcallbacks.onRemoteStream=function(rtc,stream){if(typeof dialog.callbacks.onRemoteStream==='function'){dialog.callbacks.onRemoteStream(stream,dialog);}
+console.log("remote stream started");};RTCcallbacks.onError=function(e){if(dialog.callbacks.permissionCallback&&typeof dialog.callbacks.permissionCallback.onDenied==='function'){dialog.callbacks.permissionCallback.onDenied();}
+else if(dialog.verto.options.permissionCallback&&typeof dialog.verto.options.permissionCallback.onDenied==='function'){dialog.verto.options.permissionCallback.onDenied();}
+console.error("ERROR:",e);dialog.hangup({cause:"Device or Permission Error"});};dialog.rtc=new $.FSRTC({callbacks:RTCcallbacks,localVideo:dialog.screenShare?null:dialog.localVideo,useVideo:dialog.params.useVideo?dialog.videoStream:null,useAudio:dialog.audioStream,useStereo:dialog.params.useStereo,videoParams:dialog.params.videoParams,audioParams:verto.options.audioParams,iceServers:verto.options.iceServers,screenShare:dialog.screenShare,useCamera:dialog.useCamera,useCameraLabel:dialog.useCameraLabel,useMic:dialog.useMic,useMicLabel:dialog.useMicLabel,useSpeak:dialog.useSpeak,turnServer:verto.options.turnServer,useStream:dialog.params.useStream});dialog.rtc.verto=dialog.verto;if(dialog.direction==$.verto.enum.direction.inbound){if(dialog.attach){dialog.answer();}else{dialog.ring();}}};$.verto.dialog.prototype.invite=function(){var dialog=this;dialog.rtc.call();};$.verto.dialog.prototype.sendMethod=function(method,obj){var dialog=this;obj.dialogParams={};for(var i in dialog.params){if(i=="sdp"&&method!="verto.invite"&&method!="verto.attach"){continue;}
+if((obj.noDialogParams&&i!="callID")){continue;}
+obj.dialogParams[i]=dialog.params[i];}
+delete obj.noDialogParams;dialog.verto.rpcClient.call(method,obj,function(e){dialog.processReply(method,true,e);},function(e){dialog.processReply(method,false,e);});};function checkStateChange(oldS,newS){if(newS==$.verto.enum.state.purge||$.verto.enum.states[oldS.name][newS.name]){return true;}
+return false;}
+function find_name(id){for(var i in $.verto.audioOutDevices){var source=$.verto.audioOutDevices[i];if(source.id===id){return(source.label);}}
+return id;}
+$.verto.dialog.prototype.setAudioPlaybackDevice=function(sinkId,callback,arg){var dialog=this;var element=dialog.audioStream;if(typeof element.sinkId!=='undefined'){var devname=find_name(sinkId);console.info("Dialog: "+dialog.callID+" Setting speaker:",element,devname);element.setSinkId(sinkId).then(function(){console.log("Dialog: "+dialog.callID+' Success, audio output device attached: '+sinkId);if(callback){callback(true,devname,arg);}}).catch(function(error){var errorMessage=error;if(error.name==='SecurityError'){errorMessage="Dialog: "+dialog.callID+' You need to use HTTPS for selecting audio output '+'device: '+error;}
+if(callback){callback(false,null,arg);}
+console.error(errorMessage);});}else{console.warn("Dialog: "+dialog.callID+' Browser does not support output device selection.');if(callback){callback(false,null,arg);}}}
+$.verto.dialog.prototype.setState=function(state){var dialog=this;if(dialog.state==$.verto.enum.state.ringing){dialog.stopRinging();}
+if(dialog.state==state||!checkStateChange(dialog.state,state)){console.error("Dialog "+dialog.callID+": INVALID state change from "+dialog.state.name+" to "+state.name);dialog.hangup();return false;}
+console.log("Dialog "+dialog.callID+": state change from "+dialog.state.name+" to "+state.name);dialog.lastState=dialog.state;dialog.state=state;if(dialog.callbacks.onDialogState){dialog.callbacks.onDialogState(this);}
+switch(dialog.state){case $.verto.enum.state.early:case $.verto.enum.state.active:var speaker=dialog.useSpeak;console.info("Using Speaker: ",speaker);if(speaker&&speaker!=="any"&&speaker!=="none"){setTimeout(function(){dialog.setAudioPlaybackDevice(speaker);},500);}
+break;case $.verto.enum.state.trying:setTimeout(function(){if(dialog.state==$.verto.enum.state.trying){dialog.setState($.verto.enum.state.hangup);}},30000);break;case $.verto.enum.state.purge:dialog.setState($.verto.enum.state.destroy);break;case $.verto.enum.state.hangup:if(dialog.lastState.val>$.verto.enum.state.requesting.val&&dialog.lastState.val<$.verto.enum.state.hangup.val){dialog.sendMethod("verto.bye",{});}
+dialog.setState($.verto.enum.state.destroy);break;case $.verto.enum.state.destroy:if(typeof(dialog.verto.options.tag)==="function"){$('#'+dialog.params.tag).remove();}
+delete dialog.verto.dialogs[dialog.callID];if(dialog.params.screenShare){dialog.rtc.stopPeer();}else{dialog.rtc.stop();}
+break;}
+return true;};$.verto.dialog.prototype.processReply=function(method,success,e){var dialog=this;switch(method){case"verto.answer":case"verto.attach":if(success){dialog.setState($.verto.enum.state.active);}else{dialog.hangup();}
+break;case"verto.invite":if(success){dialog.setState($.verto.enum.state.trying);}else{dialog.setState($.verto.enum.state.destroy);}
+break;case"verto.bye":dialog.hangup();break;case"verto.modify":if(e.holdState){if(e.holdState=="held"){if(dialog.state!=$.verto.enum.state.held){dialog.setState($.verto.enum.state.held);}}else if(e.holdState=="active"){if(dialog.state!=$.verto.enum.state.active){dialog.setState($.verto.enum.state.active);}}}
+if(success){}
+break;default:break;}};$.verto.dialog.prototype.hangup=function(params){var dialog=this;if(params){if(params.causeCode){dialog.causeCode=params.causeCode;}
+if(params.cause){dialog.cause=params.cause;}}
+if(!dialog.cause&&!dialog.causeCode){dialog.cause="NORMAL_CLEARING";}
+if(dialog.state.val>=$.verto.enum.state.new.val&&dialog.state.val<$.verto.enum.state.hangup.val){dialog.setState($.verto.enum.state.hangup);}else if(dialog.state.val<$.verto.enum.state.destroy){dialog.setState($.verto.enum.state.destroy);}};$.verto.dialog.prototype.stopRinging=function(){var dialog=this;if(dialog.verto.ringer){dialog.verto.ringer.stop();}};$.verto.dialog.prototype.indicateRing=function(){var dialog=this;if(dialog.verto.ringer){dialog.verto.ringer.attr("src",dialog.verto.options.ringFile)[0].play();setTimeout(function(){dialog.stopRinging();if(dialog.state==$.verto.enum.state.ringing){dialog.indicateRing();}},dialog.verto.options.ringSleep);}};$.verto.dialog.prototype.ring=function(){var dialog=this;dialog.setState($.verto.enum.state.ringing);dialog.indicateRing();};$.verto.dialog.prototype.useVideo=function(on){var dialog=this;dialog.params.useVideo=on;if(on){dialog.videoStream=dialog.audioStream;}else{dialog.videoStream=null;}
+dialog.rtc.useVideo(dialog.videoStream,dialog.localVideo);};$.verto.dialog.prototype.setMute=function(what){var dialog=this;return dialog.rtc.setMute(what);};$.verto.dialog.prototype.getMute=function(){var dialog=this;return dialog.rtc.getMute();};$.verto.dialog.prototype.setVideoMute=function(what){var dialog=this;return dialog.rtc.setVideoMute(what);};$.verto.dialog.prototype.getVideoMute=function(){var dialog=this;return dialog.rtc.getVideoMute();};$.verto.dialog.prototype.useStereo=function(on){var dialog=this;dialog.params.useStereo=on;dialog.rtc.useStereo(on);};$.verto.dialog.prototype.dtmf=function(digits){var dialog=this;if(digits){dialog.sendMethod("verto.info",{dtmf:digits});}};$.verto.dialog.prototype.rtt=function(obj){var dialog=this;var pobj={};if(!obj){return false;}
+pobj.code=obj.code;pobj.chars=obj.chars;if(pobj.chars||pobj.code){dialog.sendMethod("verto.info",{txt:obj,noDialogParams:true});}};$.verto.dialog.prototype.transfer=function(dest,params){var dialog=this;if(dest){dialog.sendMethod("verto.modify",{action:"transfer",destination:dest,params:params});}};$.verto.dialog.prototype.replace=function(replaceCallID,params){var dialog=this;if(replaceCallID){dialog.sendMethod("verto.modify",{action:"replace",replaceCallID:replaceCallID,params:params});}};$.verto.dialog.prototype.hold=function(params){var dialog=this;dialog.sendMethod("verto.modify",{action:"hold",params:params});};$.verto.dialog.prototype.unhold=function(params){var dialog=this;dialog.sendMethod("verto.modify",{action:"unhold",params:params});};$.verto.dialog.prototype.toggleHold=function(params){var dialog=this;dialog.sendMethod("verto.modify",{action:"toggleHold",params:params});};$.verto.dialog.prototype.message=function(msg){var dialog=this;var err=0;msg.from=dialog.params.login;if(!msg.to){console.error("Missing To");err++;}
+if(!msg.body){console.error("Missing Body");err++;}
+if(err){return false;}
+dialog.sendMethod("verto.info",{msg:msg});return true;};$.verto.dialog.prototype.answer=function(params){var dialog=this;if(!dialog.answered){if(!params){params={};}
+params.sdp=dialog.params.sdp;if(params){if(params.useVideo){dialog.useVideo(true);}
+dialog.params.callee_id_name=params.callee_id_name;dialog.params.callee_id_number=params.callee_id_number;if(params.useCamera){dialog.useCamera=params.useCamera;dialog.useCameraLabel=params.useCameraLabel;}
+if(params.useMic){dialog.useMic=params.useMic;dialog.useMic=params.useMicLabel;}
+if(params.useSpeak){dialog.useSpeak=params.useSpeak;}}
+dialog.rtc.createAnswer(params);dialog.answered=true;}};$.verto.dialog.prototype.handleAnswer=function(params){var dialog=this;dialog.gotAnswer=true;if(dialog.state.val>=$.verto.enum.state.active.val){return;}
+if(dialog.state.val>=$.verto.enum.state.early.val){dialog.setState($.verto.enum.state.active);}else{if(dialog.gotEarly){console.log("Dialog "+dialog.callID+" Got answer while still establishing early media, delaying...");}else{console.log("Dialog "+dialog.callID+" Answering Channel");dialog.rtc.answer(params.sdp,function(){dialog.setState($.verto.enum.state.active);},function(e){console.error(e);dialog.hangup();});console.log("Dialog "+dialog.callID+"ANSWER SDP",params.sdp);}}};$.verto.dialog.prototype.cidString=function(enc){var dialog=this;var party=dialog.params.remote_caller_id_name+(enc?" <":" <")+dialog.params.remote_caller_id_number+(enc?">":">");return party;};$.verto.dialog.prototype.sendMessage=function(msg,params){var dialog=this;if(dialog.callbacks.onMessage){dialog.callbacks.onMessage(dialog.verto,dialog,msg,params);}};$.verto.dialog.prototype.handleInfo=function(params){var dialog=this;dialog.sendMessage($.verto.enum.message.info,params);};$.verto.dialog.prototype.handleDisplay=function(params){var dialog=this;if(params.display_name){dialog.params.remote_caller_id_name=params.display_name;}
+if(params.display_number){dialog.params.remote_caller_id_number=params.display_number;}
+dialog.sendMessage($.verto.enum.message.display,{});};$.verto.dialog.prototype.handleMedia=function(params){var dialog=this;if(dialog.state.val>=$.verto.enum.state.early.val){return;}
+dialog.gotEarly=true;dialog.rtc.answer(params.sdp,function(){console.log("Dialog "+dialog.callID+"Establishing early media");dialog.setState($.verto.enum.state.early);if(dialog.gotAnswer){console.log("Dialog "+dialog.callID+"Answering Channel");dialog.setState($.verto.enum.state.active);}},function(e){console.error(e);dialog.hangup();});console.log("Dialog "+dialog.callID+"EARLY SDP",params.sdp);};$.verto.ENUM=function(s){var i=0,o={};s.split(" ").map(function(x){o[x]={name:x,val:i++};});return Object.freeze(o);};$.verto.enum={};$.verto.enum.states=Object.freeze({new:{requesting:1,recovering:1,ringing:1,destroy:1,answering:1,hangup:1},requesting:{trying:1,hangup:1,active:1},recovering:{answering:1,hangup:1},trying:{active:1,early:1,hangup:1},ringing:{answering:1,hangup:1},answering:{active:1,hangup:1},active:{answering:1,requesting:1,hangup:1,held:1},held:{hangup:1,active:1},early:{hangup:1,active:1},hangup:{destroy:1},destroy:{},purge:{destroy:1}});$.verto.enum.state=$.verto.ENUM("new requesting trying recovering ringing answering early active held hangup destroy purge");$.verto.enum.direction=$.verto.ENUM("inbound outbound");$.verto.enum.message=$.verto.ENUM("display info pvtEvent clientReady");$.verto.enum=Object.freeze($.verto.enum);$.verto.saved=[];$.verto.unloadJobs=[];var unloadEventName='beforeunload';var iOS=['iPad','iPhone','iPod'].indexOf(navigator.platform)>=0;if(iOS){unloadEventName='pagehide';}
+$(window).bind(unloadEventName,function(){for(var f in $.verto.unloadJobs){$.verto.unloadJobs[f]();}
+if($.verto.haltClosure)
+return $.verto.haltClosure();for(var i in $.verto.saved){var verto=$.verto.saved[i];if(verto){verto.purge();verto.logout();}}
+return $.verto.warnOnUnload;});$.verto.videoDevices=[];$.verto.audioInDevices=[];$.verto.audioOutDevices=[];var checkDevices=function(runtime){console.info("enumerating devices");var aud_in=[],aud_out=[],vid=[];var has_video=0,has_audio=0;var Xstream;function gotDevices(deviceInfos){for(var i=0;i!==deviceInfos.length;++i){var deviceInfo=deviceInfos[i];var text="";console.log(deviceInfo);console.log(deviceInfo.kind+": "+deviceInfo.label+" id = "+deviceInfo.deviceId);if(deviceInfo.kind==='audioinput'){text=deviceInfo.label||'microphone '+(aud_in.length+1);aud_in.push({id:deviceInfo.deviceId,kind:"audio_in",label:text});}else if(deviceInfo.kind==='audiooutput'){text=deviceInfo.label||'speaker '+(aud_out.length+1);aud_out.push({id:deviceInfo.deviceId,kind:"audio_out",label:text});}else if(deviceInfo.kind==='videoinput'){text=deviceInfo.label||'camera '+(vid.length+1);vid.push({id:deviceInfo.deviceId,kind:"video",label:text});}else{console.log('Some other kind of source/device: ',deviceInfo);}}
+$.verto.videoDevices=vid;$.verto.audioInDevices=aud_in;$.verto.audioOutDevices=aud_out;console.info("Audio IN Devices",$.verto.audioInDevices);console.info("Audio Out Devices",$.verto.audioOutDevices);console.info("Video Devices",$.verto.videoDevices);if(Xstream){Xstream.getTracks().forEach(function(track){track.stop();});}
+if(runtime){runtime(true);}}
+function handleError(error){console.log('device enumeration error: ',error);if(runtime)runtime(false);}
+function checkTypes(devs){for(var i=0;i!==devs.length;++i){if(devs[i].kind==='audioinput'){has_audio++;}else if(devs[i].kind==='videoinput'){has_video++;}}
+navigator.getUserMedia({audio:(has_audio>0?true:false),video:(has_video>0?true:false)},function(stream){Xstream=stream;navigator.mediaDevices.enumerateDevices().then(gotDevices).catch(handleError);},function(err){console.log("The following error occurred: "+err.name);});}
+navigator.mediaDevices.enumerateDevices().then(checkTypes).catch(handleError);};$.verto.refreshDevices=function(runtime){checkDevices(runtime);}
+$.verto.init=function(obj,runtime){if(!obj){obj={};}
+if(!obj.skipPermCheck&&!obj.skipDeviceCheck){$.FSRTC.checkPerms(function(status){checkDevices(runtime);},true,true);}else if(obj.skipPermCheck&&!obj.skipDeviceCheck){checkDevices(runtime);}else if(!obj.skipPermCheck&&obj.skipDeviceCheck){$.FSRTC.checkPerms(function(status){runtime(status);},true,true);}else{runtime(null);}}
+$.verto.genUUID=function(){return generateGUID();}})(jQuery);(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.adapter=f()}})(function(){var define,module,exports;return(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i0&&arguments[0]!==undefined?arguments[0]:{},window=_ref.window;var options=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{shimChrome:true,shimFirefox:true,shimEdge:true,shimSafari:true};var logging=utils.log;var browserDetails=utils.detectBrowser(window);var adapter={browserDetails:browserDetails,commonShim:commonShim,extractVersion:utils.extractVersion,disableLog:utils.disableLog,disableWarnings:utils.disableWarnings};switch(browserDetails.browser){case'chrome':if(!chromeShim||!chromeShim.shimPeerConnection||!options.shimChrome){logging('Chrome shim is not included in this adapter release.');return adapter;}
+logging('adapter.js shimming chrome.');adapter.browserShim=chromeShim;chromeShim.shimGetUserMedia(window);chromeShim.shimMediaStream(window);chromeShim.shimPeerConnection(window);chromeShim.shimOnTrack(window);chromeShim.shimAddTrackRemoveTrack(window);chromeShim.shimGetSendersWithDtmf(window);chromeShim.shimSenderReceiverGetStats(window);chromeShim.fixNegotiationNeeded(window);commonShim.shimRTCIceCandidate(window);commonShim.shimConnectionState(window);commonShim.shimMaxMessageSize(window);commonShim.shimSendThrowTypeError(window);commonShim.removeAllowExtmapMixed(window);break;case'firefox':if(!firefoxShim||!firefoxShim.shimPeerConnection||!options.shimFirefox){logging('Firefox shim is not included in this adapter release.');return adapter;}
+logging('adapter.js shimming firefox.');adapter.browserShim=firefoxShim;firefoxShim.shimGetUserMedia(window);firefoxShim.shimPeerConnection(window);firefoxShim.shimOnTrack(window);firefoxShim.shimRemoveStream(window);firefoxShim.shimSenderGetStats(window);firefoxShim.shimReceiverGetStats(window);firefoxShim.shimRTCDataChannel(window);commonShim.shimRTCIceCandidate(window);commonShim.shimConnectionState(window);commonShim.shimMaxMessageSize(window);commonShim.shimSendThrowTypeError(window);break;case'edge':if(!edgeShim||!edgeShim.shimPeerConnection||!options.shimEdge){logging('MS edge shim is not included in this adapter release.');return adapter;}
+logging('adapter.js shimming edge.');adapter.browserShim=edgeShim;edgeShim.shimGetUserMedia(window);edgeShim.shimGetDisplayMedia(window);edgeShim.shimPeerConnection(window);edgeShim.shimReplaceTrack(window);commonShim.shimMaxMessageSize(window);commonShim.shimSendThrowTypeError(window);break;case'safari':if(!safariShim||!options.shimSafari){logging('Safari shim is not included in this adapter release.');return adapter;}
+logging('adapter.js shimming safari.');adapter.browserShim=safariShim;safariShim.shimRTCIceServerUrls(window);safariShim.shimCreateOfferLegacy(window);safariShim.shimCallbacksAPI(window);safariShim.shimLocalStreamsAPI(window);safariShim.shimRemoteStreamsAPI(window);safariShim.shimTrackEventTransceiver(window);safariShim.shimGetUserMedia(window);commonShim.shimRTCIceCandidate(window);commonShim.shimMaxMessageSize(window);commonShim.shimSendThrowTypeError(window);commonShim.removeAllowExtmapMixed(window);break;default:logging('Unsupported browser!');break;}
+return adapter;}},{"./chrome/chrome_shim":3,"./common_shim":6,"./edge/edge_shim":7,"./firefox/firefox_shim":11,"./safari/safari_shim":14,"./utils":15}],3:[function(require,module,exports){'use strict';Object.defineProperty(exports,"__esModule",{value:true});exports.shimGetDisplayMedia=exports.shimGetUserMedia=undefined;var _typeof=typeof Symbol==="function"&&typeof Symbol.iterator==="symbol"?function(obj){return typeof obj;}:function(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj;};var _getusermedia=require('./getusermedia');Object.defineProperty(exports,'shimGetUserMedia',{enumerable:true,get:function get(){return _getusermedia.shimGetUserMedia;}});var _getdisplaymedia=require('./getdisplaymedia');Object.defineProperty(exports,'shimGetDisplayMedia',{enumerable:true,get:function get(){return _getdisplaymedia.shimGetDisplayMedia;}});exports.shimMediaStream=shimMediaStream;exports.shimOnTrack=shimOnTrack;exports.shimGetSendersWithDtmf=shimGetSendersWithDtmf;exports.shimSenderReceiverGetStats=shimSenderReceiverGetStats;exports.shimAddTrackRemoveTrackWithNative=shimAddTrackRemoveTrackWithNative;exports.shimAddTrackRemoveTrack=shimAddTrackRemoveTrack;exports.shimPeerConnection=shimPeerConnection;exports.fixNegotiationNeeded=fixNegotiationNeeded;var _utils=require('../utils.js');var utils=_interopRequireWildcard(_utils);function _interopRequireWildcard(obj){if(obj&&obj.__esModule){return obj;}else{var newObj={};if(obj!=null){for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key))newObj[key]=obj[key];}}newObj.default=obj;return newObj;}}
+function walkStats(stats,base,resultSet){if(!base||resultSet.has(base.id)){return;}
+resultSet.set(base.id,base);Object.keys(base).forEach(function(name){if(name.endsWith('Id')){walkStats(stats,stats.get(base[name]),resultSet);}else if(name.endsWith('Ids')){base[name].forEach(function(id){walkStats(stats,stats.get(id),resultSet);});}});}
+function filterStats(result,track,outbound){var streamStatsType=outbound?'outbound-rtp':'inbound-rtp';var filteredResult=new Map();if(track===null){return filteredResult;}
+var trackStats=[];result.forEach(function(value){if(value.type==='track'&&value.trackIdentifier===track.id){trackStats.push(value);}});trackStats.forEach(function(trackStat){result.forEach(function(stats){if(stats.type===streamStatsType&&stats.trackId===trackStat.id){walkStats(result,stats,filteredResult);}});});return filteredResult;}
+function shimMediaStream(window){window.MediaStream=window.MediaStream||window.webkitMediaStream;}
+function shimOnTrack(window){if((typeof window==='undefined'?'undefined':_typeof(window))==='object'&&window.RTCPeerConnection&&!('ontrack'in window.RTCPeerConnection.prototype)){Object.defineProperty(window.RTCPeerConnection.prototype,'ontrack',{get:function get(){return this._ontrack;},set:function set(f){if(this._ontrack){this.removeEventListener('track',this._ontrack);}
+this.addEventListener('track',this._ontrack=f);},enumerable:true,configurable:true});var origSetRemoteDescription=window.RTCPeerConnection.prototype.setRemoteDescription;window.RTCPeerConnection.prototype.setRemoteDescription=function(){var _this=this;if(!this._ontrackpoly){this._ontrackpoly=function(e){e.stream.addEventListener('addtrack',function(te){var receiver=void 0;if(window.RTCPeerConnection.prototype.getReceivers){receiver=_this.getReceivers().find(function(r){return r.track&&r.track.id===te.track.id;});}else{receiver={track:te.track};}
+var event=new Event('track');event.track=te.track;event.receiver=receiver;event.transceiver={receiver:receiver};event.streams=[e.stream];_this.dispatchEvent(event);});e.stream.getTracks().forEach(function(track){var receiver=void 0;if(window.RTCPeerConnection.prototype.getReceivers){receiver=_this.getReceivers().find(function(r){return r.track&&r.track.id===track.id;});}else{receiver={track:track};}
+var event=new Event('track');event.track=track;event.receiver=receiver;event.transceiver={receiver:receiver};event.streams=[e.stream];_this.dispatchEvent(event);});};this.addEventListener('addstream',this._ontrackpoly);}
+return origSetRemoteDescription.apply(this,arguments);};}else{utils.wrapPeerConnectionEvent(window,'track',function(e){if(!e.transceiver){Object.defineProperty(e,'transceiver',{value:{receiver:e.receiver}});}
+return e;});}}
+function shimGetSendersWithDtmf(window){if((typeof window==='undefined'?'undefined':_typeof(window))==='object'&&window.RTCPeerConnection&&!('getSenders'in window.RTCPeerConnection.prototype)&&'createDTMFSender'in window.RTCPeerConnection.prototype){var shimSenderWithDtmf=function shimSenderWithDtmf(pc,track){return{track:track,get dtmf(){if(this._dtmf===undefined){if(track.kind==='audio'){this._dtmf=pc.createDTMFSender(track);}else{this._dtmf=null;}}
+return this._dtmf;},_pc:pc};};if(!window.RTCPeerConnection.prototype.getSenders){window.RTCPeerConnection.prototype.getSenders=function(){this._senders=this._senders||[];return this._senders.slice();};var origAddTrack=window.RTCPeerConnection.prototype.addTrack;window.RTCPeerConnection.prototype.addTrack=function(track,stream){var sender=origAddTrack.apply(this,arguments);if(!sender){sender=shimSenderWithDtmf(this,track);this._senders.push(sender);}
+return sender;};var origRemoveTrack=window.RTCPeerConnection.prototype.removeTrack;window.RTCPeerConnection.prototype.removeTrack=function(sender){origRemoveTrack.apply(this,arguments);var idx=this._senders.indexOf(sender);if(idx!==-1){this._senders.splice(idx,1);}};}
+var origAddStream=window.RTCPeerConnection.prototype.addStream;window.RTCPeerConnection.prototype.addStream=function(stream){var _this2=this;this._senders=this._senders||[];origAddStream.apply(this,[stream]);stream.getTracks().forEach(function(track){_this2._senders.push(shimSenderWithDtmf(_this2,track));});};var origRemoveStream=window.RTCPeerConnection.prototype.removeStream;window.RTCPeerConnection.prototype.removeStream=function(stream){var _this3=this;this._senders=this._senders||[];origRemoveStream.apply(this,[stream]);stream.getTracks().forEach(function(track){var sender=_this3._senders.find(function(s){return s.track===track;});if(sender){_this3._senders.splice(_this3._senders.indexOf(sender),1);}});};}else if((typeof window==='undefined'?'undefined':_typeof(window))==='object'&&window.RTCPeerConnection&&'getSenders'in window.RTCPeerConnection.prototype&&'createDTMFSender'in window.RTCPeerConnection.prototype&&window.RTCRtpSender&&!('dtmf'in window.RTCRtpSender.prototype)){var origGetSenders=window.RTCPeerConnection.prototype.getSenders;window.RTCPeerConnection.prototype.getSenders=function(){var _this4=this;var senders=origGetSenders.apply(this,[]);senders.forEach(function(sender){return sender._pc=_this4;});return senders;};Object.defineProperty(window.RTCRtpSender.prototype,'dtmf',{get:function get(){if(this._dtmf===undefined){if(this.track.kind==='audio'){this._dtmf=this._pc.createDTMFSender(this.track);}else{this._dtmf=null;}}
+return this._dtmf;}});}}
+function shimSenderReceiverGetStats(window){if(!((typeof window==='undefined'?'undefined':_typeof(window))==='object'&&window.RTCPeerConnection&&window.RTCRtpSender&&window.RTCRtpReceiver)){return;}
+if(!('getStats'in window.RTCRtpSender.prototype)){var origGetSenders=window.RTCPeerConnection.prototype.getSenders;if(origGetSenders){window.RTCPeerConnection.prototype.getSenders=function(){var _this5=this;var senders=origGetSenders.apply(this,[]);senders.forEach(function(sender){return sender._pc=_this5;});return senders;};}
+var origAddTrack=window.RTCPeerConnection.prototype.addTrack;if(origAddTrack){window.RTCPeerConnection.prototype.addTrack=function(){var sender=origAddTrack.apply(this,arguments);sender._pc=this;return sender;};}
+window.RTCRtpSender.prototype.getStats=function(){var sender=this;return this._pc.getStats().then(function(result){return(filterStats(result,sender.track,true));});};}
+if(!('getStats'in window.RTCRtpReceiver.prototype)){var origGetReceivers=window.RTCPeerConnection.prototype.getReceivers;if(origGetReceivers){window.RTCPeerConnection.prototype.getReceivers=function(){var _this6=this;var receivers=origGetReceivers.apply(this,[]);receivers.forEach(function(receiver){return receiver._pc=_this6;});return receivers;};}
+utils.wrapPeerConnectionEvent(window,'track',function(e){e.receiver._pc=e.srcElement;return e;});window.RTCRtpReceiver.prototype.getStats=function(){var receiver=this;return this._pc.getStats().then(function(result){return filterStats(result,receiver.track,false);});};}
+if(!('getStats'in window.RTCRtpSender.prototype&&'getStats'in window.RTCRtpReceiver.prototype)){return;}
+var origGetStats=window.RTCPeerConnection.prototype.getStats;window.RTCPeerConnection.prototype.getStats=function(){if(arguments.length>0&&arguments[0]instanceof window.MediaStreamTrack){var track=arguments[0];var sender=void 0;var receiver=void 0;var err=void 0;this.getSenders().forEach(function(s){if(s.track===track){if(sender){err=true;}else{sender=s;}}});this.getReceivers().forEach(function(r){if(r.track===track){if(receiver){err=true;}else{receiver=r;}}
+return r.track===track;});if(err||sender&&receiver){return Promise.reject(new DOMException('There are more than one sender or receiver for the track.','InvalidAccessError'));}else if(sender){return sender.getStats();}else if(receiver){return receiver.getStats();}
+return Promise.reject(new DOMException('There is no sender or receiver for the track.','InvalidAccessError'));}
+return origGetStats.apply(this,arguments);};}
+function shimAddTrackRemoveTrackWithNative(window){window.RTCPeerConnection.prototype.getLocalStreams=function(){var _this7=this;this._shimmedLocalStreams=this._shimmedLocalStreams||{};return Object.keys(this._shimmedLocalStreams).map(function(streamId){return _this7._shimmedLocalStreams[streamId][0];});};var origAddTrack=window.RTCPeerConnection.prototype.addTrack;window.RTCPeerConnection.prototype.addTrack=function(track,stream){if(!stream){return origAddTrack.apply(this,arguments);}
+this._shimmedLocalStreams=this._shimmedLocalStreams||{};var sender=origAddTrack.apply(this,arguments);if(!this._shimmedLocalStreams[stream.id]){this._shimmedLocalStreams[stream.id]=[stream,sender];}else if(this._shimmedLocalStreams[stream.id].indexOf(sender)===-1){this._shimmedLocalStreams[stream.id].push(sender);}
+return sender;};var origAddStream=window.RTCPeerConnection.prototype.addStream;window.RTCPeerConnection.prototype.addStream=function(stream){var _this8=this;this._shimmedLocalStreams=this._shimmedLocalStreams||{};stream.getTracks().forEach(function(track){var alreadyExists=_this8.getSenders().find(function(s){return s.track===track;});if(alreadyExists){throw new DOMException('Track already exists.','InvalidAccessError');}});var existingSenders=this.getSenders();origAddStream.apply(this,arguments);var newSenders=this.getSenders().filter(function(newSender){return existingSenders.indexOf(newSender)===-1;});this._shimmedLocalStreams[stream.id]=[stream].concat(newSenders);};var origRemoveStream=window.RTCPeerConnection.prototype.removeStream;window.RTCPeerConnection.prototype.removeStream=function(stream){this._shimmedLocalStreams=this._shimmedLocalStreams||{};delete this._shimmedLocalStreams[stream.id];return origRemoveStream.apply(this,arguments);};var origRemoveTrack=window.RTCPeerConnection.prototype.removeTrack;window.RTCPeerConnection.prototype.removeTrack=function(sender){var _this9=this;this._shimmedLocalStreams=this._shimmedLocalStreams||{};if(sender){Object.keys(this._shimmedLocalStreams).forEach(function(streamId){var idx=_this9._shimmedLocalStreams[streamId].indexOf(sender);if(idx!==-1){_this9._shimmedLocalStreams[streamId].splice(idx,1);}
+if(_this9._shimmedLocalStreams[streamId].length===1){delete _this9._shimmedLocalStreams[streamId];}});}
+return origRemoveTrack.apply(this,arguments);};}
+function shimAddTrackRemoveTrack(window){if(!window.RTCPeerConnection){return;}
+var browserDetails=utils.detectBrowser(window);if(window.RTCPeerConnection.prototype.addTrack&&browserDetails.version>=65){return shimAddTrackRemoveTrackWithNative(window);}
+var origGetLocalStreams=window.RTCPeerConnection.prototype.getLocalStreams;window.RTCPeerConnection.prototype.getLocalStreams=function(){var _this10=this;var nativeStreams=origGetLocalStreams.apply(this);this._reverseStreams=this._reverseStreams||{};return nativeStreams.map(function(stream){return _this10._reverseStreams[stream.id];});};var origAddStream=window.RTCPeerConnection.prototype.addStream;window.RTCPeerConnection.prototype.addStream=function(stream){var _this11=this;this._streams=this._streams||{};this._reverseStreams=this._reverseStreams||{};stream.getTracks().forEach(function(track){var alreadyExists=_this11.getSenders().find(function(s){return s.track===track;});if(alreadyExists){throw new DOMException('Track already exists.','InvalidAccessError');}});if(!this._reverseStreams[stream.id]){var newStream=new window.MediaStream(stream.getTracks());this._streams[stream.id]=newStream;this._reverseStreams[newStream.id]=stream;stream=newStream;}
+origAddStream.apply(this,[stream]);};var origRemoveStream=window.RTCPeerConnection.prototype.removeStream;window.RTCPeerConnection.prototype.removeStream=function(stream){this._streams=this._streams||{};this._reverseStreams=this._reverseStreams||{};origRemoveStream.apply(this,[this._streams[stream.id]||stream]);delete this._reverseStreams[this._streams[stream.id]?this._streams[stream.id].id:stream.id];delete this._streams[stream.id];};window.RTCPeerConnection.prototype.addTrack=function(track,stream){var _this12=this;if(this.signalingState==='closed'){throw new DOMException('The RTCPeerConnection\'s signalingState is \'closed\'.','InvalidStateError');}
+var streams=[].slice.call(arguments,1);if(streams.length!==1||!streams[0].getTracks().find(function(t){return t===track;})){throw new DOMException('The adapter.js addTrack polyfill only supports a single '+' stream which is associated with the specified track.','NotSupportedError');}
+var alreadyExists=this.getSenders().find(function(s){return s.track===track;});if(alreadyExists){throw new DOMException('Track already exists.','InvalidAccessError');}
+this._streams=this._streams||{};this._reverseStreams=this._reverseStreams||{};var oldStream=this._streams[stream.id];if(oldStream){oldStream.addTrack(track);Promise.resolve().then(function(){_this12.dispatchEvent(new Event('negotiationneeded'));});}else{var newStream=new window.MediaStream([track]);this._streams[stream.id]=newStream;this._reverseStreams[newStream.id]=stream;this.addStream(newStream);}
+return this.getSenders().find(function(s){return s.track===track;});};function replaceInternalStreamId(pc,description){var sdp=description.sdp;Object.keys(pc._reverseStreams||[]).forEach(function(internalId){var externalStream=pc._reverseStreams[internalId];var internalStream=pc._streams[externalStream.id];sdp=sdp.replace(new RegExp(internalStream.id,'g'),externalStream.id);});return new RTCSessionDescription({type:description.type,sdp:sdp});}
+function replaceExternalStreamId(pc,description){var sdp=description.sdp;Object.keys(pc._reverseStreams||[]).forEach(function(internalId){var externalStream=pc._reverseStreams[internalId];var internalStream=pc._streams[externalStream.id];sdp=sdp.replace(new RegExp(externalStream.id,'g'),internalStream.id);});return new RTCSessionDescription({type:description.type,sdp:sdp});}
+['createOffer','createAnswer'].forEach(function(method){var nativeMethod=window.RTCPeerConnection.prototype[method];window.RTCPeerConnection.prototype[method]=function(){var _this13=this;var args=arguments;var isLegacyCall=arguments.length&&typeof arguments[0]==='function';if(isLegacyCall){return nativeMethod.apply(this,[function(description){var desc=replaceInternalStreamId(_this13,description);args[0].apply(null,[desc]);},function(err){if(args[1]){args[1].apply(null,err);}},arguments[2]]);}
+return nativeMethod.apply(this,arguments).then(function(description){return replaceInternalStreamId(_this13,description);});};});var origSetLocalDescription=window.RTCPeerConnection.prototype.setLocalDescription;window.RTCPeerConnection.prototype.setLocalDescription=function(){if(!arguments.length||!arguments[0].type){return origSetLocalDescription.apply(this,arguments);}
+arguments[0]=replaceExternalStreamId(this,arguments[0]);return origSetLocalDescription.apply(this,arguments);};var origLocalDescription=Object.getOwnPropertyDescriptor(window.RTCPeerConnection.prototype,'localDescription');Object.defineProperty(window.RTCPeerConnection.prototype,'localDescription',{get:function get(){var description=origLocalDescription.get.apply(this);if(description.type===''){return description;}
+return replaceInternalStreamId(this,description);}});window.RTCPeerConnection.prototype.removeTrack=function(sender){var _this14=this;if(this.signalingState==='closed'){throw new DOMException('The RTCPeerConnection\'s signalingState is \'closed\'.','InvalidStateError');}
+if(!sender._pc){throw new DOMException('Argument 1 of RTCPeerConnection.removeTrack '+'does not implement interface RTCRtpSender.','TypeError');}
+var isLocal=sender._pc===this;if(!isLocal){throw new DOMException('Sender was not created by this connection.','InvalidAccessError');}
+this._streams=this._streams||{};var stream=void 0;Object.keys(this._streams).forEach(function(streamid){var hasTrack=_this14._streams[streamid].getTracks().find(function(track){return sender.track===track;});if(hasTrack){stream=_this14._streams[streamid];}});if(stream){if(stream.getTracks().length===1){this.removeStream(this._reverseStreams[stream.id]);}else{stream.removeTrack(sender.track);}
+this.dispatchEvent(new Event('negotiationneeded'));}};}
+function shimPeerConnection(window){if(!window.RTCPeerConnection&&window.webkitRTCPeerConnection){window.RTCPeerConnection=window.webkitRTCPeerConnection;}
+if(!window.RTCPeerConnection){return;}
+var origGetStats=window.RTCPeerConnection.prototype.getStats;window.RTCPeerConnection.prototype.getStats=function(selector,successCallback,errorCallback){var _this15=this;var args=arguments;if(arguments.length>0&&typeof selector==='function'){return origGetStats.apply(this,arguments);}
+if(origGetStats.length===0&&(arguments.length===0||typeof arguments[0]!=='function')){return origGetStats.apply(this,[]);}
+var fixChromeStats_=function fixChromeStats_(response){var standardReport={};var reports=response.result();reports.forEach(function(report){var standardStats={id:report.id,timestamp:report.timestamp,type:{localcandidate:'local-candidate',remotecandidate:'remote-candidate'}[report.type]||report.type};report.names().forEach(function(name){standardStats[name]=report.stat(name);});standardReport[standardStats.id]=standardStats;});return standardReport;};var makeMapStats=function makeMapStats(stats){return new Map(Object.keys(stats).map(function(key){return[key,stats[key]];}));};if(arguments.length>=2){var successCallbackWrapper_=function successCallbackWrapper_(response){args[1](makeMapStats(fixChromeStats_(response)));};return origGetStats.apply(this,[successCallbackWrapper_,arguments[0]]);}
+return new Promise(function(resolve,reject){origGetStats.apply(_this15,[function(response){resolve(makeMapStats(fixChromeStats_(response)));},reject]);}).then(successCallback,errorCallback);};['setLocalDescription','setRemoteDescription','addIceCandidate'].forEach(function(method){var nativeMethod=window.RTCPeerConnection.prototype[method];window.RTCPeerConnection.prototype[method]=function(){arguments[0]=new(method==='addIceCandidate'?window.RTCIceCandidate:window.RTCSessionDescription)(arguments[0]);return nativeMethod.apply(this,arguments);};});var nativeAddIceCandidate=window.RTCPeerConnection.prototype.addIceCandidate;window.RTCPeerConnection.prototype.addIceCandidate=function(){if(!arguments[0]){if(arguments[1]){arguments[1].apply(null);}
+return Promise.resolve();}
+return nativeAddIceCandidate.apply(this,arguments);};}
+function fixNegotiationNeeded(window){utils.wrapPeerConnectionEvent(window,'negotiationneeded',function(e){var pc=e.target;if(pc.signalingState!=='stable'){return;}
+return e;});}},{"../utils.js":15,"./getdisplaymedia":4,"./getusermedia":5}],4:[function(require,module,exports){'use strict';Object.defineProperty(exports,"__esModule",{value:true});exports.shimGetDisplayMedia=shimGetDisplayMedia;function shimGetDisplayMedia(window,getSourceId){if(window.navigator.mediaDevices&&'getDisplayMedia'in window.navigator.mediaDevices){return;}
+if(!window.navigator.mediaDevices){return;}
+if(typeof getSourceId!=='function'){console.error('shimGetDisplayMedia: getSourceId argument is not '+'a function');return;}
+window.navigator.mediaDevices.getDisplayMedia=function(constraints){return getSourceId(constraints).then(function(sourceId){var widthSpecified=constraints.video&&constraints.video.width;var heightSpecified=constraints.video&&constraints.video.height;var frameRateSpecified=constraints.video&&constraints.video.frameRate;constraints.video={mandatory:{chromeMediaSource:'desktop',chromeMediaSourceId:sourceId,maxFrameRate:frameRateSpecified||3}};if(widthSpecified){constraints.video.mandatory.maxWidth=widthSpecified;}
+if(heightSpecified){constraints.video.mandatory.maxHeight=heightSpecified;}
+return window.navigator.mediaDevices.getUserMedia(constraints);});};}},{}],5:[function(require,module,exports){'use strict';Object.defineProperty(exports,"__esModule",{value:true});var _typeof=typeof Symbol==="function"&&typeof Symbol.iterator==="symbol"?function(obj){return typeof obj;}:function(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj;};exports.shimGetUserMedia=shimGetUserMedia;var _utils=require('../utils.js');var utils=_interopRequireWildcard(_utils);function _interopRequireWildcard(obj){if(obj&&obj.__esModule){return obj;}else{var newObj={};if(obj!=null){for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key))newObj[key]=obj[key];}}newObj.default=obj;return newObj;}}
+var logging=utils.log;function shimGetUserMedia(window){var navigator=window&&window.navigator;if(!navigator.mediaDevices){return;}
+var browserDetails=utils.detectBrowser(window);var constraintsToChrome_=function constraintsToChrome_(c){if((typeof c==='undefined'?'undefined':_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 oldname_(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;};var shimConstraints_=function shimConstraints_(constraints,func){if(browserDetails.version>=61){return func(constraints);}
+constraints=JSON.parse(JSON.stringify(constraints));if(constraints&&_typeof(constraints.audio)==='object'){var remap=function remap(obj,a,b){if(a in obj&&!(b in obj)){obj[b]=obj[a];delete obj[a];}};constraints=JSON.parse(JSON.stringify(constraints));remap(constraints.audio,'autoGainControl','googAutoGainControl');remap(constraints.audio,'noiseSuppression','googNoiseSuppression');constraints.audio=constraintsToChrome_(constraints.audio);}
+if(constraints&&_typeof(constraints.video)==='object'){var face=constraints.video.facingMode;face=face&&((typeof face==='undefined'?'undefined':_typeof(face))==='object'?face:{ideal:face});var getSupportedFacingModeLies=browserDetails.version<66;if(face&&(face.exact==='user'||face.exact==='environment'||face.ideal==='user'||face.ideal==='environment')&&!(navigator.mediaDevices.getSupportedConstraints&&navigator.mediaDevices.getSupportedConstraints().facingMode&&!getSupportedFacingModeLies)){delete constraints.video.facingMode;var matches=void 0;if(face.exact==='environment'||face.ideal==='environment'){matches=['back','rear'];}else if(face.exact==='user'||face.ideal==='user'){matches=['front'];}
+if(matches){return navigator.mediaDevices.enumerateDevices().then(function(devices){devices=devices.filter(function(d){return d.kind==='videoinput';});var dev=devices.find(function(d){return matches.some(function(match){return d.label.toLowerCase().includes(match);});});if(!dev&&devices.length&&matches.includes('back')){dev=devices[devices.length-1];}
+if(dev){constraints.video.deviceId=face.exact?{exact:dev.deviceId}:{ideal:dev.deviceId};}
+constraints.video=constraintsToChrome_(constraints.video);logging('chrome: '+JSON.stringify(constraints));return func(constraints);});}}
+constraints.video=constraintsToChrome_(constraints.video);}
+logging('chrome: '+JSON.stringify(constraints));return func(constraints);};var shimError_=function shimError_(e){if(browserDetails.version>=64){return e;}
+return{name:{PermissionDeniedError:'NotAllowedError',PermissionDismissedError:'NotAllowedError',InvalidStateError:'NotAllowedError',DevicesNotFoundError:'NotFoundError',ConstraintNotSatisfiedError:'OverconstrainedError',TrackStartError:'NotReadableError',MediaDeviceFailedDueToShutdown:'NotAllowedError',MediaDeviceKillSwitchOn:'NotAllowedError',TabCaptureError:'AbortError',ScreenCaptureError:'AbortError',DeviceCaptureError:'AbortError'}[e.name]||e.name,message:e.message,constraint:e.constraint||e.constraintName,toString:function toString(){return this.name+(this.message&&': ')+this.message;}};};var getUserMedia_=function getUserMedia_(constraints,onSuccess,onError){shimConstraints_(constraints,function(c){navigator.webkitGetUserMedia(c,onSuccess,function(e){if(onError){onError(shimError_(e));}});});};navigator.getUserMedia=getUserMedia_.bind(navigator);var origGetUserMedia=navigator.mediaDevices.getUserMedia.bind(navigator.mediaDevices);navigator.mediaDevices.getUserMedia=function(cs){return shimConstraints_(cs,function(c){return origGetUserMedia(c).then(function(stream){if(c.audio&&!stream.getAudioTracks().length||c.video&&!stream.getVideoTracks().length){stream.getTracks().forEach(function(track){track.stop();});throw new DOMException('','NotFoundError');}
+return stream;},function(e){return Promise.reject(shimError_(e));});});};}},{"../utils.js":15}],6:[function(require,module,exports){'use strict';Object.defineProperty(exports,"__esModule",{value:true});var _typeof=typeof Symbol==="function"&&typeof Symbol.iterator==="symbol"?function(obj){return typeof obj;}:function(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj;};exports.shimRTCIceCandidate=shimRTCIceCandidate;exports.shimMaxMessageSize=shimMaxMessageSize;exports.shimSendThrowTypeError=shimSendThrowTypeError;exports.shimConnectionState=shimConnectionState;exports.removeAllowExtmapMixed=removeAllowExtmapMixed;var _sdp=require('sdp');var _sdp2=_interopRequireDefault(_sdp);var _utils=require('./utils');var utils=_interopRequireWildcard(_utils);function _interopRequireWildcard(obj){if(obj&&obj.__esModule){return obj;}else{var newObj={};if(obj!=null){for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key))newObj[key]=obj[key];}}newObj.default=obj;return newObj;}}
+function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj};}
+function shimRTCIceCandidate(window){if(!window.RTCIceCandidate||window.RTCIceCandidate&&'foundation'in window.RTCIceCandidate.prototype){return;}
+var NativeRTCIceCandidate=window.RTCIceCandidate;window.RTCIceCandidate=function(args){if((typeof args==='undefined'?'undefined':_typeof(args))==='object'&&args.candidate&&args.candidate.indexOf('a=')===0){args=JSON.parse(JSON.stringify(args));args.candidate=args.candidate.substr(2);}
+if(args.candidate&&args.candidate.length){var nativeCandidate=new NativeRTCIceCandidate(args);var parsedCandidate=_sdp2.default.parseCandidate(args.candidate);var augmentedCandidate=Object.assign(nativeCandidate,parsedCandidate);augmentedCandidate.toJSON=function(){return{candidate:augmentedCandidate.candidate,sdpMid:augmentedCandidate.sdpMid,sdpMLineIndex:augmentedCandidate.sdpMLineIndex,usernameFragment:augmentedCandidate.usernameFragment};};return augmentedCandidate;}
+return new NativeRTCIceCandidate(args);};window.RTCIceCandidate.prototype=NativeRTCIceCandidate.prototype;utils.wrapPeerConnectionEvent(window,'icecandidate',function(e){if(e.candidate){Object.defineProperty(e,'candidate',{value:new window.RTCIceCandidate(e.candidate),writable:'false'});}
+return e;});}
+function shimMaxMessageSize(window){if(window.RTCSctpTransport||!window.RTCPeerConnection){return;}
+var browserDetails=utils.detectBrowser(window);if(!('sctp'in window.RTCPeerConnection.prototype)){Object.defineProperty(window.RTCPeerConnection.prototype,'sctp',{get:function get(){return typeof this._sctp==='undefined'?null:this._sctp;}});}
+var sctpInDescription=function sctpInDescription(description){var sections=_sdp2.default.splitSections(description.sdp);sections.shift();return sections.some(function(mediaSection){var mLine=_sdp2.default.parseMLine(mediaSection);return mLine&&mLine.kind==='application'&&mLine.protocol.indexOf('SCTP')!==-1;});};var getRemoteFirefoxVersion=function getRemoteFirefoxVersion(description){var match=description.sdp.match(/mozilla...THIS_IS_SDPARTA-(\d+)/);if(match===null||match.length<2){return-1;}
+var version=parseInt(match[1],10);return version!==version?-1:version;};var getCanSendMaxMessageSize=function getCanSendMaxMessageSize(remoteIsFirefox){var canSendMaxMessageSize=65536;if(browserDetails.browser==='firefox'){if(browserDetails.version<57){if(remoteIsFirefox===-1){canSendMaxMessageSize=16384;}else{canSendMaxMessageSize=2147483637;}}else if(browserDetails.version<60){canSendMaxMessageSize=browserDetails.version===57?65535:65536;}else{canSendMaxMessageSize=2147483637;}}
+return canSendMaxMessageSize;};var getMaxMessageSize=function getMaxMessageSize(description,remoteIsFirefox){var maxMessageSize=65536;if(browserDetails.browser==='firefox'&&browserDetails.version===57){maxMessageSize=65535;}
+var match=_sdp2.default.matchPrefix(description.sdp,'a=max-message-size:');if(match.length>0){maxMessageSize=parseInt(match[0].substr(19),10);}else if(browserDetails.browser==='firefox'&&remoteIsFirefox!==-1){maxMessageSize=2147483637;}
+return maxMessageSize;};var origSetRemoteDescription=window.RTCPeerConnection.prototype.setRemoteDescription;window.RTCPeerConnection.prototype.setRemoteDescription=function(){this._sctp=null;if(sctpInDescription(arguments[0])){var isFirefox=getRemoteFirefoxVersion(arguments[0]);var canSendMMS=getCanSendMaxMessageSize(isFirefox);var remoteMMS=getMaxMessageSize(arguments[0],isFirefox);var maxMessageSize=void 0;if(canSendMMS===0&&remoteMMS===0){maxMessageSize=Number.POSITIVE_INFINITY;}else if(canSendMMS===0||remoteMMS===0){maxMessageSize=Math.max(canSendMMS,remoteMMS);}else{maxMessageSize=Math.min(canSendMMS,remoteMMS);}
+var sctp={};Object.defineProperty(sctp,'maxMessageSize',{get:function get(){return maxMessageSize;}});this._sctp=sctp;}
+return origSetRemoteDescription.apply(this,arguments);};}
+function shimSendThrowTypeError(window){if(!(window.RTCPeerConnection&&'createDataChannel'in window.RTCPeerConnection.prototype)){return;}
+function wrapDcSend(dc,pc){var origDataChannelSend=dc.send;dc.send=function(){var data=arguments[0];var length=data.length||data.size||data.byteLength;if(dc.readyState==='open'&&pc.sctp&&length>pc.sctp.maxMessageSize){throw new TypeError('Message too large (can send a maximum of '+pc.sctp.maxMessageSize+' bytes)');}
+return origDataChannelSend.apply(dc,arguments);};}
+var origCreateDataChannel=window.RTCPeerConnection.prototype.createDataChannel;window.RTCPeerConnection.prototype.createDataChannel=function(){var dataChannel=origCreateDataChannel.apply(this,arguments);wrapDcSend(dataChannel,this);return dataChannel;};utils.wrapPeerConnectionEvent(window,'datachannel',function(e){wrapDcSend(e.channel,e.target);return e;});}
+function shimConnectionState(window){if(!window.RTCPeerConnection||'connectionState'in window.RTCPeerConnection.prototype){return;}
+var proto=window.RTCPeerConnection.prototype;Object.defineProperty(proto,'connectionState',{get:function get(){return{completed:'connected',checking:'connecting'}[this.iceConnectionState]||this.iceConnectionState;},enumerable:true,configurable:true});Object.defineProperty(proto,'onconnectionstatechange',{get:function get(){return this._onconnectionstatechange||null;},set:function set(cb){if(this._onconnectionstatechange){this.removeEventListener('connectionstatechange',this._onconnectionstatechange);delete this._onconnectionstatechange;}
+if(cb){this.addEventListener('connectionstatechange',this._onconnectionstatechange=cb);}},enumerable:true,configurable:true});['setLocalDescription','setRemoteDescription'].forEach(function(method){var origMethod=proto[method];proto[method]=function(){if(!this._connectionstatechangepoly){this._connectionstatechangepoly=function(e){var pc=e.target;if(pc._lastConnectionState!==pc.connectionState){pc._lastConnectionState=pc.connectionState;var newEvent=new Event('connectionstatechange',e);pc.dispatchEvent(newEvent);}
+return e;};this.addEventListener('iceconnectionstatechange',this._connectionstatechangepoly);}
+return origMethod.apply(this,arguments);};});}
+function removeAllowExtmapMixed(window){if(!window.RTCPeerConnection){return;}
+var browserDetails=utils.detectBrowser(window);if(browserDetails.browser==='chrome'&&browserDetails.version>=71){return;}
+var nativeSRD=window.RTCPeerConnection.prototype.setRemoteDescription;window.RTCPeerConnection.prototype.setRemoteDescription=function(desc){if(desc&&desc.sdp&&desc.sdp.indexOf('\na=extmap-allow-mixed')!==-1){desc.sdp=desc.sdp.split('\n').filter(function(line){return line.trim()!=='a=extmap-allow-mixed';}).join('\n');}
+return nativeSRD.apply(this,arguments);};}},{"./utils":15,"sdp":17}],7:[function(require,module,exports){'use strict';Object.defineProperty(exports,"__esModule",{value:true});exports.shimGetDisplayMedia=exports.shimGetUserMedia=undefined;var _getusermedia=require('./getusermedia');Object.defineProperty(exports,'shimGetUserMedia',{enumerable:true,get:function get(){return _getusermedia.shimGetUserMedia;}});var _getdisplaymedia=require('./getdisplaymedia');Object.defineProperty(exports,'shimGetDisplayMedia',{enumerable:true,get:function get(){return _getdisplaymedia.shimGetDisplayMedia;}});exports.shimPeerConnection=shimPeerConnection;exports.shimReplaceTrack=shimReplaceTrack;var _utils=require('../utils');var utils=_interopRequireWildcard(_utils);var _filtericeservers=require('./filtericeservers');var _rtcpeerconnectionShim=require('rtcpeerconnection-shim');var _rtcpeerconnectionShim2=_interopRequireDefault(_rtcpeerconnectionShim);function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj};}
+function _interopRequireWildcard(obj){if(obj&&obj.__esModule){return obj;}else{var newObj={};if(obj!=null){for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key))newObj[key]=obj[key];}}newObj.default=obj;return newObj;}}
+function shimPeerConnection(window){var browserDetails=utils.detectBrowser(window);if(window.RTCIceGatherer){if(!window.RTCIceCandidate){window.RTCIceCandidate=function(args){return args;};}
+if(!window.RTCSessionDescription){window.RTCSessionDescription=function(args){return args;};}
+if(browserDetails.version<15025){var origMSTEnabled=Object.getOwnPropertyDescriptor(window.MediaStreamTrack.prototype,'enabled');Object.defineProperty(window.MediaStreamTrack.prototype,'enabled',{set:function set(value){origMSTEnabled.set.call(this,value);var ev=new Event('enabled');ev.enabled=value;this.dispatchEvent(ev);}});}}
+if(window.RTCRtpSender&&!('dtmf'in window.RTCRtpSender.prototype)){Object.defineProperty(window.RTCRtpSender.prototype,'dtmf',{get:function get(){if(this._dtmf===undefined){if(this.track.kind==='audio'){this._dtmf=new window.RTCDtmfSender(this);}else if(this.track.kind==='video'){this._dtmf=null;}}
+return this._dtmf;}});}
+if(window.RTCDtmfSender&&!window.RTCDTMFSender){window.RTCDTMFSender=window.RTCDtmfSender;}
+var RTCPeerConnectionShim=(0,_rtcpeerconnectionShim2.default)(window,browserDetails.version);window.RTCPeerConnection=function(config){if(config&&config.iceServers){config.iceServers=(0,_filtericeservers.filterIceServers)(config.iceServers,browserDetails.version);utils.log('ICE servers after filtering:',config.iceServers);}
+return new RTCPeerConnectionShim(config);};window.RTCPeerConnection.prototype=RTCPeerConnectionShim.prototype;}
+function shimReplaceTrack(window){if(window.RTCRtpSender&&!('replaceTrack'in window.RTCRtpSender.prototype)){window.RTCRtpSender.prototype.replaceTrack=window.RTCRtpSender.prototype.setTrack;}}},{"../utils":15,"./filtericeservers":8,"./getdisplaymedia":9,"./getusermedia":10,"rtcpeerconnection-shim":16}],8:[function(require,module,exports){'use strict';Object.defineProperty(exports,"__esModule",{value:true});exports.filterIceServers=filterIceServers;var _utils=require('../utils');var utils=_interopRequireWildcard(_utils);function _interopRequireWildcard(obj){if(obj&&obj.__esModule){return obj;}else{var newObj={};if(obj!=null){for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key))newObj[key]=obj[key];}}newObj.default=obj;return newObj;}}
+function filterIceServers(iceServers,edgeVersion){var hasTurn=false;iceServers=JSON.parse(JSON.stringify(iceServers));return iceServers.filter(function(server){if(server&&(server.urls||server.url)){var urls=server.urls||server.url;if(server.url&&!server.urls){utils.deprecated('RTCIceServer.url','RTCIceServer.urls');}
+var isString=typeof urls==='string';if(isString){urls=[urls];}
+urls=urls.filter(function(url){if(url.indexOf('stun:')===0){return false;}
+var validTurn=url.startsWith('turn')&&!url.startsWith('turn:[')&&url.includes('transport=udp');if(validTurn&&!hasTurn){hasTurn=true;return true;}
+return validTurn&&!hasTurn;});delete server.url;server.urls=isString?urls[0]:urls;return!!urls.length;}});}},{"../utils":15}],9:[function(require,module,exports){'use strict';Object.defineProperty(exports,"__esModule",{value:true});exports.shimGetDisplayMedia=shimGetDisplayMedia;function shimGetDisplayMedia(window){if(!('getDisplayMedia'in window.navigator)){return;}
+if(!window.navigator.mediaDevices){return;}
+if(window.navigator.mediaDevices&&'getDisplayMedia'in window.navigator.mediaDevices){return;}
+window.navigator.mediaDevices.getDisplayMedia=window.navigator.getDisplayMedia.bind(window.navigator.mediaDevices);}},{}],10:[function(require,module,exports){'use strict';Object.defineProperty(exports,"__esModule",{value:true});exports.shimGetUserMedia=shimGetUserMedia;function shimGetUserMedia(window){var navigator=window&&window.navigator;var shimError_=function shimError_(e){return{name:{PermissionDeniedError:'NotAllowedError'}[e.name]||e.name,message:e.message,constraint:e.constraint,toString:function toString(){return this.name;}};};var origGetUserMedia=navigator.mediaDevices.getUserMedia.bind(navigator.mediaDevices);navigator.mediaDevices.getUserMedia=function(c){return origGetUserMedia(c).catch(function(e){return Promise.reject(shimError_(e));});};}},{}],11:[function(require,module,exports){'use strict';Object.defineProperty(exports,"__esModule",{value:true});exports.shimGetDisplayMedia=exports.shimGetUserMedia=undefined;var _typeof=typeof Symbol==="function"&&typeof Symbol.iterator==="symbol"?function(obj){return typeof obj;}:function(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj;};var _getusermedia=require('./getusermedia');Object.defineProperty(exports,'shimGetUserMedia',{enumerable:true,get:function get(){return _getusermedia.shimGetUserMedia;}});var _getdisplaymedia=require('./getdisplaymedia');Object.defineProperty(exports,'shimGetDisplayMedia',{enumerable:true,get:function get(){return _getdisplaymedia.shimGetDisplayMedia;}});exports.shimOnTrack=shimOnTrack;exports.shimPeerConnection=shimPeerConnection;exports.shimSenderGetStats=shimSenderGetStats;exports.shimReceiverGetStats=shimReceiverGetStats;exports.shimRemoveStream=shimRemoveStream;exports.shimRTCDataChannel=shimRTCDataChannel;var _utils=require('../utils');var utils=_interopRequireWildcard(_utils);function _interopRequireWildcard(obj){if(obj&&obj.__esModule){return obj;}else{var newObj={};if(obj!=null){for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key))newObj[key]=obj[key];}}newObj.default=obj;return newObj;}}
+function shimOnTrack(window){if((typeof window==='undefined'?'undefined':_typeof(window))==='object'&&window.RTCTrackEvent&&'receiver'in window.RTCTrackEvent.prototype&&!('transceiver'in window.RTCTrackEvent.prototype)){Object.defineProperty(window.RTCTrackEvent.prototype,'transceiver',{get:function get(){return{receiver:this.receiver};}});}}
+function shimPeerConnection(window){var browserDetails=utils.detectBrowser(window);if((typeof window==='undefined'?'undefined':_typeof(window))!=='object'||!(window.RTCPeerConnection||window.mozRTCPeerConnection)){return;}
+if(!window.RTCPeerConnection&&window.mozRTCPeerConnection){window.RTCPeerConnection=window.mozRTCPeerConnection;}
+['setLocalDescription','setRemoteDescription','addIceCandidate'].forEach(function(method){var nativeMethod=window.RTCPeerConnection.prototype[method];window.RTCPeerConnection.prototype[method]=function(){arguments[0]=new(method==='addIceCandidate'?window.RTCIceCandidate:window.RTCSessionDescription)(arguments[0]);return nativeMethod.apply(this,arguments);};});var nativeAddIceCandidate=window.RTCPeerConnection.prototype.addIceCandidate;window.RTCPeerConnection.prototype.addIceCandidate=function(){if(!arguments[0]){if(arguments[1]){arguments[1].apply(null);}
+return Promise.resolve();}
+return nativeAddIceCandidate.apply(this,arguments);};var modernStatsTypes={inboundrtp:'inbound-rtp',outboundrtp:'outbound-rtp',candidatepair:'candidate-pair',localcandidate:'local-candidate',remotecandidate:'remote-candidate'};var nativeGetStats=window.RTCPeerConnection.prototype.getStats;window.RTCPeerConnection.prototype.getStats=function(selector,onSucc,onErr){return nativeGetStats.apply(this,[selector||null]).then(function(stats){if(browserDetails.version<53&&!onSucc){try{stats.forEach(function(stat){stat.type=modernStatsTypes[stat.type]||stat.type;});}catch(e){if(e.name!=='TypeError'){throw e;}
+stats.forEach(function(stat,i){stats.set(i,Object.assign({},stat,{type:modernStatsTypes[stat.type]||stat.type}));});}}
+return stats;}).then(onSucc,onErr);};}
+function shimSenderGetStats(window){if(!((typeof window==='undefined'?'undefined':_typeof(window))==='object'&&window.RTCPeerConnection&&window.RTCRtpSender)){return;}
+if(window.RTCRtpSender&&'getStats'in window.RTCRtpSender.prototype){return;}
+var origGetSenders=window.RTCPeerConnection.prototype.getSenders;if(origGetSenders){window.RTCPeerConnection.prototype.getSenders=function(){var _this=this;var senders=origGetSenders.apply(this,[]);senders.forEach(function(sender){return sender._pc=_this;});return senders;};}
+var origAddTrack=window.RTCPeerConnection.prototype.addTrack;if(origAddTrack){window.RTCPeerConnection.prototype.addTrack=function(){var sender=origAddTrack.apply(this,arguments);sender._pc=this;return sender;};}
+window.RTCRtpSender.prototype.getStats=function(){return this.track?this._pc.getStats(this.track):Promise.resolve(new Map());};}
+function shimReceiverGetStats(window){if(!((typeof window==='undefined'?'undefined':_typeof(window))==='object'&&window.RTCPeerConnection&&window.RTCRtpSender)){return;}
+if(window.RTCRtpSender&&'getStats'in window.RTCRtpReceiver.prototype){return;}
+var origGetReceivers=window.RTCPeerConnection.prototype.getReceivers;if(origGetReceivers){window.RTCPeerConnection.prototype.getReceivers=function(){var _this2=this;var receivers=origGetReceivers.apply(this,[]);receivers.forEach(function(receiver){return receiver._pc=_this2;});return receivers;};}
+utils.wrapPeerConnectionEvent(window,'track',function(e){e.receiver._pc=e.srcElement;return e;});window.RTCRtpReceiver.prototype.getStats=function(){return this._pc.getStats(this.track);};}
+function shimRemoveStream(window){if(!window.RTCPeerConnection||'removeStream'in window.RTCPeerConnection.prototype){return;}
+window.RTCPeerConnection.prototype.removeStream=function(stream){var _this3=this;utils.deprecated('removeStream','removeTrack');this.getSenders().forEach(function(sender){if(sender.track&&stream.getTracks().includes(sender.track)){_this3.removeTrack(sender);}});};}
+function shimRTCDataChannel(window){if(window.DataChannel&&!window.RTCDataChannel){window.RTCDataChannel=window.DataChannel;}}},{"../utils":15,"./getdisplaymedia":12,"./getusermedia":13}],12:[function(require,module,exports){'use strict';Object.defineProperty(exports,"__esModule",{value:true});exports.shimGetDisplayMedia=shimGetDisplayMedia;function shimGetDisplayMedia(window,preferredMediaSource){if(window.navigator.mediaDevices&&'getDisplayMedia'in window.navigator.mediaDevices){return;}
+if(!window.navigator.mediaDevices){return;}
+window.navigator.mediaDevices.getDisplayMedia=function(constraints){if(!(constraints&&constraints.video)){var err=new DOMException('getDisplayMedia without video '+'constraints is undefined');err.name='NotFoundError';err.code=8;return Promise.reject(err);}
+if(constraints.video===true){constraints.video={mediaSource:preferredMediaSource};}else{constraints.video.mediaSource=preferredMediaSource;}
+return window.navigator.mediaDevices.getUserMedia(constraints);};}},{}],13:[function(require,module,exports){'use strict';Object.defineProperty(exports,"__esModule",{value:true});var _typeof=typeof Symbol==="function"&&typeof Symbol.iterator==="symbol"?function(obj){return typeof obj;}:function(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj;};exports.shimGetUserMedia=shimGetUserMedia;var _utils=require('../utils');var utils=_interopRequireWildcard(_utils);function _interopRequireWildcard(obj){if(obj&&obj.__esModule){return obj;}else{var newObj={};if(obj!=null){for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key))newObj[key]=obj[key];}}newObj.default=obj;return newObj;}}
+function shimGetUserMedia(window){var browserDetails=utils.detectBrowser(window);var navigator=window&&window.navigator;var MediaStreamTrack=window&&window.MediaStreamTrack;navigator.getUserMedia=function(constraints,onSuccess,onError){utils.deprecated('navigator.getUserMedia','navigator.mediaDevices.getUserMedia');navigator.mediaDevices.getUserMedia(constraints).then(onSuccess,onError);};if(!(browserDetails.version>55&&'autoGainControl'in navigator.mediaDevices.getSupportedConstraints())){var remap=function remap(obj,a,b){if(a in obj&&!(b in obj)){obj[b]=obj[a];delete obj[a];}};var nativeGetUserMedia=navigator.mediaDevices.getUserMedia.bind(navigator.mediaDevices);navigator.mediaDevices.getUserMedia=function(c){if((typeof c==='undefined'?'undefined':_typeof(c))==='object'&&_typeof(c.audio)==='object'){c=JSON.parse(JSON.stringify(c));remap(c.audio,'autoGainControl','mozAutoGainControl');remap(c.audio,'noiseSuppression','mozNoiseSuppression');}
+return nativeGetUserMedia(c);};if(MediaStreamTrack&&MediaStreamTrack.prototype.getSettings){var nativeGetSettings=MediaStreamTrack.prototype.getSettings;MediaStreamTrack.prototype.getSettings=function(){var obj=nativeGetSettings.apply(this,arguments);remap(obj,'mozAutoGainControl','autoGainControl');remap(obj,'mozNoiseSuppression','noiseSuppression');return obj;};}
+if(MediaStreamTrack&&MediaStreamTrack.prototype.applyConstraints){var nativeApplyConstraints=MediaStreamTrack.prototype.applyConstraints;MediaStreamTrack.prototype.applyConstraints=function(c){if(this.kind==='audio'&&(typeof c==='undefined'?'undefined':_typeof(c))==='object'){c=JSON.parse(JSON.stringify(c));remap(c,'autoGainControl','mozAutoGainControl');remap(c,'noiseSuppression','mozNoiseSuppression');}
+return nativeApplyConstraints.apply(this,[c]);};}}}},{"../utils":15}],14:[function(require,module,exports){'use strict';Object.defineProperty(exports,"__esModule",{value:true});var _typeof=typeof Symbol==="function"&&typeof Symbol.iterator==="symbol"?function(obj){return typeof obj;}:function(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj;};exports.shimLocalStreamsAPI=shimLocalStreamsAPI;exports.shimRemoteStreamsAPI=shimRemoteStreamsAPI;exports.shimCallbacksAPI=shimCallbacksAPI;exports.shimGetUserMedia=shimGetUserMedia;exports.shimConstraints=shimConstraints;exports.shimRTCIceServerUrls=shimRTCIceServerUrls;exports.shimTrackEventTransceiver=shimTrackEventTransceiver;exports.shimCreateOfferLegacy=shimCreateOfferLegacy;var _utils=require('../utils');var utils=_interopRequireWildcard(_utils);function _interopRequireWildcard(obj){if(obj&&obj.__esModule){return obj;}else{var newObj={};if(obj!=null){for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key))newObj[key]=obj[key];}}newObj.default=obj;return newObj;}}
+function shimLocalStreamsAPI(window){if((typeof window==='undefined'?'undefined':_typeof(window))!=='object'||!window.RTCPeerConnection){return;}
+if(!('getLocalStreams'in window.RTCPeerConnection.prototype)){window.RTCPeerConnection.prototype.getLocalStreams=function(){if(!this._localStreams){this._localStreams=[];}
+return this._localStreams;};}
+if(!('addStream'in window.RTCPeerConnection.prototype)){var _addTrack=window.RTCPeerConnection.prototype.addTrack;window.RTCPeerConnection.prototype.addStream=function(stream){var _this=this;if(!this._localStreams){this._localStreams=[];}
+if(!this._localStreams.includes(stream)){this._localStreams.push(stream);}
+stream.getTracks().forEach(function(track){return _addTrack.call(_this,track,stream);});};window.RTCPeerConnection.prototype.addTrack=function(track,stream){if(stream){if(!this._localStreams){this._localStreams=[stream];}else if(!this._localStreams.includes(stream)){this._localStreams.push(stream);}}
+return _addTrack.call(this,track,stream);};}
+if(!('removeStream'in window.RTCPeerConnection.prototype)){window.RTCPeerConnection.prototype.removeStream=function(stream){var _this2=this;if(!this._localStreams){this._localStreams=[];}
+var index=this._localStreams.indexOf(stream);if(index===-1){return;}
+this._localStreams.splice(index,1);var tracks=stream.getTracks();this.getSenders().forEach(function(sender){if(tracks.includes(sender.track)){_this2.removeTrack(sender);}});};}}
+function shimRemoteStreamsAPI(window){if((typeof window==='undefined'?'undefined':_typeof(window))!=='object'||!window.RTCPeerConnection){return;}
+if(!('getRemoteStreams'in window.RTCPeerConnection.prototype)){window.RTCPeerConnection.prototype.getRemoteStreams=function(){return this._remoteStreams?this._remoteStreams:[];};}
+if(!('onaddstream'in window.RTCPeerConnection.prototype)){Object.defineProperty(window.RTCPeerConnection.prototype,'onaddstream',{get:function get(){return this._onaddstream;},set:function set(f){var _this3=this;if(this._onaddstream){this.removeEventListener('addstream',this._onaddstream);this.removeEventListener('track',this._onaddstreampoly);}
+this.addEventListener('addstream',this._onaddstream=f);this.addEventListener('track',this._onaddstreampoly=function(e){e.streams.forEach(function(stream){if(!_this3._remoteStreams){_this3._remoteStreams=[];}
+if(_this3._remoteStreams.includes(stream)){return;}
+_this3._remoteStreams.push(stream);var event=new Event('addstream');event.stream=stream;_this3.dispatchEvent(event);});});}});var origSetRemoteDescription=window.RTCPeerConnection.prototype.setRemoteDescription;window.RTCPeerConnection.prototype.setRemoteDescription=function(){var pc=this;if(!this._onaddstreampoly){this.addEventListener('track',this._onaddstreampoly=function(e){e.streams.forEach(function(stream){if(!pc._remoteStreams){pc._remoteStreams=[];}
+if(pc._remoteStreams.indexOf(stream)>=0){return;}
+pc._remoteStreams.push(stream);var event=new Event('addstream');event.stream=stream;pc.dispatchEvent(event);});});}
+return origSetRemoteDescription.apply(pc,arguments);};}}
+function shimCallbacksAPI(window){if((typeof window==='undefined'?'undefined':_typeof(window))!=='object'||!window.RTCPeerConnection){return;}
+var prototype=window.RTCPeerConnection.prototype;var createOffer=prototype.createOffer;var createAnswer=prototype.createAnswer;var setLocalDescription=prototype.setLocalDescription;var setRemoteDescription=prototype.setRemoteDescription;var addIceCandidate=prototype.addIceCandidate;prototype.createOffer=function(successCallback,failureCallback){var options=arguments.length>=2?arguments[2]:arguments[0];var promise=createOffer.apply(this,[options]);if(!failureCallback){return promise;}
+promise.then(successCallback,failureCallback);return Promise.resolve();};prototype.createAnswer=function(successCallback,failureCallback){var options=arguments.length>=2?arguments[2]:arguments[0];var promise=createAnswer.apply(this,[options]);if(!failureCallback){return promise;}
+promise.then(successCallback,failureCallback);return Promise.resolve();};var withCallback=function withCallback(description,successCallback,failureCallback){var promise=setLocalDescription.apply(this,[description]);if(!failureCallback){return promise;}
+promise.then(successCallback,failureCallback);return Promise.resolve();};prototype.setLocalDescription=withCallback;withCallback=function withCallback(description,successCallback,failureCallback){var promise=setRemoteDescription.apply(this,[description]);if(!failureCallback){return promise;}
+promise.then(successCallback,failureCallback);return Promise.resolve();};prototype.setRemoteDescription=withCallback;withCallback=function withCallback(candidate,successCallback,failureCallback){var promise=addIceCandidate.apply(this,[candidate]);if(!failureCallback){return promise;}
+promise.then(successCallback,failureCallback);return Promise.resolve();};prototype.addIceCandidate=withCallback;}
+function shimGetUserMedia(window){var navigator=window&&window.navigator;if(navigator.mediaDevices&&navigator.mediaDevices.getUserMedia){var mediaDevices=navigator.mediaDevices;var _getUserMedia=mediaDevices.getUserMedia.bind(mediaDevices);navigator.mediaDevices.getUserMedia=function(constraints){return _getUserMedia(shimConstraints(constraints));};}
+if(!navigator.getUserMedia&&navigator.mediaDevices&&navigator.mediaDevices.getUserMedia){navigator.getUserMedia=function(constraints,cb,errcb){navigator.mediaDevices.getUserMedia(constraints).then(cb,errcb);}.bind(navigator);}}
+function shimConstraints(constraints){if(constraints&&constraints.video!==undefined){return Object.assign({},constraints,{video:utils.compactObject(constraints.video)});}
+return constraints;}
+function shimRTCIceServerUrls(window){var OrigPeerConnection=window.RTCPeerConnection;window.RTCPeerConnection=function(pcConfig,pcConstraints){if(pcConfig&&pcConfig.iceServers){var newIceServers=[];for(var i=0;i=pos&&parseInt(match[pos],10);}
+function wrapPeerConnectionEvent(window,eventNameToWrap,wrapper){if(!window.RTCPeerConnection){return;}
+var proto=window.RTCPeerConnection.prototype;var nativeAddEventListener=proto.addEventListener;proto.addEventListener=function(nativeEventName,cb){if(nativeEventName!==eventNameToWrap){return nativeAddEventListener.apply(this,arguments);}
+var wrappedCallback=function wrappedCallback(e){var modifiedEvent=wrapper(e);if(modifiedEvent){cb(modifiedEvent);}};this._eventMap=this._eventMap||{};this._eventMap[cb]=wrappedCallback;return nativeAddEventListener.apply(this,[nativeEventName,wrappedCallback]);};var nativeRemoveEventListener=proto.removeEventListener;proto.removeEventListener=function(nativeEventName,cb){if(nativeEventName!==eventNameToWrap||!this._eventMap||!this._eventMap[cb]){return nativeRemoveEventListener.apply(this,arguments);}
+var unwrappedCb=this._eventMap[cb];delete this._eventMap[cb];return nativeRemoveEventListener.apply(this,[nativeEventName,unwrappedCb]);};Object.defineProperty(proto,'on'+eventNameToWrap,{get:function get(){return this['_on'+eventNameToWrap];},set:function set(cb){if(this['_on'+eventNameToWrap]){this.removeEventListener(eventNameToWrap,this['_on'+eventNameToWrap]);delete this['_on'+eventNameToWrap];}
+if(cb){this.addEventListener(eventNameToWrap,this['_on'+eventNameToWrap]=cb);}},enumerable:true,configurable:true});}
+function disableLog(bool){if(typeof bool!=='boolean'){return new Error('Argument type: '+(typeof bool==='undefined'?'undefined':_typeof(bool))+'. Please use a boolean.');}
+logDisabled_=bool;return bool?'adapter.js logging disabled':'adapter.js logging enabled';}
+function disableWarnings(bool){if(typeof bool!=='boolean'){return new Error('Argument type: '+(typeof bool==='undefined'?'undefined':_typeof(bool))+'. Please use a boolean.');}
+deprecationWarnings_=!bool;return'adapter.js deprecation warnings '+(bool?'disabled':'enabled');}
+function log(){if((typeof window==='undefined'?'undefined':_typeof(window))==='object'){if(logDisabled_){return;}
+if(typeof console!=='undefined'&&typeof console.log==='function'){console.log.apply(console,arguments);}}}
+function deprecated(oldMethod,newMethod){if(!deprecationWarnings_){return;}
+console.warn(oldMethod+' is deprecated, please use '+newMethod+' instead.');}
+function detectBrowser(window){var navigator=window.navigator;var result={browser:null,version:null};if(typeof window==='undefined'||!window.navigator){result.browser='Not a browser.';return result;}
+if(navigator.mozGetUserMedia){result.browser='firefox';result.version=extractVersion(navigator.userAgent,/Firefox\/(\d+)\./,1);}else if(navigator.webkitGetUserMedia){result.browser='chrome';result.version=extractVersion(navigator.userAgent,/Chrom(e|ium)\/(\d+)\./,2);}else if(navigator.mediaDevices&&navigator.userAgent.match(/Edge\/(\d+).(\d+)$/)){result.browser='edge';result.version=extractVersion(navigator.userAgent,/Edge\/(\d+).(\d+)$/,2);}else if(window.RTCPeerConnection&&navigator.userAgent.match(/AppleWebKit\/(\d+)\./)){result.browser='safari';result.version=extractVersion(navigator.userAgent,/AppleWebKit\/(\d+)\./,1);}else{result.browser='Not a supported browser.';return result;}
+return result;}
+function compactObject(data){if((typeof data==='undefined'?'undefined':_typeof(data))!=='object'){return data;}
+return Object.keys(data).reduce(function(accumulator,key){var isObject=_typeof(data[key])==='object';var value=isObject?compactObject(data[key]):data[key];var isEmptyObject=isObject&&!Object.keys(value).length;if(value===undefined||isEmptyObject){return accumulator;}
+return Object.assign(accumulator,_defineProperty({},key,value));},{});}},{}],16:[function(require,module,exports){'use strict';var SDPUtils=require('sdp');function fixStatsType(stat){return{inboundrtp:'inbound-rtp',outboundrtp:'outbound-rtp',candidatepair:'candidate-pair',localcandidate:'local-candidate',remotecandidate:'remote-candidate'}[stat.type]||stat.type;}
+function writeMediaSection(transceiver,caps,type,stream,dtlsRole){var sdp=SDPUtils.writeRtpDescription(transceiver.kind,caps);sdp+=SDPUtils.writeIceParameters(transceiver.iceGatherer.getLocalParameters());sdp+=SDPUtils.writeDtlsParameters(transceiver.dtlsTransport.getLocalParameters(),type==='offer'?'actpass':dtlsRole||'active');sdp+='a=mid:'+transceiver.mid+'\r\n';if(transceiver.rtpSender&&transceiver.rtpReceiver){sdp+='a=sendrecv\r\n';}else if(transceiver.rtpSender){sdp+='a=sendonly\r\n';}else if(transceiver.rtpReceiver){sdp+='a=recvonly\r\n';}else{sdp+='a=inactive\r\n';}
+if(transceiver.rtpSender){var trackId=transceiver.rtpSender._initialTrackId||transceiver.rtpSender.track.id;transceiver.rtpSender._initialTrackId=trackId;var msid='msid:'+(stream?stream.id:'-')+' '+
+trackId+'\r\n';sdp+='a='+msid;sdp+='a=ssrc:'+transceiver.sendEncodingParameters[0].ssrc+' '+msid;if(transceiver.sendEncodingParameters[0].rtx){sdp+='a=ssrc:'+transceiver.sendEncodingParameters[0].rtx.ssrc+' '+msid;sdp+='a=ssrc-group:FID '+
+transceiver.sendEncodingParameters[0].ssrc+' '+
+transceiver.sendEncodingParameters[0].rtx.ssrc+'\r\n';}}
+sdp+='a=ssrc:'+transceiver.sendEncodingParameters[0].ssrc+' cname:'+SDPUtils.localCName+'\r\n';if(transceiver.rtpSender&&transceiver.sendEncodingParameters[0].rtx){sdp+='a=ssrc:'+transceiver.sendEncodingParameters[0].rtx.ssrc+' cname:'+SDPUtils.localCName+'\r\n';}
+return sdp;}
+function filterIceServers(iceServers,edgeVersion){var hasTurn=false;iceServers=JSON.parse(JSON.stringify(iceServers));return iceServers.filter(function(server){if(server&&(server.urls||server.url)){var urls=server.urls||server.url;if(server.url&&!server.urls){console.warn('RTCIceServer.url is deprecated! Use urls instead.');}
+var isString=typeof urls==='string';if(isString){urls=[urls];}
+urls=urls.filter(function(url){var validTurn=url.indexOf('turn:')===0&&url.indexOf('transport=udp')!==-1&&url.indexOf('turn:[')===-1&&!hasTurn;if(validTurn){hasTurn=true;return true;}
+return url.indexOf('stun:')===0&&edgeVersion>=14393&&url.indexOf('?transport=udp')===-1;});delete server.url;server.urls=isString?urls[0]:urls;return!!urls.length;}});}
+function getCommonCapabilities(localCapabilities,remoteCapabilities){var commonCapabilities={codecs:[],headerExtensions:[],fecMechanisms:[]};var findCodecByPayloadType=function(pt,codecs){pt=parseInt(pt,10);for(var i=0;i0;i--){this._iceGatherers.push(new window.RTCIceGatherer({iceServers:config.iceServers,gatherPolicy:config.iceTransportPolicy}));}}else{config.iceCandidatePoolSize=0;}
+this._config=config;this.transceivers=[];this._sdpSessionId=SDPUtils.generateSessionId();this._sdpSessionVersion=0;this._dtlsRole=undefined;this._isClosed=false;};Object.defineProperty(RTCPeerConnection.prototype,'localDescription',{configurable:true,get:function(){return this._localDescription;}});Object.defineProperty(RTCPeerConnection.prototype,'remoteDescription',{configurable:true,get:function(){return this._remoteDescription;}});RTCPeerConnection.prototype.onicecandidate=null;RTCPeerConnection.prototype.onaddstream=null;RTCPeerConnection.prototype.ontrack=null;RTCPeerConnection.prototype.onremovestream=null;RTCPeerConnection.prototype.onsignalingstatechange=null;RTCPeerConnection.prototype.oniceconnectionstatechange=null;RTCPeerConnection.prototype.onconnectionstatechange=null;RTCPeerConnection.prototype.onicegatheringstatechange=null;RTCPeerConnection.prototype.onnegotiationneeded=null;RTCPeerConnection.prototype.ondatachannel=null;RTCPeerConnection.prototype._dispatchEvent=function(name,event){if(this._isClosed){return;}
+this.dispatchEvent(event);if(typeof this['on'+name]==='function'){this['on'+name](event);}};RTCPeerConnection.prototype._emitGatheringStateChange=function(){var event=new Event('icegatheringstatechange');this._dispatchEvent('icegatheringstatechange',event);};RTCPeerConnection.prototype.getConfiguration=function(){return this._config;};RTCPeerConnection.prototype.getLocalStreams=function(){return this.localStreams;};RTCPeerConnection.prototype.getRemoteStreams=function(){return this.remoteStreams;};RTCPeerConnection.prototype._createTransceiver=function(kind,doNotAdd){var hasBundleTransport=this.transceivers.length>0;var transceiver={track:null,iceGatherer:null,iceTransport:null,dtlsTransport:null,localCapabilities:null,remoteCapabilities:null,rtpSender:null,rtpReceiver:null,kind:kind,mid:null,sendEncodingParameters:null,recvEncodingParameters:null,stream:null,associatedRemoteMediaStreams:[],wantReceive:true};if(this.usingBundle&&hasBundleTransport){transceiver.iceTransport=this.transceivers[0].iceTransport;transceiver.dtlsTransport=this.transceivers[0].dtlsTransport;}else{var transports=this._createIceAndDtlsTransports();transceiver.iceTransport=transports.iceTransport;transceiver.dtlsTransport=transports.dtlsTransport;}
+if(!doNotAdd){this.transceivers.push(transceiver);}
+return transceiver;};RTCPeerConnection.prototype.addTrack=function(track,stream){if(this._isClosed){throw makeError('InvalidStateError','Attempted to call addTrack on a closed peerconnection.');}
+var alreadyExists=this.transceivers.find(function(s){return s.track===track;});if(alreadyExists){throw makeError('InvalidAccessError','Track already exists.');}
+var transceiver;for(var i=0;i=15025){stream.getTracks().forEach(function(track){pc.addTrack(track,stream);});}else{var clonedStream=stream.clone();stream.getTracks().forEach(function(track,idx){var clonedTrack=clonedStream.getTracks()[idx];track.addEventListener('enabled',function(event){clonedTrack.enabled=event.enabled;});});clonedStream.getTracks().forEach(function(track){pc.addTrack(track,clonedStream);});}};RTCPeerConnection.prototype.removeTrack=function(sender){if(this._isClosed){throw makeError('InvalidStateError','Attempted to call removeTrack on a closed peerconnection.');}
+if(!(sender instanceof window.RTCRtpSender)){throw new TypeError('Argument 1 of RTCPeerConnection.removeTrack '+'does not implement interface RTCRtpSender.');}
+var transceiver=this.transceivers.find(function(t){return t.rtpSender===sender;});if(!transceiver){throw makeError('InvalidAccessError','Sender was not created by this connection.');}
+var stream=transceiver.stream;transceiver.rtpSender.stop();transceiver.rtpSender=null;transceiver.track=null;transceiver.stream=null;var localStreams=this.transceivers.map(function(t){return t.stream;});if(localStreams.indexOf(stream)===-1&&this.localStreams.indexOf(stream)>-1){this.localStreams.splice(this.localStreams.indexOf(stream),1);}
+this._maybeFireNegotiationNeeded();};RTCPeerConnection.prototype.removeStream=function(stream){var pc=this;stream.getTracks().forEach(function(track){var sender=pc.getSenders().find(function(s){return s.track===track;});if(sender){pc.removeTrack(sender);}});};RTCPeerConnection.prototype.getSenders=function(){return this.transceivers.filter(function(transceiver){return!!transceiver.rtpSender;}).map(function(transceiver){return transceiver.rtpSender;});};RTCPeerConnection.prototype.getReceivers=function(){return this.transceivers.filter(function(transceiver){return!!transceiver.rtpReceiver;}).map(function(transceiver){return transceiver.rtpReceiver;});};RTCPeerConnection.prototype._createIceGatherer=function(sdpMLineIndex,usingBundle){var pc=this;if(usingBundle&&sdpMLineIndex>0){return this.transceivers[0].iceGatherer;}else if(this._iceGatherers.length){return this._iceGatherers.shift();}
+var iceGatherer=new window.RTCIceGatherer({iceServers:this._config.iceServers,gatherPolicy:this._config.iceTransportPolicy});Object.defineProperty(iceGatherer,'state',{value:'new',writable:true});this.transceivers[sdpMLineIndex].bufferedCandidateEvents=[];this.transceivers[sdpMLineIndex].bufferCandidates=function(event){var end=!event.candidate||Object.keys(event.candidate).length===0;iceGatherer.state=end?'completed':'gathering';if(pc.transceivers[sdpMLineIndex].bufferedCandidateEvents!==null){pc.transceivers[sdpMLineIndex].bufferedCandidateEvents.push(event);}};iceGatherer.addEventListener('localcandidate',this.transceivers[sdpMLineIndex].bufferCandidates);return iceGatherer;};RTCPeerConnection.prototype._gather=function(mid,sdpMLineIndex){var pc=this;var iceGatherer=this.transceivers[sdpMLineIndex].iceGatherer;if(iceGatherer.onlocalcandidate){return;}
+var bufferedCandidateEvents=this.transceivers[sdpMLineIndex].bufferedCandidateEvents;this.transceivers[sdpMLineIndex].bufferedCandidateEvents=null;iceGatherer.removeEventListener('localcandidate',this.transceivers[sdpMLineIndex].bufferCandidates);iceGatherer.onlocalcandidate=function(evt){if(pc.usingBundle&&sdpMLineIndex>0){return;}
+var event=new Event('icecandidate');event.candidate={sdpMid:mid,sdpMLineIndex:sdpMLineIndex};var cand=evt.candidate;var end=!cand||Object.keys(cand).length===0;if(end){if(iceGatherer.state==='new'||iceGatherer.state==='gathering'){iceGatherer.state='completed';}}else{if(iceGatherer.state==='new'){iceGatherer.state='gathering';}
+cand.component=1;cand.ufrag=iceGatherer.getLocalParameters().usernameFragment;var serializedCandidate=SDPUtils.writeCandidate(cand);event.candidate=Object.assign(event.candidate,SDPUtils.parseCandidate(serializedCandidate));event.candidate.candidate=serializedCandidate;event.candidate.toJSON=function(){return{candidate:event.candidate.candidate,sdpMid:event.candidate.sdpMid,sdpMLineIndex:event.candidate.sdpMLineIndex,usernameFragment:event.candidate.usernameFragment};};}
+var sections=SDPUtils.getMediaSections(pc._localDescription.sdp);if(!end){sections[event.candidate.sdpMLineIndex]+='a='+event.candidate.candidate+'\r\n';}else{sections[event.candidate.sdpMLineIndex]+='a=end-of-candidates\r\n';}
+pc._localDescription.sdp=SDPUtils.getDescription(pc._localDescription.sdp)+
+sections.join('');var complete=pc.transceivers.every(function(transceiver){return transceiver.iceGatherer&&transceiver.iceGatherer.state==='completed';});if(pc.iceGatheringState!=='gathering'){pc.iceGatheringState='gathering';pc._emitGatheringStateChange();}
+if(!end){pc._dispatchEvent('icecandidate',event);}
+if(complete){pc._dispatchEvent('icecandidate',new Event('icecandidate'));pc.iceGatheringState='complete';pc._emitGatheringStateChange();}};window.setTimeout(function(){bufferedCandidateEvents.forEach(function(e){iceGatherer.onlocalcandidate(e);});},0);};RTCPeerConnection.prototype._createIceAndDtlsTransports=function(){var pc=this;var iceTransport=new window.RTCIceTransport(null);iceTransport.onicestatechange=function(){pc._updateIceConnectionState();pc._updateConnectionState();};var dtlsTransport=new window.RTCDtlsTransport(iceTransport);dtlsTransport.ondtlsstatechange=function(){pc._updateConnectionState();};dtlsTransport.onerror=function(){Object.defineProperty(dtlsTransport,'state',{value:'failed',writable:true});pc._updateConnectionState();};return{iceTransport:iceTransport,dtlsTransport:dtlsTransport};};RTCPeerConnection.prototype._disposeIceAndDtlsTransports=function(sdpMLineIndex){var iceGatherer=this.transceivers[sdpMLineIndex].iceGatherer;if(iceGatherer){delete iceGatherer.onlocalcandidate;delete this.transceivers[sdpMLineIndex].iceGatherer;}
+var iceTransport=this.transceivers[sdpMLineIndex].iceTransport;if(iceTransport){delete iceTransport.onicestatechange;delete this.transceivers[sdpMLineIndex].iceTransport;}
+var dtlsTransport=this.transceivers[sdpMLineIndex].dtlsTransport;if(dtlsTransport){delete dtlsTransport.ondtlsstatechange;delete dtlsTransport.onerror;delete this.transceivers[sdpMLineIndex].dtlsTransport;}};RTCPeerConnection.prototype._transceive=function(transceiver,send,recv){var params=getCommonCapabilities(transceiver.localCapabilities,transceiver.remoteCapabilities);if(send&&transceiver.rtpSender){params.encodings=transceiver.sendEncodingParameters;params.rtcp={cname:SDPUtils.localCName,compound:transceiver.rtcpParameters.compound};if(transceiver.recvEncodingParameters.length){params.rtcp.ssrc=transceiver.recvEncodingParameters[0].ssrc;}
+transceiver.rtpSender.send(params);}
+if(recv&&transceiver.rtpReceiver&¶ms.codecs.length>0){if(transceiver.kind==='video'&&transceiver.recvEncodingParameters&&edgeVersion<15019){transceiver.recvEncodingParameters.forEach(function(p){delete p.rtx;});}
+if(transceiver.recvEncodingParameters.length){params.encodings=transceiver.recvEncodingParameters;}else{params.encodings=[{}];}
+params.rtcp={compound:transceiver.rtcpParameters.compound};if(transceiver.rtcpParameters.cname){params.rtcp.cname=transceiver.rtcpParameters.cname;}
+if(transceiver.sendEncodingParameters.length){params.rtcp.ssrc=transceiver.sendEncodingParameters[0].ssrc;}
+transceiver.rtpReceiver.receive(params);}};RTCPeerConnection.prototype.setLocalDescription=function(description){var pc=this;if(['offer','answer'].indexOf(description.type)===-1){return Promise.reject(makeError('TypeError','Unsupported type "'+description.type+'"'));}
+if(!isActionAllowedInSignalingState('setLocalDescription',description.type,pc.signalingState)||pc._isClosed){return Promise.reject(makeError('InvalidStateError','Can not set local '+description.type+' in state '+pc.signalingState));}
+var sections;var sessionpart;if(description.type==='offer'){sections=SDPUtils.splitSections(description.sdp);sessionpart=sections.shift();sections.forEach(function(mediaSection,sdpMLineIndex){var caps=SDPUtils.parseRtpParameters(mediaSection);pc.transceivers[sdpMLineIndex].localCapabilities=caps;});pc.transceivers.forEach(function(transceiver,sdpMLineIndex){pc._gather(transceiver.mid,sdpMLineIndex);});}else if(description.type==='answer'){sections=SDPUtils.splitSections(pc._remoteDescription.sdp);sessionpart=sections.shift();var isIceLite=SDPUtils.matchPrefix(sessionpart,'a=ice-lite').length>0;sections.forEach(function(mediaSection,sdpMLineIndex){var transceiver=pc.transceivers[sdpMLineIndex];var iceGatherer=transceiver.iceGatherer;var iceTransport=transceiver.iceTransport;var dtlsTransport=transceiver.dtlsTransport;var localCapabilities=transceiver.localCapabilities;var remoteCapabilities=transceiver.remoteCapabilities;var rejected=SDPUtils.isRejected(mediaSection)&&SDPUtils.matchPrefix(mediaSection,'a=bundle-only').length===0;if(!rejected&&!transceiver.rejected){var remoteIceParameters=SDPUtils.getIceParameters(mediaSection,sessionpart);var remoteDtlsParameters=SDPUtils.getDtlsParameters(mediaSection,sessionpart);if(isIceLite){remoteDtlsParameters.role='server';}
+if(!pc.usingBundle||sdpMLineIndex===0){pc._gather(transceiver.mid,sdpMLineIndex);if(iceTransport.state==='new'){iceTransport.start(iceGatherer,remoteIceParameters,isIceLite?'controlling':'controlled');}
+if(dtlsTransport.state==='new'){dtlsTransport.start(remoteDtlsParameters);}}
+var params=getCommonCapabilities(localCapabilities,remoteCapabilities);pc._transceive(transceiver,params.codecs.length>0,false);}});}
+pc._localDescription={type:description.type,sdp:description.sdp};if(description.type==='offer'){pc._updateSignalingState('have-local-offer');}else{pc._updateSignalingState('stable');}
+return Promise.resolve();};RTCPeerConnection.prototype.setRemoteDescription=function(description){var pc=this;if(['offer','answer'].indexOf(description.type)===-1){return Promise.reject(makeError('TypeError','Unsupported type "'+description.type+'"'));}
+if(!isActionAllowedInSignalingState('setRemoteDescription',description.type,pc.signalingState)||pc._isClosed){return Promise.reject(makeError('InvalidStateError','Can not set remote '+description.type+' in state '+pc.signalingState));}
+var streams={};pc.remoteStreams.forEach(function(stream){streams[stream.id]=stream;});var receiverList=[];var sections=SDPUtils.splitSections(description.sdp);var sessionpart=sections.shift();var isIceLite=SDPUtils.matchPrefix(sessionpart,'a=ice-lite').length>0;var usingBundle=SDPUtils.matchPrefix(sessionpart,'a=group:BUNDLE ').length>0;pc.usingBundle=usingBundle;var iceOptions=SDPUtils.matchPrefix(sessionpart,'a=ice-options:')[0];if(iceOptions){pc.canTrickleIceCandidates=iceOptions.substr(14).split(' ').indexOf('trickle')>=0;}else{pc.canTrickleIceCandidates=false;}
+sections.forEach(function(mediaSection,sdpMLineIndex){var lines=SDPUtils.splitLines(mediaSection);var kind=SDPUtils.getKind(mediaSection);var rejected=SDPUtils.isRejected(mediaSection)&&SDPUtils.matchPrefix(mediaSection,'a=bundle-only').length===0;var protocol=lines[0].substr(2).split(' ')[2];var direction=SDPUtils.getDirection(mediaSection,sessionpart);var remoteMsid=SDPUtils.parseMsid(mediaSection);var mid=SDPUtils.getMid(mediaSection)||SDPUtils.generateIdentifier();if(rejected||(kind==='application'&&(protocol==='DTLS/SCTP'||protocol==='UDP/DTLS/SCTP'))){pc.transceivers[sdpMLineIndex]={mid:mid,kind:kind,protocol:protocol,rejected:true};return;}
+if(!rejected&&pc.transceivers[sdpMLineIndex]&&pc.transceivers[sdpMLineIndex].rejected){pc.transceivers[sdpMLineIndex]=pc._createTransceiver(kind,true);}
+var transceiver;var iceGatherer;var iceTransport;var dtlsTransport;var rtpReceiver;var sendEncodingParameters;var recvEncodingParameters;var localCapabilities;var track;var remoteCapabilities=SDPUtils.parseRtpParameters(mediaSection);var remoteIceParameters;var remoteDtlsParameters;if(!rejected){remoteIceParameters=SDPUtils.getIceParameters(mediaSection,sessionpart);remoteDtlsParameters=SDPUtils.getDtlsParameters(mediaSection,sessionpart);remoteDtlsParameters.role='client';}
+recvEncodingParameters=SDPUtils.parseRtpEncodingParameters(mediaSection);var rtcpParameters=SDPUtils.parseRtcpParameters(mediaSection);var isComplete=SDPUtils.matchPrefix(mediaSection,'a=end-of-candidates',sessionpart).length>0;var cands=SDPUtils.matchPrefix(mediaSection,'a=candidate:').map(function(cand){return SDPUtils.parseCandidate(cand);}).filter(function(cand){return cand.component===1;});if((description.type==='offer'||description.type==='answer')&&!rejected&&usingBundle&&sdpMLineIndex>0&&pc.transceivers[sdpMLineIndex]){pc._disposeIceAndDtlsTransports(sdpMLineIndex);pc.transceivers[sdpMLineIndex].iceGatherer=pc.transceivers[0].iceGatherer;pc.transceivers[sdpMLineIndex].iceTransport=pc.transceivers[0].iceTransport;pc.transceivers[sdpMLineIndex].dtlsTransport=pc.transceivers[0].dtlsTransport;if(pc.transceivers[sdpMLineIndex].rtpSender){pc.transceivers[sdpMLineIndex].rtpSender.setTransport(pc.transceivers[0].dtlsTransport);}
+if(pc.transceivers[sdpMLineIndex].rtpReceiver){pc.transceivers[sdpMLineIndex].rtpReceiver.setTransport(pc.transceivers[0].dtlsTransport);}}
+if(description.type==='offer'&&!rejected){transceiver=pc.transceivers[sdpMLineIndex]||pc._createTransceiver(kind);transceiver.mid=mid;if(!transceiver.iceGatherer){transceiver.iceGatherer=pc._createIceGatherer(sdpMLineIndex,usingBundle);}
+if(cands.length&&transceiver.iceTransport.state==='new'){if(isComplete&&(!usingBundle||sdpMLineIndex===0)){transceiver.iceTransport.setRemoteCandidates(cands);}else{cands.forEach(function(candidate){maybeAddCandidate(transceiver.iceTransport,candidate);});}}
+localCapabilities=window.RTCRtpReceiver.getCapabilities(kind);if(edgeVersion<15019){localCapabilities.codecs=localCapabilities.codecs.filter(function(codec){return codec.name!=='rtx';});}
+sendEncodingParameters=transceiver.sendEncodingParameters||[{ssrc:(2*sdpMLineIndex+2)*1001}];var isNewTrack=false;if(direction==='sendrecv'||direction==='sendonly'){isNewTrack=!transceiver.rtpReceiver;rtpReceiver=transceiver.rtpReceiver||new window.RTCRtpReceiver(transceiver.dtlsTransport,kind);if(isNewTrack){var stream;track=rtpReceiver.track;if(remoteMsid&&remoteMsid.stream==='-'){}else if(remoteMsid){if(!streams[remoteMsid.stream]){streams[remoteMsid.stream]=new window.MediaStream();Object.defineProperty(streams[remoteMsid.stream],'id',{get:function(){return remoteMsid.stream;}});}
+Object.defineProperty(track,'id',{get:function(){return remoteMsid.track;}});stream=streams[remoteMsid.stream];}else{if(!streams.default){streams.default=new window.MediaStream();}
+stream=streams.default;}
+if(stream){addTrackToStreamAndFireEvent(track,stream);transceiver.associatedRemoteMediaStreams.push(stream);}
+receiverList.push([track,rtpReceiver,stream]);}}else if(transceiver.rtpReceiver&&transceiver.rtpReceiver.track){transceiver.associatedRemoteMediaStreams.forEach(function(s){var nativeTrack=s.getTracks().find(function(t){return t.id===transceiver.rtpReceiver.track.id;});if(nativeTrack){removeTrackFromStreamAndFireEvent(nativeTrack,s);}});transceiver.associatedRemoteMediaStreams=[];}
+transceiver.localCapabilities=localCapabilities;transceiver.remoteCapabilities=remoteCapabilities;transceiver.rtpReceiver=rtpReceiver;transceiver.rtcpParameters=rtcpParameters;transceiver.sendEncodingParameters=sendEncodingParameters;transceiver.recvEncodingParameters=recvEncodingParameters;pc._transceive(pc.transceivers[sdpMLineIndex],false,isNewTrack);}else if(description.type==='answer'&&!rejected){transceiver=pc.transceivers[sdpMLineIndex];iceGatherer=transceiver.iceGatherer;iceTransport=transceiver.iceTransport;dtlsTransport=transceiver.dtlsTransport;rtpReceiver=transceiver.rtpReceiver;sendEncodingParameters=transceiver.sendEncodingParameters;localCapabilities=transceiver.localCapabilities;pc.transceivers[sdpMLineIndex].recvEncodingParameters=recvEncodingParameters;pc.transceivers[sdpMLineIndex].remoteCapabilities=remoteCapabilities;pc.transceivers[sdpMLineIndex].rtcpParameters=rtcpParameters;if(cands.length&&iceTransport.state==='new'){if((isIceLite||isComplete)&&(!usingBundle||sdpMLineIndex===0)){iceTransport.setRemoteCandidates(cands);}else{cands.forEach(function(candidate){maybeAddCandidate(transceiver.iceTransport,candidate);});}}
+if(!usingBundle||sdpMLineIndex===0){if(iceTransport.state==='new'){iceTransport.start(iceGatherer,remoteIceParameters,'controlling');}
+if(dtlsTransport.state==='new'){dtlsTransport.start(remoteDtlsParameters);}}
+var commonCapabilities=getCommonCapabilities(transceiver.localCapabilities,transceiver.remoteCapabilities);var hasRtx=commonCapabilities.codecs.filter(function(c){return c.name.toLowerCase()==='rtx';}).length;if(!hasRtx&&transceiver.sendEncodingParameters[0].rtx){delete transceiver.sendEncodingParameters[0].rtx;}
+pc._transceive(transceiver,direction==='sendrecv'||direction==='recvonly',direction==='sendrecv'||direction==='sendonly');if(rtpReceiver&&(direction==='sendrecv'||direction==='sendonly')){track=rtpReceiver.track;if(remoteMsid){if(!streams[remoteMsid.stream]){streams[remoteMsid.stream]=new window.MediaStream();}
+addTrackToStreamAndFireEvent(track,streams[remoteMsid.stream]);receiverList.push([track,rtpReceiver,streams[remoteMsid.stream]]);}else{if(!streams.default){streams.default=new window.MediaStream();}
+addTrackToStreamAndFireEvent(track,streams.default);receiverList.push([track,rtpReceiver,streams.default]);}}else{delete transceiver.rtpReceiver;}}});if(pc._dtlsRole===undefined){pc._dtlsRole=description.type==='offer'?'active':'passive';}
+pc._remoteDescription={type:description.type,sdp:description.sdp};if(description.type==='offer'){pc._updateSignalingState('have-remote-offer');}else{pc._updateSignalingState('stable');}
+Object.keys(streams).forEach(function(sid){var stream=streams[sid];if(stream.getTracks().length){if(pc.remoteStreams.indexOf(stream)===-1){pc.remoteStreams.push(stream);var event=new Event('addstream');event.stream=stream;window.setTimeout(function(){pc._dispatchEvent('addstream',event);});}
+receiverList.forEach(function(item){var track=item[0];var receiver=item[1];if(stream.id!==item[2].id){return;}
+fireAddTrack(pc,track,receiver,[stream]);});}});receiverList.forEach(function(item){if(item[2]){return;}
+fireAddTrack(pc,item[0],item[1],[]);});window.setTimeout(function(){if(!(pc&&pc.transceivers)){return;}
+pc.transceivers.forEach(function(transceiver){if(transceiver.iceTransport&&transceiver.iceTransport.state==='new'&&transceiver.iceTransport.getRemoteCandidates().length>0){console.warn('Timeout for addRemoteCandidate. Consider sending '+'an end-of-candidates notification');transceiver.iceTransport.addRemoteCandidate({});}});},4000);return Promise.resolve();};RTCPeerConnection.prototype.close=function(){this.transceivers.forEach(function(transceiver){if(transceiver.iceTransport){transceiver.iceTransport.stop();}
+if(transceiver.dtlsTransport){transceiver.dtlsTransport.stop();}
+if(transceiver.rtpSender){transceiver.rtpSender.stop();}
+if(transceiver.rtpReceiver){transceiver.rtpReceiver.stop();}});this._isClosed=true;this._updateSignalingState('closed');};RTCPeerConnection.prototype._updateSignalingState=function(newState){this.signalingState=newState;var event=new Event('signalingstatechange');this._dispatchEvent('signalingstatechange',event);};RTCPeerConnection.prototype._maybeFireNegotiationNeeded=function(){var pc=this;if(this.signalingState!=='stable'||this.needNegotiation===true){return;}
+this.needNegotiation=true;window.setTimeout(function(){if(pc.needNegotiation){pc.needNegotiation=false;var event=new Event('negotiationneeded');pc._dispatchEvent('negotiationneeded',event);}},0);};RTCPeerConnection.prototype._updateIceConnectionState=function(){var newState;var states={'new':0,closed:0,checking:0,connected:0,completed:0,disconnected:0,failed:0};this.transceivers.forEach(function(transceiver){if(transceiver.iceTransport&&!transceiver.rejected){states[transceiver.iceTransport.state]++;}});newState='new';if(states.failed>0){newState='failed';}else if(states.checking>0){newState='checking';}else if(states.disconnected>0){newState='disconnected';}else if(states.new>0){newState='new';}else if(states.connected>0){newState='connected';}else if(states.completed>0){newState='completed';}
+if(newState!==this.iceConnectionState){this.iceConnectionState=newState;var event=new Event('iceconnectionstatechange');this._dispatchEvent('iceconnectionstatechange',event);}};RTCPeerConnection.prototype._updateConnectionState=function(){var newState;var states={'new':0,closed:0,connecting:0,connected:0,completed:0,disconnected:0,failed:0};this.transceivers.forEach(function(transceiver){if(transceiver.iceTransport&&transceiver.dtlsTransport&&!transceiver.rejected){states[transceiver.iceTransport.state]++;states[transceiver.dtlsTransport.state]++;}});states.connected+=states.completed;newState='new';if(states.failed>0){newState='failed';}else if(states.connecting>0){newState='connecting';}else if(states.disconnected>0){newState='disconnected';}else if(states.new>0){newState='new';}else if(states.connected>0){newState='connected';}
+if(newState!==this.connectionState){this.connectionState=newState;var event=new Event('connectionstatechange');this._dispatchEvent('connectionstatechange',event);}};RTCPeerConnection.prototype.createOffer=function(){var pc=this;if(pc._isClosed){return Promise.reject(makeError('InvalidStateError','Can not call createOffer after close'));}
+var numAudioTracks=pc.transceivers.filter(function(t){return t.kind==='audio';}).length;var numVideoTracks=pc.transceivers.filter(function(t){return t.kind==='video';}).length;var offerOptions=arguments[0];if(offerOptions){if(offerOptions.mandatory||offerOptions.optional){throw new TypeError('Legacy mandatory/optional constraints not supported.');}
+if(offerOptions.offerToReceiveAudio!==undefined){if(offerOptions.offerToReceiveAudio===true){numAudioTracks=1;}else if(offerOptions.offerToReceiveAudio===false){numAudioTracks=0;}else{numAudioTracks=offerOptions.offerToReceiveAudio;}}
+if(offerOptions.offerToReceiveVideo!==undefined){if(offerOptions.offerToReceiveVideo===true){numVideoTracks=1;}else if(offerOptions.offerToReceiveVideo===false){numVideoTracks=0;}else{numVideoTracks=offerOptions.offerToReceiveVideo;}}}
+pc.transceivers.forEach(function(transceiver){if(transceiver.kind==='audio'){numAudioTracks--;if(numAudioTracks<0){transceiver.wantReceive=false;}}else if(transceiver.kind==='video'){numVideoTracks--;if(numVideoTracks<0){transceiver.wantReceive=false;}}});while(numAudioTracks>0||numVideoTracks>0){if(numAudioTracks>0){pc._createTransceiver('audio');numAudioTracks--;}
+if(numVideoTracks>0){pc._createTransceiver('video');numVideoTracks--;}}
+var sdp=SDPUtils.writeSessionBoilerplate(pc._sdpSessionId,pc._sdpSessionVersion++);pc.transceivers.forEach(function(transceiver,sdpMLineIndex){var track=transceiver.track;var kind=transceiver.kind;var mid=transceiver.mid||SDPUtils.generateIdentifier();transceiver.mid=mid;if(!transceiver.iceGatherer){transceiver.iceGatherer=pc._createIceGatherer(sdpMLineIndex,pc.usingBundle);}
+var localCapabilities=window.RTCRtpSender.getCapabilities(kind);if(edgeVersion<15019){localCapabilities.codecs=localCapabilities.codecs.filter(function(codec){return codec.name!=='rtx';});}
+localCapabilities.codecs.forEach(function(codec){if(codec.name==='H264'&&codec.parameters['level-asymmetry-allowed']===undefined){codec.parameters['level-asymmetry-allowed']='1';}
+if(transceiver.remoteCapabilities&&transceiver.remoteCapabilities.codecs){transceiver.remoteCapabilities.codecs.forEach(function(remoteCodec){if(codec.name.toLowerCase()===remoteCodec.name.toLowerCase()&&codec.clockRate===remoteCodec.clockRate){codec.preferredPayloadType=remoteCodec.payloadType;}});}});localCapabilities.headerExtensions.forEach(function(hdrExt){var remoteExtensions=transceiver.remoteCapabilities&&transceiver.remoteCapabilities.headerExtensions||[];remoteExtensions.forEach(function(rHdrExt){if(hdrExt.uri===rHdrExt.uri){hdrExt.id=rHdrExt.id;}});});var sendEncodingParameters=transceiver.sendEncodingParameters||[{ssrc:(2*sdpMLineIndex+1)*1001}];if(track){if(edgeVersion>=15019&&kind==='video'&&!sendEncodingParameters[0].rtx){sendEncodingParameters[0].rtx={ssrc:sendEncodingParameters[0].ssrc+1};}}
+if(transceiver.wantReceive){transceiver.rtpReceiver=new window.RTCRtpReceiver(transceiver.dtlsTransport,kind);}
+transceiver.localCapabilities=localCapabilities;transceiver.sendEncodingParameters=sendEncodingParameters;});if(pc._config.bundlePolicy!=='max-compat'){sdp+='a=group:BUNDLE '+pc.transceivers.map(function(t){return t.mid;}).join(' ')+'\r\n';}
+sdp+='a=ice-options:trickle\r\n';pc.transceivers.forEach(function(transceiver,sdpMLineIndex){sdp+=writeMediaSection(transceiver,transceiver.localCapabilities,'offer',transceiver.stream,pc._dtlsRole);sdp+='a=rtcp-rsize\r\n';if(transceiver.iceGatherer&&pc.iceGatheringState!=='new'&&(sdpMLineIndex===0||!pc.usingBundle)){transceiver.iceGatherer.getLocalCandidates().forEach(function(cand){cand.component=1;sdp+='a='+SDPUtils.writeCandidate(cand)+'\r\n';});if(transceiver.iceGatherer.state==='completed'){sdp+='a=end-of-candidates\r\n';}}});var desc=new window.RTCSessionDescription({type:'offer',sdp:sdp});return Promise.resolve(desc);};RTCPeerConnection.prototype.createAnswer=function(){var pc=this;if(pc._isClosed){return Promise.reject(makeError('InvalidStateError','Can not call createAnswer after close'));}
+if(!(pc.signalingState==='have-remote-offer'||pc.signalingState==='have-local-pranswer')){return Promise.reject(makeError('InvalidStateError','Can not call createAnswer in signalingState '+pc.signalingState));}
+var sdp=SDPUtils.writeSessionBoilerplate(pc._sdpSessionId,pc._sdpSessionVersion++);if(pc.usingBundle){sdp+='a=group:BUNDLE '+pc.transceivers.map(function(t){return t.mid;}).join(' ')+'\r\n';}
+sdp+='a=ice-options:trickle\r\n';var mediaSectionsInOffer=SDPUtils.getMediaSections(pc._remoteDescription.sdp).length;pc.transceivers.forEach(function(transceiver,sdpMLineIndex){if(sdpMLineIndex+1>mediaSectionsInOffer){return;}
+if(transceiver.rejected){if(transceiver.kind==='application'){if(transceiver.protocol==='DTLS/SCTP'){sdp+='m=application 0 DTLS/SCTP 5000\r\n';}else{sdp+='m=application 0 '+transceiver.protocol+' webrtc-datachannel\r\n';}}else if(transceiver.kind==='audio'){sdp+='m=audio 0 UDP/TLS/RTP/SAVPF 0\r\n'+'a=rtpmap:0 PCMU/8000\r\n';}else if(transceiver.kind==='video'){sdp+='m=video 0 UDP/TLS/RTP/SAVPF 120\r\n'+'a=rtpmap:120 VP8/90000\r\n';}
+sdp+='c=IN IP4 0.0.0.0\r\n'+'a=inactive\r\n'+'a=mid:'+transceiver.mid+'\r\n';return;}
+if(transceiver.stream){var localTrack;if(transceiver.kind==='audio'){localTrack=transceiver.stream.getAudioTracks()[0];}else if(transceiver.kind==='video'){localTrack=transceiver.stream.getVideoTracks()[0];}
+if(localTrack){if(edgeVersion>=15019&&transceiver.kind==='video'&&!transceiver.sendEncodingParameters[0].rtx){transceiver.sendEncodingParameters[0].rtx={ssrc:transceiver.sendEncodingParameters[0].ssrc+1};}}}
+var commonCapabilities=getCommonCapabilities(transceiver.localCapabilities,transceiver.remoteCapabilities);var hasRtx=commonCapabilities.codecs.filter(function(c){return c.name.toLowerCase()==='rtx';}).length;if(!hasRtx&&transceiver.sendEncodingParameters[0].rtx){delete transceiver.sendEncodingParameters[0].rtx;}
+sdp+=writeMediaSection(transceiver,commonCapabilities,'answer',transceiver.stream,pc._dtlsRole);if(transceiver.rtcpParameters&&transceiver.rtcpParameters.reducedSize){sdp+='a=rtcp-rsize\r\n';}});var desc=new window.RTCSessionDescription({type:'answer',sdp:sdp});return Promise.resolve(desc);};RTCPeerConnection.prototype.addIceCandidate=function(candidate){var pc=this;var sections;if(candidate&&!(candidate.sdpMLineIndex!==undefined||candidate.sdpMid)){return Promise.reject(new TypeError('sdpMLineIndex or sdpMid required'));}
+return new Promise(function(resolve,reject){if(!pc._remoteDescription){return reject(makeError('InvalidStateError','Can not add ICE candidate without a remote description'));}else if(!candidate||candidate.candidate===''){for(var j=0;j0?SDPUtils.parseCandidate(candidate.candidate):{};if(cand.protocol==='tcp'&&(cand.port===0||cand.port===9)){return resolve();}
+if(cand.component&&cand.component!==1){return resolve();}
+if(sdpMLineIndex===0||(sdpMLineIndex>0&&transceiver.iceTransport!==pc.transceivers[0].iceTransport)){if(!maybeAddCandidate(transceiver.iceTransport,cand)){return reject(makeError('OperationError','Can not add ICE candidate'));}}
+var candidateString=candidate.candidate.trim();if(candidateString.indexOf('a=')===0){candidateString=candidateString.substr(2);}
+sections=SDPUtils.getMediaSections(pc._remoteDescription.sdp);sections[sdpMLineIndex]+='a='+
+(cand.type?candidateString:'end-of-candidates')
++'\r\n';pc._remoteDescription.sdp=SDPUtils.getDescription(pc._remoteDescription.sdp)+
+sections.join('');}else{return reject(makeError('OperationError','Can not add ICE candidate'));}}
+resolve();});};RTCPeerConnection.prototype.getStats=function(selector){if(selector&&selector instanceof window.MediaStreamTrack){var senderOrReceiver=null;this.transceivers.forEach(function(transceiver){if(transceiver.rtpSender&&transceiver.rtpSender.track===selector){senderOrReceiver=transceiver.rtpSender;}else if(transceiver.rtpReceiver&&transceiver.rtpReceiver.track===selector){senderOrReceiver=transceiver.rtpReceiver;}});if(!senderOrReceiver){throw makeError('InvalidAccessError','Invalid selector.');}
+return senderOrReceiver.getStats();}
+var promises=[];this.transceivers.forEach(function(transceiver){['rtpSender','rtpReceiver','iceGatherer','iceTransport','dtlsTransport'].forEach(function(method){if(transceiver[method]){promises.push(transceiver[method].getStats());}});});return Promise.all(promises).then(function(allStats){var results=new Map();allStats.forEach(function(stats){stats.forEach(function(stat){results.set(stat.id,stat);});});return results;});};var ortcObjects=['RTCRtpSender','RTCRtpReceiver','RTCIceGatherer','RTCIceTransport','RTCDtlsTransport'];ortcObjects.forEach(function(ortcObjectName){var obj=window[ortcObjectName];if(obj&&obj.prototype&&obj.prototype.getStats){var nativeGetstats=obj.prototype.getStats;obj.prototype.getStats=function(){return nativeGetstats.apply(this).then(function(nativeStats){var mapStats=new Map();Object.keys(nativeStats).forEach(function(id){nativeStats[id].type=fixStatsType(nativeStats[id]);mapStats.set(id,nativeStats[id]);});return mapStats;});};}});var methods=['createOffer','createAnswer'];methods.forEach(function(method){var nativeMethod=RTCPeerConnection.prototype[method];RTCPeerConnection.prototype[method]=function(){var args=arguments;if(typeof args[0]==='function'||typeof args[1]==='function'){return nativeMethod.apply(this,[arguments[2]]).then(function(description){if(typeof args[0]==='function'){args[0].apply(null,[description]);}},function(error){if(typeof args[1]==='function'){args[1].apply(null,[error]);}});}
+return nativeMethod.apply(this,arguments);};});methods=['setLocalDescription','setRemoteDescription','addIceCandidate'];methods.forEach(function(method){var nativeMethod=RTCPeerConnection.prototype[method];RTCPeerConnection.prototype[method]=function(){var args=arguments;if(typeof args[1]==='function'||typeof args[2]==='function'){return nativeMethod.apply(this,arguments).then(function(){if(typeof args[1]==='function'){args[1].apply(null);}},function(error){if(typeof args[2]==='function'){args[2].apply(null,[error]);}});}
+return nativeMethod.apply(this,arguments);};});['getStats'].forEach(function(method){var nativeMethod=RTCPeerConnection.prototype[method];RTCPeerConnection.prototype[method]=function(){var args=arguments;if(typeof args[1]==='function'){return nativeMethod.apply(this,arguments).then(function(){if(typeof args[1]==='function'){args[1].apply(null);}});}
+return nativeMethod.apply(this,arguments);};});return RTCPeerConnection;};},{"sdp":17}],17:[function(require,module,exports){'use strict';var SDPUtils={};SDPUtils.generateIdentifier=function(){return Math.random().toString(36).substr(2,10);};SDPUtils.localCName=SDPUtils.generateIdentifier();SDPUtils.splitLines=function(blob){return blob.trim().split('\n').map(function(line){return line.trim();});};SDPUtils.splitSections=function(blob){var parts=blob.split('\nm=');return parts.map(function(part,index){return(index>0?'m='+part:part).trim()+'\r\n';});};SDPUtils.getDescription=function(blob){var sections=SDPUtils.splitSections(blob);return sections&§ions[0];};SDPUtils.getMediaSections=function(blob){var sections=SDPUtils.splitSections(blob);sections.shift();return sections;};SDPUtils.matchPrefix=function(blob,prefix){return SDPUtils.splitLines(blob).filter(function(line){return line.indexOf(prefix)===0;});};SDPUtils.parseCandidate=function(line){var parts;if(line.indexOf('a=candidate:')===0){parts=line.substring(12).split(' ');}else{parts=line.substring(10).split(' ');}
+var candidate={foundation:parts[0],component:parseInt(parts[1],10),protocol:parts[2].toLowerCase(),priority:parseInt(parts[3],10),ip:parts[4],address:parts[4],port:parseInt(parts[5],10),type:parts[7]};for(var i=8;i0?parts[0].split('/')[1]:'sendrecv',uri:parts[1]};};SDPUtils.writeExtmap=function(headerExtension){return'a=extmap:'+(headerExtension.id||headerExtension.preferredId)+
+(headerExtension.direction&&headerExtension.direction!=='sendrecv'?'/'+headerExtension.direction:'')+' '+headerExtension.uri+'\r\n';};SDPUtils.parseFmtp=function(line){var parsed={};var kv;var parts=line.substr(line.indexOf(' ')+1).split(';');for(var j=0;j-1){parts.attribute=line.substr(sp+1,colon-sp-1);parts.value=line.substr(colon+1);}else{parts.attribute=line.substr(sp+1);}
+return parts;};SDPUtils.parseSsrcGroup=function(line){var parts=line.substr(13).split(' ');return{semantics:parts.shift(),ssrcs:parts.map(function(ssrc){return parseInt(ssrc,10);})};};SDPUtils.getMid=function(mediaSection){var mid=SDPUtils.matchPrefix(mediaSection,'a=mid:')[0];if(mid){return mid.substr(6);}};SDPUtils.parseFingerprint=function(line){var parts=line.substr(14).split(' ');return{algorithm:parts[0].toLowerCase(),value:parts[1]};};SDPUtils.getDtlsParameters=function(mediaSection,sessionpart){var lines=SDPUtils.matchPrefix(mediaSection+sessionpart,'a=fingerprint:');return{role:'auto',fingerprints:lines.map(SDPUtils.parseFingerprint)};};SDPUtils.writeDtlsParameters=function(params,setupType){var sdp='a=setup:'+setupType+'\r\n';params.fingerprints.forEach(function(fp){sdp+='a=fingerprint:'+fp.algorithm+' '+fp.value+'\r\n';});return sdp;};SDPUtils.getIceParameters=function(mediaSection,sessionpart){var lines=SDPUtils.splitLines(mediaSection);lines=lines.concat(SDPUtils.splitLines(sessionpart));var iceParameters={usernameFragment:lines.filter(function(line){return line.indexOf('a=ice-ufrag:')===0;})[0].substr(12),password:lines.filter(function(line){return line.indexOf('a=ice-pwd:')===0;})[0].substr(10)};return iceParameters;};SDPUtils.writeIceParameters=function(params){return'a=ice-ufrag:'+params.usernameFragment+'\r\n'+'a=ice-pwd:'+params.password+'\r\n';};SDPUtils.parseRtpParameters=function(mediaSection){var description={codecs:[],headerExtensions:[],fecMechanisms:[],rtcp:[]};var lines=SDPUtils.splitLines(mediaSection);var mline=lines[0].split(' ');for(var i=3;i0?'9':'0';sdp+=' UDP/TLS/RTP/SAVPF ';sdp+=caps.codecs.map(function(codec){if(codec.preferredPayloadType!==undefined){return codec.preferredPayloadType;}
+return codec.payloadType;}).join(' ')+'\r\n';sdp+='c=IN IP4 0.0.0.0\r\n';sdp+='a=rtcp:9 IN IP4 0.0.0.0\r\n';caps.codecs.forEach(function(codec){sdp+=SDPUtils.writeRtpMap(codec);sdp+=SDPUtils.writeFmtp(codec);sdp+=SDPUtils.writeRtcpFb(codec);});var maxptime=0;caps.codecs.forEach(function(codec){if(codec.maxptime>maxptime){maxptime=codec.maxptime;}});if(maxptime>0){sdp+='a=maxptime:'+maxptime+'\r\n';}
+sdp+='a=rtcp-mux\r\n';if(caps.headerExtensions){caps.headerExtensions.forEach(function(extension){sdp+=SDPUtils.writeExtmap(extension);});}
+return sdp;};SDPUtils.parseRtpEncodingParameters=function(mediaSection){var encodingParameters=[];var description=SDPUtils.parseRtpParameters(mediaSection);var hasRed=description.fecMechanisms.indexOf('RED')!==-1;var hasUlpfec=description.fecMechanisms.indexOf('ULPFEC')!==-1;var ssrcs=SDPUtils.matchPrefix(mediaSection,'a=ssrc:').map(function(line){return SDPUtils.parseSsrcMedia(line);}).filter(function(parts){return parts.attribute==='cname';});var primarySsrc=ssrcs.length>0&&ssrcs[0].ssrc;var secondarySsrc;var flows=SDPUtils.matchPrefix(mediaSection,'a=ssrc-group:FID').map(function(line){var parts=line.substr(17).split(' ');return parts.map(function(part){return parseInt(part,10);});});if(flows.length>0&&flows[0].length>1&&flows[0][0]===primarySsrc){secondarySsrc=flows[0][1];}
+description.codecs.forEach(function(codec){if(codec.name.toUpperCase()==='RTX'&&codec.parameters.apt){var encParam={ssrc:primarySsrc,codecPayloadType:parseInt(codec.parameters.apt,10)};if(primarySsrc&&secondarySsrc){encParam.rtx={ssrc:secondarySsrc};}
+encodingParameters.push(encParam);if(hasRed){encParam=JSON.parse(JSON.stringify(encParam));encParam.fec={ssrc:primarySsrc,mechanism:hasUlpfec?'red+ulpfec':'red'};encodingParameters.push(encParam);}}});if(encodingParameters.length===0&&primarySsrc){encodingParameters.push({ssrc:primarySsrc});}
+var bandwidth=SDPUtils.matchPrefix(mediaSection,'b=');if(bandwidth.length){if(bandwidth[0].indexOf('b=TIAS:')===0){bandwidth=parseInt(bandwidth[0].substr(7),10);}else if(bandwidth[0].indexOf('b=AS:')===0){bandwidth=parseInt(bandwidth[0].substr(5),10)*1000*0.95
+-(50*40*8);}else{bandwidth=undefined;}
+encodingParameters.forEach(function(params){params.maxBitrate=bandwidth;});}
+return encodingParameters;};SDPUtils.parseRtcpParameters=function(mediaSection){var rtcpParameters={};var remoteSsrc=SDPUtils.matchPrefix(mediaSection,'a=ssrc:').map(function(line){return SDPUtils.parseSsrcMedia(line);}).filter(function(obj){return obj.attribute==='cname';})[0];if(remoteSsrc){rtcpParameters.cname=remoteSsrc.value;rtcpParameters.ssrc=remoteSsrc.ssrc;}
+var rsize=SDPUtils.matchPrefix(mediaSection,'a=rtcp-rsize');rtcpParameters.reducedSize=rsize.length>0;rtcpParameters.compound=rsize.length===0;var mux=SDPUtils.matchPrefix(mediaSection,'a=rtcp-mux');rtcpParameters.mux=mux.length>0;return rtcpParameters;};SDPUtils.parseMsid=function(mediaSection){var parts;var spec=SDPUtils.matchPrefix(mediaSection,'a=msid:');if(spec.length===1){parts=spec[0].substr(7).split(' ');return{stream:parts[0],track:parts[1]};}
+var planB=SDPUtils.matchPrefix(mediaSection,'a=ssrc:').map(function(line){return SDPUtils.parseSsrcMedia(line);}).filter(function(msidParts){return msidParts.attribute==='msid';});if(planB.length>0){parts=planB[0].value.split(' ');return{stream:parts[0],track:parts[1]};}};SDPUtils.generateSessionId=function(){return Math.random().toString().substr(2,21);};SDPUtils.writeSessionBoilerplate=function(sessId,sessVer,sessUser){var sessionId;var version=sessVer!==undefined?sessVer:2;if(sessId){sessionId=sessId;}else{sessionId=SDPUtils.generateSessionId();}
+var user=sessUser||'thisisadapterortc';return'v=0\r\n'+'o='+user+' '+sessionId+' '+version+' IN IP4 127.0.0.1\r\n'+'s=-\r\n'+'t=0 0\r\n';};SDPUtils.writeMediaSection=function(transceiver,caps,type,stream){var sdp=SDPUtils.writeRtpDescription(transceiver.kind,caps);sdp+=SDPUtils.writeIceParameters(transceiver.iceGatherer.getLocalParameters());sdp+=SDPUtils.writeDtlsParameters(transceiver.dtlsTransport.getLocalParameters(),type==='offer'?'actpass':'active');sdp+='a=mid:'+transceiver.mid+'\r\n';if(transceiver.direction){sdp+='a='+transceiver.direction+'\r\n';}else if(transceiver.rtpSender&&transceiver.rtpReceiver){sdp+='a=sendrecv\r\n';}else if(transceiver.rtpSender){sdp+='a=sendonly\r\n';}else if(transceiver.rtpReceiver){sdp+='a=recvonly\r\n';}else{sdp+='a=inactive\r\n';}
+if(transceiver.rtpSender){var msid='msid:'+stream.id+' '+
+transceiver.rtpSender.track.id+'\r\n';sdp+='a='+msid;sdp+='a=ssrc:'+transceiver.sendEncodingParameters[0].ssrc+' '+msid;if(transceiver.sendEncodingParameters[0].rtx){sdp+='a=ssrc:'+transceiver.sendEncodingParameters[0].rtx.ssrc+' '+msid;sdp+='a=ssrc-group:FID '+
+transceiver.sendEncodingParameters[0].ssrc+' '+
+transceiver.sendEncodingParameters[0].rtx.ssrc+'\r\n';}}
+sdp+='a=ssrc:'+transceiver.sendEncodingParameters[0].ssrc+' cname:'+SDPUtils.localCName+'\r\n';if(transceiver.rtpSender&&transceiver.sendEncodingParameters[0].rtx){sdp+='a=ssrc:'+transceiver.sendEncodingParameters[0].rtx.ssrc+' cname:'+SDPUtils.localCName+'\r\n';}
+return sdp;};SDPUtils.getDirection=function(mediaSection,sessionpart){var lines=SDPUtils.splitLines(mediaSection);for(var i=0;iai_addr->sa_family != AF_INET) {
+ freeaddrinfo(ai);
exit(1);
}
+ freeaddrinfo(ai);
exit(0);
}
],[
@@ -92,12 +95,15 @@ AC_DEFUN([APR_CHECK_GETADDRINFO_ADDRCONFIG], [
int main(int argc, char **argv) {
struct addrinfo hints, *ai;
+ int ret;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_ADDRCONFIG;
- return getaddrinfo("localhost", NULL, &hints, &ai) != 0;
+ ret = getaddrinfo("localhost", NULL, &hints, &ai) != 0;
+ freeaddrinfo(ai);
+ return ret;
}], [apr_cv_gai_addrconfig=yes],
[apr_cv_gai_addrconfig=no],
[apr_cv_gai_addrconfig=no])])
diff --git a/libs/libdingaling/configure.ac b/libs/libdingaling/configure.ac
index 57aa712c84..0d7e832fa1 100755
--- a/libs/libdingaling/configure.ac
+++ b/libs/libdingaling/configure.ac
@@ -136,7 +136,6 @@ AC_STRUCT_TM
# Checks for library functions.
AC_PROG_GCC_TRADITIONAL
-AC_FUNC_MALLOC
AC_TYPE_SIGNAL
AC_FUNC_STRFTIME
#AC_CHECK_FUNCS([gethostname gettimeofday localtime_r memmove memset socket strcasecmp strchr strdup strncasecmp strstr])
diff --git a/libs/libteletone/src/libteletone_detect.c b/libs/libteletone/src/libteletone_detect.c
index f25fea73ff..7debc553dd 100644
--- a/libs/libteletone/src/libteletone_detect.c
+++ b/libs/libteletone/src/libteletone_detect.c
@@ -317,11 +317,10 @@ TELETONE_API(teletone_hit_type_t) teletone_dtmf_detect (teletone_dtmf_detect_sta
int sample;
int best_row;
int best_col;
- char hit;
+ char hit = 0;
int limit;
teletone_hit_type_t r = 0;
- hit = 0;
for (sample = 0; sample < samples; sample = limit) {
/* BLOCK_LEN is optimised to meet the DTMF specs. */
if ((samples - sample) >= (BLOCK_LEN - dtmf_detect_state->current_sample)) {
diff --git a/libs/libteletone/src/libteletone_generate.c b/libs/libteletone/src/libteletone_generate.c
index f052c1fe9e..94ae14d228 100644
--- a/libs/libteletone/src/libteletone_generate.c
+++ b/libs/libteletone/src/libteletone_generate.c
@@ -256,7 +256,9 @@ TELETONE_API(int) teletone_mux_tones(teletone_generation_session_t *ts, teletone
int32_t s = teletone_dds_state_modulate_sample(&tones[i], 0);
sample += s;
}
- sample /= freqlen;
+ if (freqlen) {
+ sample /= freqlen;
+ }
ts->buffer[ts->samples] = (teletone_audio_t)sample;
for (c = 1; c < ts->channels; c++) {
diff --git a/libs/libzrtp/configure.ac b/libs/libzrtp/configure.ac
index 251c51acc1..5ac158109c 100644
--- a/libs/libzrtp/configure.ac
+++ b/libs/libzrtp/configure.ac
@@ -66,7 +66,6 @@ AC_CHECK_TYPES([int8_t,uint8_t,int16_t,uint16_t,int32_t,uint32_t,uint64_t,int64_
AC_C_CONST
# Checks for library functions.
-AC_FUNC_MALLOC
AC_CHECK_FUNCS([memset memcpy malloc free])
AC_CHECK_FUNCS([usleep nanosleep])
AC_CHECK_FUNCS([fopen fread])
diff --git a/libs/sofia-sip/.update b/libs/sofia-sip/.update
index e94c5432f4..ec04f46051 100644
--- a/libs/sofia-sip/.update
+++ b/libs/sofia-sip/.update
@@ -1 +1 @@
-Wed Feb 21 15:29:04 CST 2018
+Mon Feb 18 16:55:02 EST 2019
diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/nua_session.c b/libs/sofia-sip/libsofia-sip-ua/nua/nua_session.c
index d9261324d5..21c3d65af1 100644
--- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_session.c
+++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_session.c
@@ -940,12 +940,12 @@ static int nua_session_client_response(nua_client_request_t *cr,
char const *received = NULL;
#define LOG3(m) \
- SU_DEBUG_3(("nua(%p): %s: %s %s in %u %s\n", \
+ SU_DEBUG_3(("nua(%p): %s: %s %s in %u %s (%u)\n", \
(void *)nh, cr->cr_method_name, (m), \
- received ? received : "SDP", status, phrase))
+ received ? received : "SDP", status, phrase, cr->cr_answer_recv))
#define LOG5(m) \
- SU_DEBUG_5(("nua(%p): %s: %s %s in %u %s\n", \
- (void *)nh, cr->cr_method_name, (m), received, status, phrase))
+ SU_DEBUG_5(("nua(%p): %s: %s %s in %u %s (%u)\n", \
+ (void *)nh, cr->cr_method_name, (m), received, status, phrase, cr->cr_answer_recv))
retry:
@@ -954,12 +954,16 @@ static int nua_session_client_response(nua_client_request_t *cr,
else if (!session_get_description(sip, &sdp, &len))
/* No SDP */;
else if (cr->cr_answer_recv) {
- /* Ignore spurious answers after completing O/A */
- //LOG3("ignoring duplicate");
- //sdp = NULL;
- // we need to make sure its *actually* a dup, so we can't assume for now.
- cr->cr_answer_recv = 0;
- goto retry;
+ if (cr->cr_answer_recv > status) {
+ LOG3("status is older than previous answer, ignoring");
+ sdp = NULL;
+ return 0;
+ } else {
+ // we need to make sure its *actually* a dup, so we can't assume for now.
+ LOG3("multiple answers received, processing");
+ cr->cr_answer_recv = 0;
+ goto retry;
+ }
}
else if (cr->cr_offer_sent) {
/* case 1: answer to our offer */
diff --git a/libs/sofia-sip/libsofia-sip-ua/sdp/sdp_parse.c b/libs/sofia-sip/libsofia-sip-ua/sdp/sdp_parse.c
index 3b1190ee5f..bb9221f109 100644
--- a/libs/sofia-sip/libsofia-sip-ua/sdp/sdp_parse.c
+++ b/libs/sofia-sip/libsofia-sip-ua/sdp/sdp_parse.c
@@ -1546,7 +1546,7 @@ static void parse_payload(sdp_parser_t *p, char *r, sdp_rtpmap_t **result)
else if (p->pr_config && r[0] == '*' && (r[1] == ' ' || r[1] == '\0')) {
PARSE_ALLOC(p, sdp_rtpmap_t, rm);
- *result = rm; result = &rm->rm_next;
+ *result = rm;
rm->rm_predef = 1;
rm->rm_any = 1;
diff --git a/libs/sofia-sip/libsofia-sip-ua/sip/sip_status.c b/libs/sofia-sip/libsofia-sip-ua/sip/sip_status.c
index f75da713eb..2ea82963e6 100644
--- a/libs/sofia-sip/libsofia-sip-ua/sip/sip_status.c
+++ b/libs/sofia-sip/libsofia-sip-ua/sip/sip_status.c
@@ -104,6 +104,7 @@ char const
sip_603_Decline[] = "Decline",
sip_604_Does_not_exist_anywhere[] = "Does Not Exist Anywhere",
sip_606_Not_acceptable[] = "Not Acceptable",
+ sip_607_Unwanted[] = "Unwanted",
sip_687_Dialog_terminated[] = "Dialog Terminated"
;
@@ -191,6 +192,7 @@ char const *sip_status_phrase(int status)
case 603: return sip_603_Decline;
case 604: return sip_604_Does_not_exist_anywhere;
case 606: return sip_606_Not_acceptable;
+ case 607: return sip_607_Unwanted;
case 687: return sip_687_Dialog_terminated;
}
diff --git a/libs/sofia-sip/libsofia-sip-ua/sip/sip_util.c b/libs/sofia-sip/libsofia-sip-ua/sip/sip_util.c
index 051ba5ae39..e5ef095eb0 100644
--- a/libs/sofia-sip/libsofia-sip-ua/sip/sip_util.c
+++ b/libs/sofia-sip/libsofia-sip-ua/sip/sip_util.c
@@ -1422,6 +1422,15 @@ int sip_response_terminates_dialog(int response_code,
*/
*return_graceful_terminate_usage = 0;
return 0;
+
+ case 607: /** @par 607 Unwanted
+
+ This response is similar to 603, except it informs the caller
+ that the call is unwanted and may be blacklisted. Added by
+ RFC-8197
+ */
+ *return_graceful_terminate_usage = 0;
+ return 0;
}
/* Do not change graceful_terminate */
diff --git a/libs/sofia-sip/libsofia-sip-ua/sip/sofia-sip/sip_status.h b/libs/sofia-sip/libsofia-sip-ua/sip/sofia-sip/sip_status.h
index c5a738927f..b10d165e3a 100644
--- a/libs/sofia-sip/libsofia-sip-ua/sip/sofia-sip/sip_status.h
+++ b/libs/sofia-sip/libsofia-sip-ua/sip/sofia-sip/sip_status.h
@@ -169,6 +169,8 @@ SOFIAPUBFUN char const *sip_status_phrase(int status);
#define SIP_604_DOES_NOT_EXIST_ANYWHERE 604, sip_604_Does_not_exist_anywhere
/** 606 Not Acceptable @HIDE */
#define SIP_606_NOT_ACCEPTABLE 606, sip_606_Not_acceptable
+/** 607 Unwanted @HIDE */
+#define SIP_607_UNWANTED 607, sip_607_Unwanted
/** 687 Dialog terminated @HIDE */
#define SIP_687_DIALOG_TERMINATED 687, sip_687_Dialog_terminated
@@ -238,6 +240,7 @@ SOFIAPUBVAR char const sip_600_Busy_everywhere[];
SOFIAPUBVAR char const sip_603_Decline[];
SOFIAPUBVAR char const sip_604_Does_not_exist_anywhere[];
SOFIAPUBVAR char const sip_606_Not_acceptable[];
+SOFIAPUBVAR char const sip_607_Unwanted[];
SOFIAPUBVAR char const sip_687_Dialog_terminated[];
SOFIA_END_DECLS
diff --git a/libs/sofia-sip/libsofia-sip-ua/sip/torture_sip.c b/libs/sofia-sip/libsofia-sip-ua/sip/torture_sip.c
index 2927380728..00514fbd2c 100644
--- a/libs/sofia-sip/libsofia-sip-ua/sip/torture_sip.c
+++ b/libs/sofia-sip/libsofia-sip-ua/sip/torture_sip.c
@@ -1511,6 +1511,7 @@ static int response_phrase_test(void)
{ SIP_603_DECLINE },
{ SIP_604_DOES_NOT_EXIST_ANYWHERE },
{ SIP_606_NOT_ACCEPTABLE },
+ { SIP_607_UNWANTED },
{ 0, NULL }
};
int i;
diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/tport_logging.c b/libs/sofia-sip/libsofia-sip-ua/tport/tport_logging.c
index 1c889da5f6..53dea29060 100644
--- a/libs/sofia-sip/libsofia-sip-ua/tport/tport_logging.c
+++ b/libs/sofia-sip/libsofia-sip-ua/tport/tport_logging.c
@@ -386,7 +386,7 @@ void tport_dump_iovec(tport_t const *self, msg_t *msg,
size_t len = iov[i].mv_len;
if (len > n)
len = n;
- if (fwrite(iov[i].mv_base, len, 1, mr->mr_dump_file) != len)
+ if (fwrite(iov[i].mv_base, len, 1, mr->mr_dump_file) != 1)
break;
n -= len;
}
@@ -732,7 +732,7 @@ int tport_capt_msg_hepv3 (tport_t const *self, msg_t *msg, size_t n,
/* Capture ID */
hg->capt_id.chunk.vendor_id = htons(0x0000);
hg->capt_id.chunk.type_id = htons(0x000c);
- hg->capt_id.data = htons(mr->mr_agent_id);
+ hg->capt_id.data = htonl(mr->mr_agent_id);
hg->capt_id.chunk.length = htons(sizeof(hg->capt_id));
diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_tls.c b/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_tls.c
index 6165c73fec..a9dd26cf0c 100644
--- a/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_tls.c
+++ b/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_tls.c
@@ -468,6 +468,9 @@ int tport_tls_recv(tport_t *self)
if (self->tp_master->mr_dump_file)
tport_dump_iovec(self, msg, n, iovec, veclen, "recv", "from");
+ if (self->tp_master->mr_capt_sock)
+ tport_capt_msg(self, msg, n, iovec, veclen, "recv");
+
/* Mark buffer as used */
msg_recv_commit(msg, N, 0);
diff --git a/libs/spandsp/configure.ac b/libs/spandsp/configure.ac
index baef75ef69..92354bd246 100644
--- a/libs/spandsp/configure.ac
+++ b/libs/spandsp/configure.ac
@@ -154,11 +154,6 @@ AC_FUNC_VPRINTF
AC_FUNC_MEMCMP
AC_FUNC_MEMMOVE
-if test "${ax_cv_c_compiler_vendor}" = "gnu"
- then
- AC_FUNC_REALLOC
- AC_FUNC_MALLOC
-fi
AC_FUNC_SELECT_ARGTYPES
AX_C99_FUNC_LRINT
diff --git a/libs/unimrcp/configure.ac b/libs/unimrcp/configure.ac
index b13c0fab4c..851f56d71b 100644
--- a/libs/unimrcp/configure.ac
+++ b/libs/unimrcp/configure.ac
@@ -190,6 +190,18 @@ AC_ARG_ENABLE(test-suites,
[enable_test_suites="$enableval"],
[enable_test_suites="no"])
+# Enable clang address sanitizer bit build
+AC_ARG_ENABLE(address_sanitizer,
+ [AC_HELP_STRING([--enable-address-sanitizer],[build with address sanitizer])],
+ [enable_address_sanitizer="$enable_address_sanitizer"],
+ [enable_address_sanitizer="no"])
+
+if test "${enable_address_sanitizer}" = "yes"; then
+ APR_ADDTO(CFLAGS, -fsanitize=address -fno-omit-frame-pointer)
+ APR_ADDTO(CXXFLAGS, -fsanitize=address -fno-omit-frame-pointer)
+ APR_ADDTO(LDFLAGS, -fsanitize=address)
+fi
+
AM_CONDITIONAL([TEST_SUITES],[test "${enable_test_suites}" != "no"])
AM_CONDITIONAL(ISMAC, [test `uname -s` = Darwin])
diff --git a/libs/win32/ffmpeg/ffmpeg.2017.vcxproj b/libs/win32/ffmpeg/ffmpeg.2017.vcxproj
index a8c70cd22a..82a1d67c45 100644
--- a/libs/win32/ffmpeg/ffmpeg.2017.vcxproj
+++ b/libs/win32/ffmpeg/ffmpeg.2017.vcxproj
@@ -1,12 +1,20 @@
-
- Debug
+
+ Debug-openh264
x64
-
- Release
+
+ Debug-x264
+ x64
+
+
+ Release-openh264
+ x64
+
+
+ Release-x264
x64
@@ -16,39 +24,55 @@
10.0.17134.0
{BC1FD72E-1CD5-4525-A7F5-17C5740BFDED}
-
+
+
-
+
StaticLibrary
v141
MultiByte
false
yasm.exe -f x64 -I./../../ffmpeg-$(ffmpegVersion)/ -I./../../ffmpeg-$(ffmpegVersion)/include_x64 -P.\..\..\libs\ffmpeg-$(ffmpegVersion)\include_x64\config.asm
-
+
StaticLibrary
v141
MultiByte
yasm.exe -f x64 -I./../../ffmpeg-$(ffmpegVersion)/ -I./../../ffmpeg-$(ffmpegVersion)/include_x64 -P.\..\..\libs\ffmpeg-$(ffmpegVersion)\include_x64\config.asm
-
+
+ StaticLibrary
v141
+ MultiByte
+ false
+ yasm.exe -f x64 -I./../../ffmpeg-$(ffmpegVersion)/ -I./../../ffmpeg-$(ffmpegVersion)/include_openh264_x64 -P.\..\..\libs\ffmpeg-$(ffmpegVersion)\include_openh264_x64\config.asm
-
+
+ StaticLibrary
v141
+ MultiByte
+ yasm.exe -f x64 -I./../../ffmpeg-$(ffmpegVersion)/ -I./../../ffmpeg-$(ffmpegVersion)/include_openh264_x64 -P.\..\..\libs\ffmpeg-$(ffmpegVersion)\include_openh264_x64\config.asm
-
+
-
+
+
+
+
+
+
+
+
+
@@ -57,7 +81,7 @@
BUILDING_avdevice;BUILDING_avfilter;BUILDING_avformat;BUILDING_avcodec;BUILDING_avresample;BUILDING_swresample;BUILDING_swscale;BUILDING_avutil;%(PreprocessorDefinitions)
-
+
X64
@@ -75,7 +99,25 @@
true
-
+
+
+ X64
+
+
+ MaxSpeed
+ "..\..\ffmpeg-$(ffmpegVersion)\include_openh264_x64";"..\..\ffmpeg-$(ffmpegVersion)";"..\..\libx264";"..\..\libx264\SMP";%(AdditionalIncludeDirectories)
+ WIN32;_DEBUG;HAVE_AV_CONFIG_H;_ISOC99_SOURCE;_FILE_OFFSET_BITS=64;_LARGEFILE_SOURCE;_USE_MATH_DEFINES;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WIN32_WINNT=0x0502;%(PreprocessorDefinitions)
+ MultiThreadedDebug
+ Level3
+ false
+ NotUsing
+ false
+ 4267;4334;4101;4018;4146;4244;4305;4554;%(DisableSpecificWarnings)
+ true
+ true
+
+
+
X64
@@ -93,5410 +135,5437 @@
Full
+
+
+ X64
+
+
+ "..\..\ffmpeg-$(ffmpegVersion)\include_openh264_x64";"..\..\ffmpeg-$(ffmpegVersion)";"..\..\libx264";"..\..\libx264\SMP";%(AdditionalIncludeDirectories)
+ WIN32;NDEBUG;HAVE_AV_CONFIG_H;_ISOC99_SOURCE;_FILE_OFFSET_BITS=64;_LARGEFILE_SOURCE;_USE_MATH_DEFINES;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WIN32_WINNT=0x0502;%(PreprocessorDefinitions)
+ MultiThreadedDebug
+ Level3
+ false
+ NotUsing
+ false
+ 4267;4334;4101;4018;4146;4244;4305;4554;%(DisableSpecificWarnings)
+ true
+ true
+ Full
+
+
<_ProjectFileVersion>10.0.30319.1
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
-
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
Assembling %(Filename)%(Extension)
@@ -5504,7 +5573,7 @@
$(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
Assembling %(Filename)%(Extension)
@@ -5512,7 +5581,7 @@
$(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
Assembling %(Filename)%(Extension)
@@ -5520,7 +5589,7 @@
$(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
- $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
Assembling %(Filename)%(Extension)
@@ -6027,7 +6096,7 @@
$(YasmCommand) -I %(RelativeDir) -o $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj "%(FullPath)"
$(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
-
+
Assembling %(Filename)%(Extension)
$(YasmCommand) -I %(RelativeDir) -o $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj "%(FullPath)"
$(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
@@ -6173,11 +6242,17 @@
$(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_')).%(FileName).obj
-
-
- {20179127-853b-4fe9-b7c0-9e817e6a3a72}
-
-
+
+
+
+
+ {20179127-853b-4fe9-b7c0-9e817e6a3a72}
+
+
+
+
+
+
diff --git a/libs/win32/libvpx/libvpx.2017.vcxproj b/libs/win32/libvpx/libvpx.2017.vcxproj
index 95942997c8..17e841c345 100644
--- a/libs/win32/libvpx/libvpx.2017.vcxproj
+++ b/libs/win32/libvpx/libvpx.2017.vcxproj
@@ -1,1552 +1,1556 @@
-
-
-
-
- Debug
- Win32
-
-
- Release
- Win32
-
-
- Debug
- x64
-
-
- Release
- x64
-
-
-
- libvpx
- {DCE19DAF-69AC-46DB-B14A-39F0FAA5DB74}
- libvpx
- ManagedCProj
-
-
-
-
- StaticLibrary
- v141
- Unicode
- true
-
-
- StaticLibrary
- v141
- Unicode
-
-
- StaticLibrary
- v141
- Unicode
- true
-
-
- StaticLibrary
- v141
- Unicode
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Disabled
- ".";".\include_x86";"../../libvpx";%(AdditionalIncludeDirectories)
- WIN32;_DEBUG;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;;%(PreprocessorDefinitions)
- MultiThreadedDebug
- Level3
- false
- NotUsing
- false
-
-
-
-
- Speed
- MaxSpeed
- ".";".\include_x86";"../../libvpx";%(AdditionalIncludeDirectories)
- WIN32;NDEBUG;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;;%(PreprocessorDefinitions)
- MultiThreaded
- Level3
- false
- NotUsing
- false
-
-
-
-
-
-
-
-
-
-
-
-
- Disabled
- ".";".\include_x64";"..\..\libvpx";%(AdditionalIncludeDirectories)
- WIN32;_DEBUG;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;;%(PreprocessorDefinitions)
- MultiThreadedDebug
- Level3
- false
- NotUsing
- false
-
-
-
-
- Speed
- MaxSpeed
- ".";".\include_x64";"..\..\libvpx";%(AdditionalIncludeDirectories)
- WIN32;NDEBUG;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;;%(PreprocessorDefinitions)
- MultiThreaded
- Level3
- false
- NotUsing
- false
-
-
-
-
- $(IntDir)vpx_src_vpx_decoder.obj
-
-
- $(IntDir)vpx_src_vpx_encoder.obj
-
-
- $(IntDir)vpx_src_vpx_codec.obj
-
-
- $(IntDir)vpx_src_vpx_image.obj
-
-
- $(IntDir)vpx_mem_vpx_mem.obj
-
-
- $(IntDir)vpx_scale_generic_vpx_scale.obj
-
-
- $(IntDir)vpx_scale_generic_yv12config.obj
-
-
- $(IntDir)vpx_scale_generic_yv12extend.obj
-
-
- $(IntDir)vpx_scale_generic_gen_scalers.obj
-
-
- $(IntDir)vpx_scale_vpx_scale_rtcd.obj
-
-
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_ports_emms_asm.obj
- $(IntDir)vpx_ports_emms_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_ports_emms_asm.obj
- $(IntDir)vpx_ports_emms_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_ports_emms_asm.obj
- $(IntDir)vpx_ports_emms_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_ports_emms_asm.obj
- $(IntDir)vpx_ports_emms_asm.obj
-
-
- $(IntDir)vpx_dsp_prob.obj
-
-
- $(IntDir)vpx_dsp_bitwriter.obj
-
-
- $(IntDir)vpx_dsp_bitwriter_buffer.obj
-
-
- $(IntDir)vpx_dsp_psnr.obj
-
-
- $(IntDir)vpx_dsp_bitreader.obj
-
-
- $(IntDir)vpx_dsp_bitreader_buffer.obj
-
-
- $(IntDir)vpx_dsp_intrapred.obj
-
-
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_intrapred_sse2_asm.obj
- $(IntDir)vpx_dsp_x86_intrapred_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_intrapred_sse2_asm.obj
- $(IntDir)vpx_dsp_x86_intrapred_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_intrapred_sse2_asm.obj
- $(IntDir)vpx_dsp_x86_intrapred_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_intrapred_sse2_asm.obj
- $(IntDir)vpx_dsp_x86_intrapred_sse2_asm.obj
-
-
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_intrapred_ssse3_asm.obj
- $(IntDir)vpx_dsp_x86_intrapred_ssse3_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_intrapred_ssse3_asm.obj
- $(IntDir)vpx_dsp_x86_intrapred_ssse3_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_intrapred_ssse3_asm.obj
- $(IntDir)vpx_dsp_x86_intrapred_ssse3_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_intrapred_ssse3_asm.obj
- $(IntDir)vpx_dsp_x86_intrapred_ssse3_asm.obj
-
-
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_vpx_subpixel_8t_ssse3_asm.obj
- $(IntDir)vpx_dsp_x86_vpx_subpixel_8t_ssse3_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_vpx_subpixel_8t_ssse3_asm.obj
- $(IntDir)vpx_dsp_x86_vpx_subpixel_8t_ssse3_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_vpx_subpixel_8t_ssse3_asm.obj
- $(IntDir)vpx_dsp_x86_vpx_subpixel_8t_ssse3_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_vpx_subpixel_8t_ssse3_asm.obj
- $(IntDir)vpx_dsp_x86_vpx_subpixel_8t_ssse3_asm.obj
-
-
- $(IntDir)vpx_dsp_add_noise.obj
-
-
- $(IntDir)vpx_dsp_deblock.obj
-
-
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_add_noise_sse2_asm.obj
- $(IntDir)vpx_dsp_x86_add_noise_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_add_noise_sse2_asm.obj
- $(IntDir)vpx_dsp_x86_add_noise_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_add_noise_sse2_asm.obj
- $(IntDir)vpx_dsp_x86_add_noise_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_add_noise_sse2_asm.obj
- $(IntDir)vpx_dsp_x86_add_noise_sse2_asm.obj
-
-
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_deblock_sse2_asm.obj
- $(IntDir)vpx_dsp_x86_deblock_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_deblock_sse2_asm.obj
- $(IntDir)vpx_dsp_x86_deblock_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_deblock_sse2_asm.obj
- $(IntDir)vpx_dsp_x86_deblock_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_deblock_sse2_asm.obj
- $(IntDir)vpx_dsp_x86_deblock_sse2_asm.obj
-
-
- $(IntDir)vpx_dsp_vpx_convolve.obj
-
-
- $(IntDir)vpx_dsp_x86_vpx_asm_stubs.obj
-
-
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_vpx_subpixel_8t_sse2_asm.obj
- $(IntDir)vpx_dsp_x86_vpx_subpixel_8t_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_vpx_subpixel_8t_sse2_asm.obj
- $(IntDir)vpx_dsp_x86_vpx_subpixel_8t_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_vpx_subpixel_8t_sse2_asm.obj
- $(IntDir)vpx_dsp_x86_vpx_subpixel_8t_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_vpx_subpixel_8t_sse2_asm.obj
- $(IntDir)vpx_dsp_x86_vpx_subpixel_8t_sse2_asm.obj
-
-
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_vpx_subpixel_bilinear_sse2_asm.obj
- $(IntDir)vpx_dsp_x86_vpx_subpixel_bilinear_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_vpx_subpixel_bilinear_sse2_asm.obj
- $(IntDir)vpx_dsp_x86_vpx_subpixel_bilinear_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_vpx_subpixel_bilinear_sse2_asm.obj
- $(IntDir)vpx_dsp_x86_vpx_subpixel_bilinear_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_vpx_subpixel_bilinear_sse2_asm.obj
- $(IntDir)vpx_dsp_x86_vpx_subpixel_bilinear_sse2_asm.obj
-
-
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_vpx_subpixel_bilinear_ssse3_asm.obj
- $(IntDir)vpx_dsp_x86_vpx_subpixel_bilinear_ssse3_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_vpx_subpixel_bilinear_ssse3_asm.obj
- $(IntDir)vpx_dsp_x86_vpx_subpixel_bilinear_ssse3_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_vpx_subpixel_bilinear_ssse3_asm.obj
- $(IntDir)vpx_dsp_x86_vpx_subpixel_bilinear_ssse3_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_vpx_subpixel_bilinear_ssse3_asm.obj
- $(IntDir)vpx_dsp_x86_vpx_subpixel_bilinear_ssse3_asm.obj
-
-
- $(IntDir)vpx_dsp_x86_vpx_subpixel_8t_intrin_avx2.obj
- /arch:AVX
-
-
- $(IntDir)vpx_dsp_x86_vpx_subpixel_8t_intrin_ssse3.obj
-
-
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_vpx_convolve_copy_sse2_asm.obj
- $(IntDir)vpx_dsp_x86_vpx_convolve_copy_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_vpx_convolve_copy_sse2_asm.obj
- $(IntDir)vpx_dsp_x86_vpx_convolve_copy_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_vpx_convolve_copy_sse2_asm.obj
- $(IntDir)vpx_dsp_x86_vpx_convolve_copy_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_vpx_convolve_copy_sse2_asm.obj
- $(IntDir)vpx_dsp_x86_vpx_convolve_copy_sse2_asm.obj
-
-
- $(IntDir)vpx_dsp_loopfilter.obj
-
-
- $(IntDir)vpx_dsp_x86_loopfilter_sse2.obj
-
-
- $(IntDir)vpx_dsp_x86_loopfilter_avx2.obj
- /arch:AVX
-
-
- $(IntDir)vpx_dsp_fwd_txfm.obj
-
-
- $(IntDir)vpx_dsp_x86_fwd_txfm_sse2.obj
-
-
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_fwd_txfm_ssse3_x86_64_asm.obj
- $(IntDir)vpx_dsp_x86_fwd_txfm_ssse3_x86_64_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_fwd_txfm_ssse3_x86_64_asm.obj
- $(IntDir)vpx_dsp_x86_fwd_txfm_ssse3_x86_64_asm.obj
-
-
- $(IntDir)vpx_dsp_x86_fwd_txfm_avx2.obj
- /arch:AVX
-
-
- $(IntDir)vpx_dsp_inv_txfm.obj
-
-
- $(IntDir)vpx_dsp_x86_inv_txfm_sse2.obj
-
-
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_inv_wht_sse2_asm.obj
- $(IntDir)vpx_dsp_x86_inv_wht_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_inv_wht_sse2_asm.obj
- $(IntDir)vpx_dsp_x86_inv_wht_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_inv_wht_sse2_asm.obj
- $(IntDir)vpx_dsp_x86_inv_wht_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_inv_wht_sse2_asm.obj
- $(IntDir)vpx_dsp_x86_inv_wht_sse2_asm.obj
-
-
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_inv_txfm_ssse3_x86_64_asm.obj
- $(IntDir)vpx_dsp_x86_inv_txfm_ssse3_x86_64_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_inv_txfm_ssse3_x86_64_asm.obj
- $(IntDir)vpx_dsp_x86_inv_txfm_ssse3_x86_64_asm.obj
-
-
- $(IntDir)vpx_dsp_quantize.obj
-
-
- $(IntDir)vpx_dsp_x86_quantize_sse2.obj
-
-
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_quantize_ssse3_x86_64_asm.obj
- $(IntDir)vpx_dsp_x86_quantize_ssse3_x86_64_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_quantize_ssse3_x86_64_asm.obj
- $(IntDir)vpx_dsp_x86_quantize_ssse3_x86_64_asm.obj
-
-
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_quantize_avx_x86_64_asm.obj
- $(IntDir)vpx_dsp_x86_quantize_avx_x86_64_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_quantize_avx_x86_64_asm.obj
- $(IntDir)vpx_dsp_x86_quantize_avx_x86_64_asm.obj
-
-
- $(IntDir)vpx_dsp_avg.obj
-
-
- $(IntDir)vpx_dsp_x86_avg_intrin_sse2.obj
-
-
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_avg_ssse3_x86_64_asm.obj
- $(IntDir)vpx_dsp_x86_avg_ssse3_x86_64_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_avg_ssse3_x86_64_asm.obj
- $(IntDir)vpx_dsp_x86_avg_ssse3_x86_64_asm.obj
-
-
- $(IntDir)vpx_dsp_sad.obj
-
-
- $(IntDir)vpx_dsp_subtract.obj
-
-
- $(IntDir)vpx_dsp_sum_squares.obj
-
-
- $(IntDir)vpx_dsp_x86_sum_squares_sse2.obj
-
-
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_sad_sse3_asm.obj
- $(IntDir)vpx_dsp_x86_sad_sse3_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_sad_sse3_asm.obj
- $(IntDir)vpx_dsp_x86_sad_sse3_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_sad_sse3_asm.obj
- $(IntDir)vpx_dsp_x86_sad_sse3_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_sad_sse3_asm.obj
- $(IntDir)vpx_dsp_x86_sad_sse3_asm.obj
-
-
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_sad_ssse3_asm.obj
- $(IntDir)vpx_dsp_x86_sad_ssse3_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_sad_ssse3_asm.obj
- $(IntDir)vpx_dsp_x86_sad_ssse3_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_sad_ssse3_asm.obj
- $(IntDir)vpx_dsp_x86_sad_ssse3_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_sad_ssse3_asm.obj
- $(IntDir)vpx_dsp_x86_sad_ssse3_asm.obj
-
-
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_sad_sse4_asm.obj
- $(IntDir)vpx_dsp_x86_sad_sse4_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_sad_sse4_asm.obj
- $(IntDir)vpx_dsp_x86_sad_sse4_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_sad_sse4_asm.obj
- $(IntDir)vpx_dsp_x86_sad_sse4_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_sad_sse4_asm.obj
- $(IntDir)vpx_dsp_x86_sad_sse4_asm.obj
-
-
- $(IntDir)vpx_dsp_x86_sad4d_avx2.obj
- /arch:AVX
-
-
- $(IntDir)vpx_dsp_x86_sad_avx2.obj
- /arch:AVX
-
-
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_sad4d_sse2_asm.obj
- $(IntDir)vpx_dsp_x86_sad4d_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_sad4d_sse2_asm.obj
- $(IntDir)vpx_dsp_x86_sad4d_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_sad4d_sse2_asm.obj
- $(IntDir)vpx_dsp_x86_sad4d_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_sad4d_sse2_asm.obj
- $(IntDir)vpx_dsp_x86_sad4d_sse2_asm.obj
-
-
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_sad_sse2_asm.obj
- $(IntDir)vpx_dsp_x86_sad_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_sad_sse2_asm.obj
- $(IntDir)vpx_dsp_x86_sad_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_sad_sse2_asm.obj
- $(IntDir)vpx_dsp_x86_sad_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_sad_sse2_asm.obj
- $(IntDir)vpx_dsp_x86_sad_sse2_asm.obj
-
-
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_subtract_sse2_asm.obj
- $(IntDir)vpx_dsp_x86_subtract_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_subtract_sse2_asm.obj
- $(IntDir)vpx_dsp_x86_subtract_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_subtract_sse2_asm.obj
- $(IntDir)vpx_dsp_x86_subtract_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_subtract_sse2_asm.obj
- $(IntDir)vpx_dsp_x86_subtract_sse2_asm.obj
-
-
- $(IntDir)vpx_dsp_variance.obj
-
-
- $(IntDir)vpx_dsp_x86_variance_sse2.obj
-
-
- $(IntDir)vpx_dsp_x86_variance_avx2.obj
- /arch:AVX
-
-
- $(IntDir)vpx_dsp_x86_variance_impl_avx2.obj
- /arch:AVX
-
-
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_ssim_opt_x86_64_asm.obj
- $(IntDir)vpx_dsp_x86_ssim_opt_x86_64_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_ssim_opt_x86_64_asm.obj
- $(IntDir)vpx_dsp_x86_ssim_opt_x86_64_asm.obj
-
-
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_subpel_variance_sse2_asm.obj
- $(IntDir)vpx_dsp_x86_subpel_variance_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_subpel_variance_sse2_asm.obj
- $(IntDir)vpx_dsp_x86_subpel_variance_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_subpel_variance_sse2_asm.obj
- $(IntDir)vpx_dsp_x86_subpel_variance_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_subpel_variance_sse2_asm.obj
- $(IntDir)vpx_dsp_x86_subpel_variance_sse2_asm.obj
-
-
- $(IntDir)vpx_dsp_vpx_dsp_rtcd.obj
-
-
- $(IntDir)vpx_util_vpx_thread.obj
-
-
- $(IntDir)vp8_common_alloccommon.obj
-
-
- $(IntDir)vp8_common_blockd.obj
-
-
- $(IntDir)vp8_common_copy_c.obj
-
-
- $(IntDir)vp8_common_dequantize.obj
-
-
- $(IntDir)vp8_common_entropy.obj
-
-
- $(IntDir)vp8_common_entropymode.obj
-
-
- $(IntDir)vp8_common_entropymv.obj
-
-
- $(IntDir)vp8_common_extend.obj
-
-
- $(IntDir)vp8_common_filter.obj
-
-
- $(IntDir)vp8_common_findnearmv.obj
-
-
- $(IntDir)vp8_common_generic_systemdependent.obj
-
-
- $(IntDir)vp8_common_idct_blk.obj
-
-
- $(IntDir)vp8_common_idctllm.obj
-
-
- $(IntDir)vp8_common_rtcd.obj
-
-
- $(IntDir)vp8_common_vp8_loopfilter.obj
-
-
- $(IntDir)vp8_common_loopfilter_filters.obj
-
-
- $(IntDir)vp8_common_mbpitch.obj
-
-
- $(IntDir)vp8_common_modecont.obj
-
-
- $(IntDir)vp8_common_quant_common.obj
-
-
- $(IntDir)vp8_common_reconinter.obj
-
-
- $(IntDir)vp8_common_reconintra.obj
-
-
- $(IntDir)vp8_common_reconintra4x4.obj
-
-
- $(IntDir)vp8_common_setupintrarecon.obj
-
-
- $(IntDir)vp8_common_swapyv12buffer.obj
-
-
- $(IntDir)vp8_common_treecoder.obj
-
-
- $(IntDir)vp8_common_x86_filter_x86.obj
-
-
- $(IntDir)vp8_common_x86_vp8_asm_stubs.obj
-
-
- $(IntDir)vp8_common_x86_loopfilter_x86.obj
-
-
- $(IntDir)vp8_common_mfqe.obj
-
-
- $(IntDir)vp8_common_postproc.obj
-
-
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_dequantize_mmx_asm.obj
- $(IntDir)vp8_common_x86_dequantize_mmx_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_dequantize_mmx_asm.obj
- $(IntDir)vp8_common_x86_dequantize_mmx_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_dequantize_mmx_asm.obj
- $(IntDir)vp8_common_x86_dequantize_mmx_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_dequantize_mmx_asm.obj
- $(IntDir)vp8_common_x86_dequantize_mmx_asm.obj
-
-
- $(IntDir)vp8_common_x86_idct_blk_mmx.obj
-
-
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_idctllm_mmx_asm.obj
- $(IntDir)vp8_common_x86_idctllm_mmx_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_idctllm_mmx_asm.obj
- $(IntDir)vp8_common_x86_idctllm_mmx_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_idctllm_mmx_asm.obj
- $(IntDir)vp8_common_x86_idctllm_mmx_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_idctllm_mmx_asm.obj
- $(IntDir)vp8_common_x86_idctllm_mmx_asm.obj
-
-
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_iwalsh_mmx_asm.obj
- $(IntDir)vp8_common_x86_iwalsh_mmx_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_iwalsh_mmx_asm.obj
- $(IntDir)vp8_common_x86_iwalsh_mmx_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_iwalsh_mmx_asm.obj
- $(IntDir)vp8_common_x86_iwalsh_mmx_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_iwalsh_mmx_asm.obj
- $(IntDir)vp8_common_x86_iwalsh_mmx_asm.obj
-
-
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_vp8_loopfilter_mmx_asm.obj
- $(IntDir)vp8_common_x86_vp8_loopfilter_mmx_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_vp8_loopfilter_mmx_asm.obj
- $(IntDir)vp8_common_x86_vp8_loopfilter_mmx_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_vp8_loopfilter_mmx_asm.obj
- $(IntDir)vp8_common_x86_vp8_loopfilter_mmx_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_vp8_loopfilter_mmx_asm.obj
- $(IntDir)vp8_common_x86_vp8_loopfilter_mmx_asm.obj
-
-
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_recon_mmx_asm.obj
- $(IntDir)vp8_common_x86_recon_mmx_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_recon_mmx_asm.obj
- $(IntDir)vp8_common_x86_recon_mmx_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_recon_mmx_asm.obj
- $(IntDir)vp8_common_x86_recon_mmx_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_recon_mmx_asm.obj
- $(IntDir)vp8_common_x86_recon_mmx_asm.obj
-
-
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_subpixel_mmx_asm.obj
- $(IntDir)vp8_common_x86_subpixel_mmx_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_subpixel_mmx_asm.obj
- $(IntDir)vp8_common_x86_subpixel_mmx_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_subpixel_mmx_asm.obj
- $(IntDir)vp8_common_x86_subpixel_mmx_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_subpixel_mmx_asm.obj
- $(IntDir)vp8_common_x86_subpixel_mmx_asm.obj
-
-
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_copy_sse2_asm.obj
- $(IntDir)vp8_common_x86_copy_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_copy_sse2_asm.obj
- $(IntDir)vp8_common_x86_copy_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_copy_sse2_asm.obj
- $(IntDir)vp8_common_x86_copy_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_copy_sse2_asm.obj
- $(IntDir)vp8_common_x86_copy_sse2_asm.obj
-
-
- $(IntDir)vp8_common_x86_idct_blk_sse2.obj
-
-
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_idctllm_sse2_asm.obj
- $(IntDir)vp8_common_x86_idctllm_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_idctllm_sse2_asm.obj
- $(IntDir)vp8_common_x86_idctllm_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_idctllm_sse2_asm.obj
- $(IntDir)vp8_common_x86_idctllm_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_idctllm_sse2_asm.obj
- $(IntDir)vp8_common_x86_idctllm_sse2_asm.obj
-
-
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_recon_sse2_asm.obj
- $(IntDir)vp8_common_x86_recon_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_recon_sse2_asm.obj
- $(IntDir)vp8_common_x86_recon_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_recon_sse2_asm.obj
- $(IntDir)vp8_common_x86_recon_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_recon_sse2_asm.obj
- $(IntDir)vp8_common_x86_recon_sse2_asm.obj
-
-
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_subpixel_sse2_asm.obj
- $(IntDir)vp8_common_x86_subpixel_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_subpixel_sse2_asm.obj
- $(IntDir)vp8_common_x86_subpixel_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_subpixel_sse2_asm.obj
- $(IntDir)vp8_common_x86_subpixel_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_subpixel_sse2_asm.obj
- $(IntDir)vp8_common_x86_subpixel_sse2_asm.obj
-
-
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_loopfilter_sse2_asm.obj
- $(IntDir)vp8_common_x86_loopfilter_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_loopfilter_sse2_asm.obj
- $(IntDir)vp8_common_x86_loopfilter_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_loopfilter_sse2_asm.obj
- $(IntDir)vp8_common_x86_loopfilter_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_loopfilter_sse2_asm.obj
- $(IntDir)vp8_common_x86_loopfilter_sse2_asm.obj
-
-
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_iwalsh_sse2_asm.obj
- $(IntDir)vp8_common_x86_iwalsh_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_iwalsh_sse2_asm.obj
- $(IntDir)vp8_common_x86_iwalsh_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_iwalsh_sse2_asm.obj
- $(IntDir)vp8_common_x86_iwalsh_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_iwalsh_sse2_asm.obj
- $(IntDir)vp8_common_x86_iwalsh_sse2_asm.obj
-
-
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_copy_sse3_asm.obj
- $(IntDir)vp8_common_x86_copy_sse3_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_copy_sse3_asm.obj
- $(IntDir)vp8_common_x86_copy_sse3_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_copy_sse3_asm.obj
- $(IntDir)vp8_common_x86_copy_sse3_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_copy_sse3_asm.obj
- $(IntDir)vp8_common_x86_copy_sse3_asm.obj
-
-
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_subpixel_ssse3_asm.obj
- $(IntDir)vp8_common_x86_subpixel_ssse3_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_subpixel_ssse3_asm.obj
- $(IntDir)vp8_common_x86_subpixel_ssse3_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_subpixel_ssse3_asm.obj
- $(IntDir)vp8_common_x86_subpixel_ssse3_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_subpixel_ssse3_asm.obj
- $(IntDir)vp8_common_x86_subpixel_ssse3_asm.obj
-
-
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_mfqe_sse2_asm.obj
- $(IntDir)vp8_common_x86_mfqe_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_mfqe_sse2_asm.obj
- $(IntDir)vp8_common_x86_mfqe_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_mfqe_sse2_asm.obj
- $(IntDir)vp8_common_x86_mfqe_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_mfqe_sse2_asm.obj
- $(IntDir)vp8_common_x86_mfqe_sse2_asm.obj
-
-
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_loopfilter_block_sse2_x86_64_asm.obj
- $(IntDir)vp8_common_x86_loopfilter_block_sse2_x86_64_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_loopfilter_block_sse2_x86_64_asm.obj
- $(IntDir)vp8_common_x86_loopfilter_block_sse2_x86_64_asm.obj
-
-
- $(IntDir)vp8_vp8_cx_iface.obj
-
-
- $(IntDir)vp8_encoder_bitstream.obj
-
-
- $(IntDir)vp8_encoder_boolhuff.obj
-
-
- $(IntDir)vp8_encoder_dct.obj
-
-
- $(IntDir)vp8_encoder_encodeframe.obj
-
-
- $(IntDir)vp8_encoder_encodeintra.obj
-
-
- $(IntDir)vp8_encoder_encodemb.obj
-
-
- $(IntDir)vp8_encoder_encodemv.obj
-
-
- $(IntDir)vp8_encoder_ethreading.obj
-
-
- $(IntDir)vp8_encoder_firstpass.obj
-
-
- $(IntDir)vp8_encoder_denoising.obj
-
-
- $(IntDir)vp8_encoder_lookahead.obj
-
-
- $(IntDir)vp8_encoder_mcomp.obj
-
-
- $(IntDir)vp8_encoder_modecosts.obj
-
-
- $(IntDir)vp8_encoder_onyx_if.obj
-
-
- $(IntDir)vp8_encoder_pickinter.obj
-
-
- $(IntDir)vp8_encoder_picklpf.obj
-
-
- $(IntDir)vp8_encoder_vp8_quantize.obj
-
-
- $(IntDir)vp8_encoder_ratectrl.obj
-
-
- $(IntDir)vp8_encoder_rdopt.obj
-
-
- $(IntDir)vp8_encoder_segmentation.obj
-
-
- $(IntDir)vp8_encoder_tokenize.obj
-
-
- $(IntDir)vp8_encoder_treewriter.obj
-
-
- $(IntDir)vp8_encoder_temporal_filter.obj
-
-
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_encoder_x86_dct_mmx_asm.obj
- $(IntDir)vp8_encoder_x86_dct_mmx_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_encoder_x86_dct_mmx_asm.obj
- $(IntDir)vp8_encoder_x86_dct_mmx_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_encoder_x86_dct_mmx_asm.obj
- $(IntDir)vp8_encoder_x86_dct_mmx_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_encoder_x86_dct_mmx_asm.obj
- $(IntDir)vp8_encoder_x86_dct_mmx_asm.obj
-
-
- $(IntDir)vp8_encoder_x86_vp8_enc_stubs_mmx.obj
-
-
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_encoder_x86_dct_sse2_asm.obj
- $(IntDir)vp8_encoder_x86_dct_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_encoder_x86_dct_sse2_asm.obj
- $(IntDir)vp8_encoder_x86_dct_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_encoder_x86_dct_sse2_asm.obj
- $(IntDir)vp8_encoder_x86_dct_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_encoder_x86_dct_sse2_asm.obj
- $(IntDir)vp8_encoder_x86_dct_sse2_asm.obj
-
-
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_encoder_x86_fwalsh_sse2_asm.obj
- $(IntDir)vp8_encoder_x86_fwalsh_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_encoder_x86_fwalsh_sse2_asm.obj
- $(IntDir)vp8_encoder_x86_fwalsh_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_encoder_x86_fwalsh_sse2_asm.obj
- $(IntDir)vp8_encoder_x86_fwalsh_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_encoder_x86_fwalsh_sse2_asm.obj
- $(IntDir)vp8_encoder_x86_fwalsh_sse2_asm.obj
-
-
- $(IntDir)vp8_encoder_x86_vp8_quantize_sse2.obj
-
-
- $(IntDir)vp8_encoder_x86_quantize_ssse3.obj
-
-
- $(IntDir)vp8_encoder_x86_quantize_sse4.obj
-
-
- $(IntDir)vp8_encoder_x86_denoising_sse2.obj
-
-
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_encoder_x86_temporal_filter_apply_sse2_asm.obj
- $(IntDir)vp8_encoder_x86_temporal_filter_apply_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_encoder_x86_temporal_filter_apply_sse2_asm.obj
- $(IntDir)vp8_encoder_x86_temporal_filter_apply_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_encoder_x86_temporal_filter_apply_sse2_asm.obj
- $(IntDir)vp8_encoder_x86_temporal_filter_apply_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_encoder_x86_temporal_filter_apply_sse2_asm.obj
- $(IntDir)vp8_encoder_x86_temporal_filter_apply_sse2_asm.obj
-
-
- $(IntDir)vp8_encoder_x86_vp8_enc_stubs_sse2.obj
-
-
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_encoder_x86_quantize_mmx_asm.obj
- $(IntDir)vp8_encoder_x86_quantize_mmx_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_encoder_x86_quantize_mmx_asm.obj
- $(IntDir)vp8_encoder_x86_quantize_mmx_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_encoder_x86_quantize_mmx_asm.obj
- $(IntDir)vp8_encoder_x86_quantize_mmx_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_encoder_x86_quantize_mmx_asm.obj
- $(IntDir)vp8_encoder_x86_quantize_mmx_asm.obj
-
-
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_encoder_x86_encodeopt_asm.obj
- $(IntDir)vp8_encoder_x86_encodeopt_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_encoder_x86_encodeopt_asm.obj
- $(IntDir)vp8_encoder_x86_encodeopt_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_encoder_x86_encodeopt_asm.obj
- $(IntDir)vp8_encoder_x86_encodeopt_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_encoder_x86_encodeopt_asm.obj
- $(IntDir)vp8_encoder_x86_encodeopt_asm.obj
-
-
- $(IntDir)vp8_vp8_dx_iface.obj
-
-
- $(IntDir)vp8_decoder_dboolhuff.obj
-
-
- $(IntDir)vp8_decoder_decodemv.obj
-
-
- $(IntDir)vp8_decoder_decodeframe.obj
-
-
- $(IntDir)vp8_decoder_detokenize.obj
-
-
- $(IntDir)vp8_decoder_onyxd_if.obj
-
-
- $(IntDir)vp8_decoder_threading.obj
-
-
- $(IntDir)vp9_common_vp9_alloccommon.obj
-
-
- $(IntDir)vp9_common_vp9_blockd.obj
-
-
- $(IntDir)vp9_common_vp9_entropy.obj
-
-
- $(IntDir)vp9_common_vp9_entropymode.obj
-
-
- $(IntDir)vp9_common_vp9_entropymv.obj
-
-
- $(IntDir)vp9_common_vp9_frame_buffers.obj
-
-
- $(IntDir)vp9_common_vp9_idct.obj
-
-
- $(IntDir)vp9_common_vp9_filter.obj
-
-
- $(IntDir)vp9_common_vp9_pred_common.obj
-
-
- $(IntDir)vp9_common_vp9_rtcd.obj
-
-
- $(IntDir)vp9_common_vp9_scale.obj
-
-
- $(IntDir)vp9_common_vp9_seg_common.obj
-
-
- $(IntDir)vp9_common_vp9_tile_common.obj
-
-
- $(IntDir)vp9_common_vp9_loopfilter.obj
-
-
- $(IntDir)vp9_common_vp9_thread_common.obj
-
-
- $(IntDir)vp9_common_vp9_mvref_common.obj
-
-
- $(IntDir)vp9_common_vp9_quant_common.obj
-
-
- $(IntDir)vp9_common_vp9_reconinter.obj
-
-
- $(IntDir)vp9_common_vp9_reconintra.obj
-
-
- $(IntDir)vp9_common_vp9_common_data.obj
-
-
- $(IntDir)vp9_common_vp9_scan.obj
-
-
- $(IntDir)vp9_common_x86_vp9_idct_intrin_sse2.obj
-
-
- $(IntDir)vp9_vp9_cx_iface.obj
-
-
- $(IntDir)vp9_encoder_vp9_bitstream.obj
-
-
- $(IntDir)vp9_encoder_vp9_context_tree.obj
-
-
- $(IntDir)vp9_encoder_vp9_cost.obj
-
-
- $(IntDir)vp9_encoder_vp9_dct.obj
-
-
- $(IntDir)vp9_encoder_vp9_encodeframe.obj
-
-
- $(IntDir)vp9_encoder_vp9_encodemb.obj
-
-
- $(IntDir)vp9_encoder_vp9_encodemv.obj
-
-
- $(IntDir)vp9_encoder_vp9_ethread.obj
-
-
- $(IntDir)vp9_encoder_vp9_extend.obj
-
-
- $(IntDir)vp9_encoder_vp9_firstpass.obj
-
-
- $(IntDir)vp9_encoder_vp9_lookahead.obj
-
-
- $(IntDir)vp9_encoder_vp9_mcomp.obj
-
-
- $(IntDir)vp9_encoder_vp9_encoder.obj
-
-
- $(IntDir)vp9_encoder_vp9_picklpf.obj
-
-
- $(IntDir)vp9_encoder_vp9_quantize.obj
-
-
- $(IntDir)vp9_encoder_vp9_ratectrl.obj
-
-
- $(IntDir)vp9_encoder_vp9_rd.obj
-
-
- $(IntDir)vp9_encoder_vp9_rdopt.obj
-
-
- $(IntDir)vp9_encoder_vp9_pickmode.obj
-
-
- $(IntDir)vp9_encoder_vp9_segmentation.obj
-
-
- $(IntDir)vp9_encoder_vp9_speed_features.obj
-
-
- $(IntDir)vp9_encoder_vp9_subexp.obj
-
-
- $(IntDir)vp9_encoder_vp9_svc_layercontext.obj
-
-
- $(IntDir)vp9_encoder_vp9_resize.obj
-
-
- $(IntDir)vp9_encoder_vp9_tokenize.obj
-
-
- $(IntDir)vp9_encoder_vp9_treewriter.obj
-
-
- $(IntDir)vp9_encoder_vp9_aq_variance.obj
-
-
- $(IntDir)vp9_encoder_vp9_aq_360.obj
-
-
- $(IntDir)vp9_encoder_vp9_aq_cyclicrefresh.obj
-
-
- $(IntDir)vp9_encoder_vp9_aq_complexity.obj
-
-
- $(IntDir)vp9_encoder_vp9_alt_ref_aq.obj
-
-
- $(IntDir)vp9_encoder_vp9_skin_detection.obj
-
-
- $(IntDir)vp9_encoder_vp9_noise_estimate.obj
-
-
- $(IntDir)vp9_encoder_vp9_temporal_filter.obj
-
-
- $(IntDir)vp9_encoder_vp9_mbgraph.obj
-
-
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp9_encoder_x86_vp9_temporal_filter_apply_sse2_asm.obj
- $(IntDir)vp9_encoder_x86_vp9_temporal_filter_apply_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp9_encoder_x86_vp9_temporal_filter_apply_sse2_asm.obj
- $(IntDir)vp9_encoder_x86_vp9_temporal_filter_apply_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp9_encoder_x86_vp9_temporal_filter_apply_sse2_asm.obj
- $(IntDir)vp9_encoder_x86_vp9_temporal_filter_apply_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp9_encoder_x86_vp9_temporal_filter_apply_sse2_asm.obj
- $(IntDir)vp9_encoder_x86_vp9_temporal_filter_apply_sse2_asm.obj
-
-
- $(IntDir)vp9_encoder_x86_vp9_quantize_sse2.obj
-
-
- $(IntDir)vp9_encoder_x86_vp9_diamond_search_sad_avx.obj
- /arch:AVX
-
-
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp9_encoder_x86_vp9_dct_sse2_asm.obj
- $(IntDir)vp9_encoder_x86_vp9_dct_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp9_encoder_x86_vp9_dct_sse2_asm.obj
- $(IntDir)vp9_encoder_x86_vp9_dct_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp9_encoder_x86_vp9_dct_sse2_asm.obj
- $(IntDir)vp9_encoder_x86_vp9_dct_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp9_encoder_x86_vp9_dct_sse2_asm.obj
- $(IntDir)vp9_encoder_x86_vp9_dct_sse2_asm.obj
-
-
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp9_encoder_x86_vp9_error_sse2_asm.obj
- $(IntDir)vp9_encoder_x86_vp9_error_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp9_encoder_x86_vp9_error_sse2_asm.obj
- $(IntDir)vp9_encoder_x86_vp9_error_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp9_encoder_x86_vp9_error_sse2_asm.obj
- $(IntDir)vp9_encoder_x86_vp9_error_sse2_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp9_encoder_x86_vp9_error_sse2_asm.obj
- $(IntDir)vp9_encoder_x86_vp9_error_sse2_asm.obj
-
-
- Assembling %(Filename)%(Extension)
- yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp9_encoder_x86_vp9_quantize_ssse3_x86_64_asm.obj
- $(IntDir)vp9_encoder_x86_vp9_quantize_ssse3_x86_64_asm.obj
- Assembling %(Filename)%(Extension)
- yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp9_encoder_x86_vp9_quantize_ssse3_x86_64_asm.obj
- $(IntDir)vp9_encoder_x86_vp9_quantize_ssse3_x86_64_asm.obj
-
-
- $(IntDir)vp9_encoder_x86_vp9_dct_intrin_sse2.obj
-
-
- $(IntDir)vp9_encoder_x86_vp9_dct_ssse3.obj
-
-
- $(IntDir)vp9_encoder_x86_vp9_frame_scale_ssse3.obj
-
-
- $(IntDir)vp9_encoder_x86_vp9_error_intrin_avx2.obj
- /arch:AVX
-
-
- $(IntDir)vp9_vp9_dx_iface.obj
-
-
- $(IntDir)vp9_decoder_vp9_decodemv.obj
-
-
- $(IntDir)vp9_decoder_vp9_decodeframe.obj
-
-
- $(IntDir)vp9_decoder_vp9_detokenize.obj
-
-
- $(IntDir)vp9_decoder_vp9_dthread.obj
-
-
- $(IntDir)vp9_decoder_vp9_decoder.obj
-
-
- $(IntDir)vp9_decoder_vp9_dsubexp.obj
-
-
- $(IntDir)vpx_config.obj
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ libvpx
+ {DCE19DAF-69AC-46DB-B14A-39F0FAA5DB74}
+ libvpx
+ ManagedCProj
+
+
+
+
+ StaticLibrary
+ v141
+ Unicode
+ true
+
+
+ StaticLibrary
+ v141
+ Unicode
+
+
+ StaticLibrary
+ v141
+ Unicode
+ true
+
+
+ StaticLibrary
+ v141
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Disabled
+ ".";".\include_x86";"../../libvpx";%(AdditionalIncludeDirectories)
+ WIN32;_DEBUG;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;;%(PreprocessorDefinitions)
+ MultiThreadedDebug
+ Level3
+ false
+ NotUsing
+ false
+ true
+
+
+
+
+ Speed
+ MaxSpeed
+ ".";".\include_x86";"../../libvpx";%(AdditionalIncludeDirectories)
+ WIN32;NDEBUG;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;;%(PreprocessorDefinitions)
+ MultiThreaded
+ Level3
+ false
+ NotUsing
+ false
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+ Disabled
+ ".";".\include_x64";"..\..\libvpx";%(AdditionalIncludeDirectories)
+ WIN32;_DEBUG;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;;%(PreprocessorDefinitions)
+ MultiThreadedDebug
+ Level3
+ false
+ NotUsing
+ false
+ true
+
+
+
+
+ Speed
+ MaxSpeed
+ ".";".\include_x64";"..\..\libvpx";%(AdditionalIncludeDirectories)
+ WIN32;NDEBUG;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;;%(PreprocessorDefinitions)
+ MultiThreaded
+ Level3
+ false
+ NotUsing
+ false
+ true
+
+
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_ports_emms_asm.obj
+ $(IntDir)vpx_ports_emms_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_ports_emms_asm.obj
+ $(IntDir)vpx_ports_emms_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_ports_emms_asm.obj
+ $(IntDir)vpx_ports_emms_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_ports_emms_asm.obj
+ $(IntDir)vpx_ports_emms_asm.obj
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_intrapred_sse2_asm.obj
+ $(IntDir)vpx_dsp_x86_intrapred_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_intrapred_sse2_asm.obj
+ $(IntDir)vpx_dsp_x86_intrapred_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_intrapred_sse2_asm.obj
+ $(IntDir)vpx_dsp_x86_intrapred_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_intrapred_sse2_asm.obj
+ $(IntDir)vpx_dsp_x86_intrapred_sse2_asm.obj
+
+
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_intrapred_ssse3_asm.obj
+ $(IntDir)vpx_dsp_x86_intrapred_ssse3_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_intrapred_ssse3_asm.obj
+ $(IntDir)vpx_dsp_x86_intrapred_ssse3_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_intrapred_ssse3_asm.obj
+ $(IntDir)vpx_dsp_x86_intrapred_ssse3_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_intrapred_ssse3_asm.obj
+ $(IntDir)vpx_dsp_x86_intrapred_ssse3_asm.obj
+
+
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_vpx_subpixel_8t_ssse3_asm.obj
+ $(IntDir)vpx_dsp_x86_vpx_subpixel_8t_ssse3_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_vpx_subpixel_8t_ssse3_asm.obj
+ $(IntDir)vpx_dsp_x86_vpx_subpixel_8t_ssse3_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_vpx_subpixel_8t_ssse3_asm.obj
+ $(IntDir)vpx_dsp_x86_vpx_subpixel_8t_ssse3_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_vpx_subpixel_8t_ssse3_asm.obj
+ $(IntDir)vpx_dsp_x86_vpx_subpixel_8t_ssse3_asm.obj
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_add_noise_sse2_asm.obj
+ $(IntDir)vpx_dsp_x86_add_noise_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_add_noise_sse2_asm.obj
+ $(IntDir)vpx_dsp_x86_add_noise_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_add_noise_sse2_asm.obj
+ $(IntDir)vpx_dsp_x86_add_noise_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_add_noise_sse2_asm.obj
+ $(IntDir)vpx_dsp_x86_add_noise_sse2_asm.obj
+
+
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_deblock_sse2_asm.obj
+ $(IntDir)vpx_dsp_x86_deblock_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_deblock_sse2_asm.obj
+ $(IntDir)vpx_dsp_x86_deblock_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_deblock_sse2_asm.obj
+ $(IntDir)vpx_dsp_x86_deblock_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_deblock_sse2_asm.obj
+ $(IntDir)vpx_dsp_x86_deblock_sse2_asm.obj
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_vpx_subpixel_8t_sse2_asm.obj
+ $(IntDir)vpx_dsp_x86_vpx_subpixel_8t_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_vpx_subpixel_8t_sse2_asm.obj
+ $(IntDir)vpx_dsp_x86_vpx_subpixel_8t_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_vpx_subpixel_8t_sse2_asm.obj
+ $(IntDir)vpx_dsp_x86_vpx_subpixel_8t_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_vpx_subpixel_8t_sse2_asm.obj
+ $(IntDir)vpx_dsp_x86_vpx_subpixel_8t_sse2_asm.obj
+
+
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_vpx_subpixel_bilinear_sse2_asm.obj
+ $(IntDir)vpx_dsp_x86_vpx_subpixel_bilinear_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_vpx_subpixel_bilinear_sse2_asm.obj
+ $(IntDir)vpx_dsp_x86_vpx_subpixel_bilinear_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_vpx_subpixel_bilinear_sse2_asm.obj
+ $(IntDir)vpx_dsp_x86_vpx_subpixel_bilinear_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_vpx_subpixel_bilinear_sse2_asm.obj
+ $(IntDir)vpx_dsp_x86_vpx_subpixel_bilinear_sse2_asm.obj
+
+
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_vpx_subpixel_bilinear_ssse3_asm.obj
+ $(IntDir)vpx_dsp_x86_vpx_subpixel_bilinear_ssse3_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_vpx_subpixel_bilinear_ssse3_asm.obj
+ $(IntDir)vpx_dsp_x86_vpx_subpixel_bilinear_ssse3_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_vpx_subpixel_bilinear_ssse3_asm.obj
+ $(IntDir)vpx_dsp_x86_vpx_subpixel_bilinear_ssse3_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_vpx_subpixel_bilinear_ssse3_asm.obj
+ $(IntDir)vpx_dsp_x86_vpx_subpixel_bilinear_ssse3_asm.obj
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+ /arch:AVX
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_vpx_convolve_copy_sse2_asm.obj
+ $(IntDir)vpx_dsp_x86_vpx_convolve_copy_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_vpx_convolve_copy_sse2_asm.obj
+ $(IntDir)vpx_dsp_x86_vpx_convolve_copy_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_vpx_convolve_copy_sse2_asm.obj
+ $(IntDir)vpx_dsp_x86_vpx_convolve_copy_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_vpx_convolve_copy_sse2_asm.obj
+ $(IntDir)vpx_dsp_x86_vpx_convolve_copy_sse2_asm.obj
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+ /arch:AVX
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_fwd_txfm_ssse3_x86_64_asm.obj
+ $(IntDir)vpx_dsp_x86_fwd_txfm_ssse3_x86_64_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_fwd_txfm_ssse3_x86_64_asm.obj
+ $(IntDir)vpx_dsp_x86_fwd_txfm_ssse3_x86_64_asm.obj
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+ /arch:AVX
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_inv_wht_sse2_asm.obj
+ $(IntDir)vpx_dsp_x86_inv_wht_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_inv_wht_sse2_asm.obj
+ $(IntDir)vpx_dsp_x86_inv_wht_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_inv_wht_sse2_asm.obj
+ $(IntDir)vpx_dsp_x86_inv_wht_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_inv_wht_sse2_asm.obj
+ $(IntDir)vpx_dsp_x86_inv_wht_sse2_asm.obj
+
+
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_inv_txfm_ssse3_x86_64_asm.obj
+ $(IntDir)vpx_dsp_x86_inv_txfm_ssse3_x86_64_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_inv_txfm_ssse3_x86_64_asm.obj
+ $(IntDir)vpx_dsp_x86_inv_txfm_ssse3_x86_64_asm.obj
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_quantize_ssse3_x86_64_asm.obj
+ $(IntDir)vpx_dsp_x86_quantize_ssse3_x86_64_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_quantize_ssse3_x86_64_asm.obj
+ $(IntDir)vpx_dsp_x86_quantize_ssse3_x86_64_asm.obj
+
+
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_quantize_avx_x86_64_asm.obj
+ $(IntDir)vpx_dsp_x86_quantize_avx_x86_64_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_quantize_avx_x86_64_asm.obj
+ $(IntDir)vpx_dsp_x86_quantize_avx_x86_64_asm.obj
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_avg_ssse3_x86_64_asm.obj
+ $(IntDir)vpx_dsp_x86_avg_ssse3_x86_64_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_avg_ssse3_x86_64_asm.obj
+ $(IntDir)vpx_dsp_x86_avg_ssse3_x86_64_asm.obj
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_sad_sse3_asm.obj
+ $(IntDir)vpx_dsp_x86_sad_sse3_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_sad_sse3_asm.obj
+ $(IntDir)vpx_dsp_x86_sad_sse3_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_sad_sse3_asm.obj
+ $(IntDir)vpx_dsp_x86_sad_sse3_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_sad_sse3_asm.obj
+ $(IntDir)vpx_dsp_x86_sad_sse3_asm.obj
+
+
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_sad_ssse3_asm.obj
+ $(IntDir)vpx_dsp_x86_sad_ssse3_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_sad_ssse3_asm.obj
+ $(IntDir)vpx_dsp_x86_sad_ssse3_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_sad_ssse3_asm.obj
+ $(IntDir)vpx_dsp_x86_sad_ssse3_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_sad_ssse3_asm.obj
+ $(IntDir)vpx_dsp_x86_sad_ssse3_asm.obj
+
+
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_sad_sse4_asm.obj
+ $(IntDir)vpx_dsp_x86_sad_sse4_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_sad_sse4_asm.obj
+ $(IntDir)vpx_dsp_x86_sad_sse4_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_sad_sse4_asm.obj
+ $(IntDir)vpx_dsp_x86_sad_sse4_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_sad_sse4_asm.obj
+ $(IntDir)vpx_dsp_x86_sad_sse4_asm.obj
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+ /arch:AVX
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+ /arch:AVX
+
+
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_sad4d_sse2_asm.obj
+ $(IntDir)vpx_dsp_x86_sad4d_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_sad4d_sse2_asm.obj
+ $(IntDir)vpx_dsp_x86_sad4d_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_sad4d_sse2_asm.obj
+ $(IntDir)vpx_dsp_x86_sad4d_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_sad4d_sse2_asm.obj
+ $(IntDir)vpx_dsp_x86_sad4d_sse2_asm.obj
+
+
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_sad_sse2_asm.obj
+ $(IntDir)vpx_dsp_x86_sad_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_sad_sse2_asm.obj
+ $(IntDir)vpx_dsp_x86_sad_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_sad_sse2_asm.obj
+ $(IntDir)vpx_dsp_x86_sad_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_sad_sse2_asm.obj
+ $(IntDir)vpx_dsp_x86_sad_sse2_asm.obj
+
+
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_subtract_sse2_asm.obj
+ $(IntDir)vpx_dsp_x86_subtract_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_subtract_sse2_asm.obj
+ $(IntDir)vpx_dsp_x86_subtract_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_subtract_sse2_asm.obj
+ $(IntDir)vpx_dsp_x86_subtract_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_subtract_sse2_asm.obj
+ $(IntDir)vpx_dsp_x86_subtract_sse2_asm.obj
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+ /arch:AVX
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+ /arch:AVX
+
+
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_ssim_opt_x86_64_asm.obj
+ $(IntDir)vpx_dsp_x86_ssim_opt_x86_64_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_ssim_opt_x86_64_asm.obj
+ $(IntDir)vpx_dsp_x86_ssim_opt_x86_64_asm.obj
+
+
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_subpel_variance_sse2_asm.obj
+ $(IntDir)vpx_dsp_x86_subpel_variance_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_subpel_variance_sse2_asm.obj
+ $(IntDir)vpx_dsp_x86_subpel_variance_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_subpel_variance_sse2_asm.obj
+ $(IntDir)vpx_dsp_x86_subpel_variance_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vpx_dsp_x86_subpel_variance_sse2_asm.obj
+ $(IntDir)vpx_dsp_x86_subpel_variance_sse2_asm.obj
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_dequantize_mmx_asm.obj
+ $(IntDir)vp8_common_x86_dequantize_mmx_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_dequantize_mmx_asm.obj
+ $(IntDir)vp8_common_x86_dequantize_mmx_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_dequantize_mmx_asm.obj
+ $(IntDir)vp8_common_x86_dequantize_mmx_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_dequantize_mmx_asm.obj
+ $(IntDir)vp8_common_x86_dequantize_mmx_asm.obj
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_idctllm_mmx_asm.obj
+ $(IntDir)vp8_common_x86_idctllm_mmx_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_idctllm_mmx_asm.obj
+ $(IntDir)vp8_common_x86_idctllm_mmx_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_idctllm_mmx_asm.obj
+ $(IntDir)vp8_common_x86_idctllm_mmx_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_idctllm_mmx_asm.obj
+ $(IntDir)vp8_common_x86_idctllm_mmx_asm.obj
+
+
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_iwalsh_mmx_asm.obj
+ $(IntDir)vp8_common_x86_iwalsh_mmx_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_iwalsh_mmx_asm.obj
+ $(IntDir)vp8_common_x86_iwalsh_mmx_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_iwalsh_mmx_asm.obj
+ $(IntDir)vp8_common_x86_iwalsh_mmx_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_iwalsh_mmx_asm.obj
+ $(IntDir)vp8_common_x86_iwalsh_mmx_asm.obj
+
+
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_vp8_loopfilter_mmx_asm.obj
+ $(IntDir)vp8_common_x86_vp8_loopfilter_mmx_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_vp8_loopfilter_mmx_asm.obj
+ $(IntDir)vp8_common_x86_vp8_loopfilter_mmx_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_vp8_loopfilter_mmx_asm.obj
+ $(IntDir)vp8_common_x86_vp8_loopfilter_mmx_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_vp8_loopfilter_mmx_asm.obj
+ $(IntDir)vp8_common_x86_vp8_loopfilter_mmx_asm.obj
+
+
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_recon_mmx_asm.obj
+ $(IntDir)vp8_common_x86_recon_mmx_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_recon_mmx_asm.obj
+ $(IntDir)vp8_common_x86_recon_mmx_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_recon_mmx_asm.obj
+ $(IntDir)vp8_common_x86_recon_mmx_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_recon_mmx_asm.obj
+ $(IntDir)vp8_common_x86_recon_mmx_asm.obj
+
+
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_subpixel_mmx_asm.obj
+ $(IntDir)vp8_common_x86_subpixel_mmx_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_subpixel_mmx_asm.obj
+ $(IntDir)vp8_common_x86_subpixel_mmx_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_subpixel_mmx_asm.obj
+ $(IntDir)vp8_common_x86_subpixel_mmx_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_subpixel_mmx_asm.obj
+ $(IntDir)vp8_common_x86_subpixel_mmx_asm.obj
+
+
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_copy_sse2_asm.obj
+ $(IntDir)vp8_common_x86_copy_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_copy_sse2_asm.obj
+ $(IntDir)vp8_common_x86_copy_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_copy_sse2_asm.obj
+ $(IntDir)vp8_common_x86_copy_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_copy_sse2_asm.obj
+ $(IntDir)vp8_common_x86_copy_sse2_asm.obj
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_idctllm_sse2_asm.obj
+ $(IntDir)vp8_common_x86_idctllm_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_idctllm_sse2_asm.obj
+ $(IntDir)vp8_common_x86_idctllm_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_idctllm_sse2_asm.obj
+ $(IntDir)vp8_common_x86_idctllm_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_idctllm_sse2_asm.obj
+ $(IntDir)vp8_common_x86_idctllm_sse2_asm.obj
+
+
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_recon_sse2_asm.obj
+ $(IntDir)vp8_common_x86_recon_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_recon_sse2_asm.obj
+ $(IntDir)vp8_common_x86_recon_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_recon_sse2_asm.obj
+ $(IntDir)vp8_common_x86_recon_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_recon_sse2_asm.obj
+ $(IntDir)vp8_common_x86_recon_sse2_asm.obj
+
+
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_subpixel_sse2_asm.obj
+ $(IntDir)vp8_common_x86_subpixel_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_subpixel_sse2_asm.obj
+ $(IntDir)vp8_common_x86_subpixel_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_subpixel_sse2_asm.obj
+ $(IntDir)vp8_common_x86_subpixel_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_subpixel_sse2_asm.obj
+ $(IntDir)vp8_common_x86_subpixel_sse2_asm.obj
+
+
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_loopfilter_sse2_asm.obj
+ $(IntDir)vp8_common_x86_loopfilter_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_loopfilter_sse2_asm.obj
+ $(IntDir)vp8_common_x86_loopfilter_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_loopfilter_sse2_asm.obj
+ $(IntDir)vp8_common_x86_loopfilter_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_loopfilter_sse2_asm.obj
+ $(IntDir)vp8_common_x86_loopfilter_sse2_asm.obj
+
+
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_iwalsh_sse2_asm.obj
+ $(IntDir)vp8_common_x86_iwalsh_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_iwalsh_sse2_asm.obj
+ $(IntDir)vp8_common_x86_iwalsh_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_iwalsh_sse2_asm.obj
+ $(IntDir)vp8_common_x86_iwalsh_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_iwalsh_sse2_asm.obj
+ $(IntDir)vp8_common_x86_iwalsh_sse2_asm.obj
+
+
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_copy_sse3_asm.obj
+ $(IntDir)vp8_common_x86_copy_sse3_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_copy_sse3_asm.obj
+ $(IntDir)vp8_common_x86_copy_sse3_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_copy_sse3_asm.obj
+ $(IntDir)vp8_common_x86_copy_sse3_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_copy_sse3_asm.obj
+ $(IntDir)vp8_common_x86_copy_sse3_asm.obj
+
+
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_subpixel_ssse3_asm.obj
+ $(IntDir)vp8_common_x86_subpixel_ssse3_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_subpixel_ssse3_asm.obj
+ $(IntDir)vp8_common_x86_subpixel_ssse3_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_subpixel_ssse3_asm.obj
+ $(IntDir)vp8_common_x86_subpixel_ssse3_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_subpixel_ssse3_asm.obj
+ $(IntDir)vp8_common_x86_subpixel_ssse3_asm.obj
+
+
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_mfqe_sse2_asm.obj
+ $(IntDir)vp8_common_x86_mfqe_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_mfqe_sse2_asm.obj
+ $(IntDir)vp8_common_x86_mfqe_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_mfqe_sse2_asm.obj
+ $(IntDir)vp8_common_x86_mfqe_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_mfqe_sse2_asm.obj
+ $(IntDir)vp8_common_x86_mfqe_sse2_asm.obj
+
+
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_loopfilter_block_sse2_x86_64_asm.obj
+ $(IntDir)vp8_common_x86_loopfilter_block_sse2_x86_64_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_common_x86_loopfilter_block_sse2_x86_64_asm.obj
+ $(IntDir)vp8_common_x86_loopfilter_block_sse2_x86_64_asm.obj
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_encoder_x86_dct_mmx_asm.obj
+ $(IntDir)vp8_encoder_x86_dct_mmx_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_encoder_x86_dct_mmx_asm.obj
+ $(IntDir)vp8_encoder_x86_dct_mmx_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_encoder_x86_dct_mmx_asm.obj
+ $(IntDir)vp8_encoder_x86_dct_mmx_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_encoder_x86_dct_mmx_asm.obj
+ $(IntDir)vp8_encoder_x86_dct_mmx_asm.obj
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_encoder_x86_dct_sse2_asm.obj
+ $(IntDir)vp8_encoder_x86_dct_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_encoder_x86_dct_sse2_asm.obj
+ $(IntDir)vp8_encoder_x86_dct_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_encoder_x86_dct_sse2_asm.obj
+ $(IntDir)vp8_encoder_x86_dct_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_encoder_x86_dct_sse2_asm.obj
+ $(IntDir)vp8_encoder_x86_dct_sse2_asm.obj
+
+
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_encoder_x86_fwalsh_sse2_asm.obj
+ $(IntDir)vp8_encoder_x86_fwalsh_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_encoder_x86_fwalsh_sse2_asm.obj
+ $(IntDir)vp8_encoder_x86_fwalsh_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_encoder_x86_fwalsh_sse2_asm.obj
+ $(IntDir)vp8_encoder_x86_fwalsh_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_encoder_x86_fwalsh_sse2_asm.obj
+ $(IntDir)vp8_encoder_x86_fwalsh_sse2_asm.obj
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_encoder_x86_temporal_filter_apply_sse2_asm.obj
+ $(IntDir)vp8_encoder_x86_temporal_filter_apply_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_encoder_x86_temporal_filter_apply_sse2_asm.obj
+ $(IntDir)vp8_encoder_x86_temporal_filter_apply_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_encoder_x86_temporal_filter_apply_sse2_asm.obj
+ $(IntDir)vp8_encoder_x86_temporal_filter_apply_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_encoder_x86_temporal_filter_apply_sse2_asm.obj
+ $(IntDir)vp8_encoder_x86_temporal_filter_apply_sse2_asm.obj
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_encoder_x86_quantize_mmx_asm.obj
+ $(IntDir)vp8_encoder_x86_quantize_mmx_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_encoder_x86_quantize_mmx_asm.obj
+ $(IntDir)vp8_encoder_x86_quantize_mmx_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_encoder_x86_quantize_mmx_asm.obj
+ $(IntDir)vp8_encoder_x86_quantize_mmx_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_encoder_x86_quantize_mmx_asm.obj
+ $(IntDir)vp8_encoder_x86_quantize_mmx_asm.obj
+
+
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_encoder_x86_encodeopt_asm.obj
+ $(IntDir)vp8_encoder_x86_encodeopt_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp8_encoder_x86_encodeopt_asm.obj
+ $(IntDir)vp8_encoder_x86_encodeopt_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_encoder_x86_encodeopt_asm.obj
+ $(IntDir)vp8_encoder_x86_encodeopt_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp8_encoder_x86_encodeopt_asm.obj
+ $(IntDir)vp8_encoder_x86_encodeopt_asm.obj
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp9_encoder_x86_vp9_temporal_filter_apply_sse2_asm.obj
+ $(IntDir)vp9_encoder_x86_vp9_temporal_filter_apply_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp9_encoder_x86_vp9_temporal_filter_apply_sse2_asm.obj
+ $(IntDir)vp9_encoder_x86_vp9_temporal_filter_apply_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp9_encoder_x86_vp9_temporal_filter_apply_sse2_asm.obj
+ $(IntDir)vp9_encoder_x86_vp9_temporal_filter_apply_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp9_encoder_x86_vp9_temporal_filter_apply_sse2_asm.obj
+ $(IntDir)vp9_encoder_x86_vp9_temporal_filter_apply_sse2_asm.obj
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+ /arch:AVX
+
+
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp9_encoder_x86_vp9_dct_sse2_asm.obj
+ $(IntDir)vp9_encoder_x86_vp9_dct_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp9_encoder_x86_vp9_dct_sse2_asm.obj
+ $(IntDir)vp9_encoder_x86_vp9_dct_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp9_encoder_x86_vp9_dct_sse2_asm.obj
+ $(IntDir)vp9_encoder_x86_vp9_dct_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp9_encoder_x86_vp9_dct_sse2_asm.obj
+ $(IntDir)vp9_encoder_x86_vp9_dct_sse2_asm.obj
+
+
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp9_encoder_x86_vp9_error_sse2_asm.obj
+ $(IntDir)vp9_encoder_x86_vp9_error_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win32 -I".\include_x86" -I"..\..\libvpx" "%(FullPath)" -o $(IntDir)vp9_encoder_x86_vp9_error_sse2_asm.obj
+ $(IntDir)vp9_encoder_x86_vp9_error_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp9_encoder_x86_vp9_error_sse2_asm.obj
+ $(IntDir)vp9_encoder_x86_vp9_error_sse2_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp9_encoder_x86_vp9_error_sse2_asm.obj
+ $(IntDir)vp9_encoder_x86_vp9_error_sse2_asm.obj
+
+
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -g cv8 -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp9_encoder_x86_vp9_quantize_ssse3_x86_64_asm.obj
+ $(IntDir)vp9_encoder_x86_vp9_quantize_ssse3_x86_64_asm.obj
+ Assembling %(Filename)%(Extension)
+ yasm -Xvc -f win64 -I"./include_x64" -I"../../libvpx" "%(FullPath)" -o $(IntDir)vp9_encoder_x86_vp9_quantize_ssse3_x86_64_asm.obj
+ $(IntDir)vp9_encoder_x86_vp9_quantize_ssse3_x86_64_asm.obj
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+ /arch:AVX
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+ $(IntDir)$([System.String]::Copy(%(RelativeDir)).Replace('\','_'))\
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/scripts/ci/common.sh b/scripts/ci/common.sh
index 6158356a1c..cecb1289bc 100755
--- a/scripts/ci/common.sh
+++ b/scripts/ci/common.sh
@@ -123,11 +123,11 @@ set_fs_ver () {
rpm_version="$major.$minor.$micro"
fi
- sed -e "s|\(%define version \).*|\1$rpm_version|" \
+ sed -e "s|\(%define nonparsedversion \).*|\1$rpm_version|" \
freeswitch.spec > freeswitch.spec.$$
mv freeswitch.spec.$$ freeswitch.spec
- sed -e "s|\(%define version \).*|\1$rpm_version|" \
+ sed -e "s|\(%define nonparsedversion \).*|\1$rpm_version|" \
freeswitch-config-rayo.spec > freeswitch-config-rayo.spec.$$
mv freeswitch-config-rayo.spec.$$ freeswitch-config-rayo.spec
diff --git a/scripts/ci/mk-sounds-rpms.sh b/scripts/ci/mk-sounds-rpms.sh
index aca867076b..fda715d02a 100755
--- a/scripts/ci/mk-sounds-rpms.sh
+++ b/scripts/ci/mk-sounds-rpms.sh
@@ -1,7 +1,7 @@
#!/bin/sh
##### -*- mode:shell-script; indent-tabs-mode:nil; sh-basic-offset:2 -*-
-declare -a specfiles=('freeswitch-sounds-en-ca-june.spec' 'freeswitch-sounds-fr-ca-june.spec' 'freeswitch-sounds-ru-RU-elena.spec' 'freeswitch-sounds-en-us-callie.spec' 'freeswitch-sounds-sv-se-jakob.spec')
+declare -a specfiles=('freeswitch-sounds-en-ca-june.spec' 'freeswitch-sounds-en-us-allison.spec' 'freeswitch-sounds-fr-ca-june.spec' 'freeswitch-sounds-music.spec' 'freeswitch-sounds-pt-BR-karina.spec' 'freeswitch-sounds-ru-RU-elena.spec' 'freeswitch-sounds-en-us-callie.spec' 'freeswitch-sounds-sv-se-jakob.spec')
sdir="."
[ -n "${0%/*}" ] && sdir="${0%/*}"
@@ -15,17 +15,17 @@ basedir=$(pwd);
if [ ! -d "$basedir/../freeswitch-sounds" ]; then
cd $basedir/..
- git clone https://freeswitch.org/stash/scm/fs/freeswitch-sounds.git
+ git clone https://freeswitch.org/stash/scm/fs/freeswitch-sounds.git
else
cd $basedir/../freeswitch-sounds
git clean -fdx
- git pull
+ git pull
fi
for i in "${specfiles[@]}"
do
-cd $basedir/../freeswitch-sounds/sounds/trunk
+cd $basedir/../freeswitch-sounds/
./dist.pl `echo $i|sed -e 's/freeswitch-sounds-//g' -e 's/\.spec//g' -e 's/-/\//g'`
diff --git a/src/include/private/switch_core_pvt.h b/src/include/private/switch_core_pvt.h
index 1d61357644..8f8076a5bf 100644
--- a/src/include/private/switch_core_pvt.h
+++ b/src/include/private/switch_core_pvt.h
@@ -129,6 +129,7 @@ struct switch_core_session {
switch_audio_resampler_t *write_resampler;
switch_mutex_t *mutex;
+ switch_mutex_t *stack_count_mutex;
switch_mutex_t *resample_mutex;
switch_mutex_t *codec_read_mutex;
switch_mutex_t *codec_write_mutex;
diff --git a/src/include/switch_channel.h b/src/include/switch_channel.h
index 8e24893fdc..ec066852c6 100644
--- a/src/include/switch_channel.h
+++ b/src/include/switch_channel.h
@@ -270,6 +270,9 @@ SWITCH_DECLARE(char *) switch_channel_get_uuid(switch_channel_t *channel);
SWITCH_DECLARE(switch_status_t) switch_channel_set_profile_var(switch_channel_t *channel, const char *name, const char *val);
+SWITCH_DECLARE(switch_status_t) switch_channel_set_log_tag(switch_channel_t *channel, const char *tagname, const char *tagvalue);
+SWITCH_DECLARE(switch_status_t) switch_channel_get_log_tags(switch_channel_t *channel, switch_event_t **log_tags);
+
SWITCH_DECLARE(switch_status_t) switch_channel_set_variable_var_check(switch_channel_t *channel,
const char *varname, const char *value, switch_bool_t var_check);
SWITCH_DECLARE(switch_status_t) switch_channel_add_variable_var_check(switch_channel_t *channel,
diff --git a/src/include/switch_core.h b/src/include/switch_core.h
index 526fe26323..7631fc287f 100644
--- a/src/include/switch_core.h
+++ b/src/include/switch_core.h
@@ -2427,6 +2427,7 @@ SWITCH_DECLARE(const char *) switch_lookup_timezone(const char *tz_name);
SWITCH_DECLARE(switch_status_t) switch_strftime_tz(const char *tz, const char *format, char *date, size_t len, switch_time_t thetime);
SWITCH_DECLARE(switch_status_t) switch_time_exp_tz_name(const char *tz, switch_time_exp_t *tm, switch_time_t thetime);
SWITCH_DECLARE(void) switch_load_network_lists(switch_bool_t reload);
+SWITCH_DECLARE(switch_bool_t) switch_check_network_list_ip_port_token(const char *ip_str, int port, const char *list_name, const char **token);
SWITCH_DECLARE(switch_bool_t) switch_check_network_list_ip_token(const char *ip_str, const char *list_name, const char **token);
#define switch_check_network_list_ip(_ip_str, _list_name) switch_check_network_list_ip_token(_ip_str, _list_name, NULL)
SWITCH_DECLARE(void) switch_time_set_monotonic(switch_bool_t enable);
diff --git a/src/include/switch_core_media.h b/src/include/switch_core_media.h
index 1c73c2367a..ef9ddda964 100644
--- a/src/include/switch_core_media.h
+++ b/src/include/switch_core_media.h
@@ -270,6 +270,10 @@ SWITCH_DECLARE(switch_rtp_stats_t *) switch_core_media_get_stats(switch_core_ses
SWITCH_DECLARE(void) switch_core_media_set_sdp_codec_string(switch_core_session_t *session, const char *r_sdp, switch_sdp_type_t sdp_type);
+SWITCH_DECLARE(void) switch_core_media_merge_sdp_codec_string(switch_core_session_t *session, const char *r_sdp,
+ switch_sdp_type_t sdp_type, const char *codec_string);
+
+
SWITCH_DECLARE(void) switch_core_media_reset_autofix(switch_core_session_t *session, switch_media_type_t type);
SWITCH_DECLARE(void) switch_core_media_check_outgoing_proxy(switch_core_session_t *session, switch_core_session_t *o_session);
SWITCH_DECLARE(switch_status_t) switch_core_media_codec_chosen(switch_core_session_t *session, switch_media_type_t media);
@@ -381,7 +385,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_print(switch_core_session_t
SWITCH_DECLARE(switch_status_t) switch_core_session_printf(switch_core_session_t *session, const char *fmt, ...);
SWITCH_DECLARE(switch_msrp_session_t *) switch_core_media_get_msrp_session(switch_core_session_t *session);
-
+SWITCH_DECLARE(void) switch_core_media_set_smode(switch_core_session_t *session, switch_media_type_t type, switch_media_flow_t smode, switch_sdp_type_t sdp_type);
SWITCH_END_EXTERN_C
#endif
diff --git a/src/include/switch_event.h b/src/include/switch_event.h
index 2c6eb48388..50519b8f99 100644
--- a/src/include/switch_event.h
+++ b/src/include/switch_event.h
@@ -215,7 +215,7 @@ SWITCH_DECLARE(int) switch_event_add_array(switch_event_t *event, const char *va
\param event pointer to the pointer to event to destroy
*/
SWITCH_DECLARE(void) switch_event_destroy(switch_event_t **event);
-#define switch_event_safe_destroy(_event) if (_event) switch_event_destroy(_event)
+#define switch_event_safe_destroy(_event) if (_event) switch_event_destroy(&_event)
/*!
\brief Duplicate an event
diff --git a/src/include/switch_ivr.h b/src/include/switch_ivr.h
index 5a444d552b..69cb038caf 100644
--- a/src/include/switch_ivr.h
+++ b/src/include/switch_ivr.h
@@ -293,6 +293,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech_start_input_timers(swit
\return SWITCH_STATUS_SUCCESS if all is well
*/
SWITCH_DECLARE(switch_status_t) switch_ivr_record_session(switch_core_session_t *session, const char *file, uint32_t limit, switch_file_handle_t *fh);
+SWITCH_DECLARE(switch_status_t) switch_ivr_record_session_event(switch_core_session_t *session, const char *file, uint32_t limit, switch_file_handle_t *fh, switch_event_t *variables);
SWITCH_DECLARE(switch_status_t) switch_ivr_transfer_recordings(switch_core_session_t *orig_session, switch_core_session_t *new_session);
diff --git a/src/include/switch_loadable_module.h b/src/include/switch_loadable_module.h
index 9cc99ee0be..87295a641b 100644
--- a/src/include/switch_loadable_module.h
+++ b/src/include/switch_loadable_module.h
@@ -318,7 +318,7 @@ SWITCH_DECLARE(switch_status_t) switch_loadable_module_exists(const char *mod);
\param err pointer to error message
\return the status
*/
-SWITCH_DECLARE(switch_status_t) switch_loadable_module_unload_module(char *dir, char *fname, switch_bool_t force, const char **err);
+SWITCH_DECLARE(switch_status_t) switch_loadable_module_unload_module(const char *dir, const char *fname, switch_bool_t force, const char **err);
/* Prototypes of module interface functions */
@@ -328,7 +328,7 @@ SWITCH_DECLARE(switch_status_t) switch_loadable_module_unload_module(char *dir,
\param filename the path to the module's dll or so file
\return SWITCH_STATUS_SUCCESS on a successful load
*/
-SWITCH_MOD_DECLARE(switch_status_t) switch_module_load(switch_loadable_module_interface_t ** module_interface, char *filename);
+SWITCH_MOD_DECLARE(switch_status_t) switch_module_load(switch_loadable_module_interface_t ** module_interface, const char *filename);
SWITCH_MOD_DECLARE(switch_status_t) switch_module_runtime(void);
/*!
diff --git a/src/include/switch_log.h b/src/include/switch_log.h
index f0df9d8315..357f20f324 100644
--- a/src/include/switch_log.h
+++ b/src/include/switch_log.h
@@ -65,6 +65,7 @@ SWITCH_BEGIN_EXTERN_C
/* To maintain abi, only add new elements to the end of this struct and do not delete any elements */
switch_text_channel_t channel;
switch_log_level_t slevel;
+ switch_event_t *tags;
} switch_log_node_t;
typedef switch_status_t (*switch_log_function_t) (const switch_log_node_t *node, switch_log_level_t level);
diff --git a/src/include/switch_rtp.h b/src/include/switch_rtp.h
index 41e8637683..a16c5f6d5a 100644
--- a/src/include/switch_rtp.h
+++ b/src/include/switch_rtp.h
@@ -578,7 +578,7 @@ SWITCH_DECLARE(switch_rtp_stats_t *) switch_rtp_get_stats(switch_rtp_t *rtp_sess
SWITCH_DECLARE(switch_byte_t) switch_rtp_check_auto_adj(switch_rtp_t *rtp_session);
SWITCH_DECLARE(void) switch_rtp_set_interdigit_delay(switch_rtp_t *rtp_session, uint32_t delay);
-SWITCH_DECLARE(switch_status_t) switch_rtp_add_dtls(switch_rtp_t *rtp_session, dtls_fingerprint_t *local_fp, dtls_fingerprint_t *remote_fp, dtls_type_t type);
+SWITCH_DECLARE(switch_status_t) switch_rtp_add_dtls(switch_rtp_t *rtp_session, dtls_fingerprint_t *local_fp, dtls_fingerprint_t *remote_fp, dtls_type_t type, uint8_t want_DTLSv1_2);
SWITCH_DECLARE(switch_status_t) switch_rtp_del_dtls(switch_rtp_t *rtp_session, dtls_type_t type);
SWITCH_DECLARE(dtls_state_t) switch_rtp_dtls_state(switch_rtp_t *rtp_session, dtls_type_t type);
diff --git a/src/include/switch_ssl.h b/src/include/switch_ssl.h
index 3f4d6d696e..f31888b57b 100644
--- a/src/include/switch_ssl.h
+++ b/src/include/switch_ssl.h
@@ -38,6 +38,7 @@
#endif
#include
#include
+#include
#include
#include
#ifndef OPENSSL_NO_ENGINE
diff --git a/src/include/switch_types.h b/src/include/switch_types.h
index 926c8a6bea..53c25c395c 100644
--- a/src/include/switch_types.h
+++ b/src/include/switch_types.h
@@ -377,7 +377,9 @@ typedef enum {
SCF_DEBUG_SQL = (1 << 21),
SCF_API_EXPANSION = (1 << 22),
SCF_SESSION_THREAD_POOL = (1 << 23),
- SCF_DIALPLAN_TIMESTAMPS = (1 << 24)
+ SCF_DIALPLAN_TIMESTAMPS = (1 << 24),
+ SCF_CPF_SOFT_PREFIX = (1 << 25),
+ SCF_CPF_SOFT_LOOKUP = (1 << 26)
} switch_core_flag_enum_t;
typedef uint32_t switch_core_flag_t;
@@ -554,7 +556,7 @@ struct switch_filenames {
typedef struct switch_filenames switch_filenames;
SWITCH_DECLARE_DATA extern switch_filenames SWITCH_GLOBAL_filenames;
-#define SWITCH_MAX_STACKS 16
+#define SWITCH_MAX_STACKS 32
#define SWITCH_THREAD_STACKSIZE 240 * 1024
#define SWITCH_SYSTEM_THREAD_STACKSIZE 8192 * 1024
#define SWITCH_MAX_INTERVAL 120 /* we only do up to 120ms */
@@ -578,7 +580,9 @@ typedef enum {
SWITCH_CPF_NONE = 0,
SWITCH_CPF_SCREEN = (1 << 0),
SWITCH_CPF_HIDE_NAME = (1 << 1),
- SWITCH_CPF_HIDE_NUMBER = (1 << 2)
+ SWITCH_CPF_HIDE_NUMBER = (1 << 2),
+ SWITCH_CPF_SOFT_PREFIX = (1 << 3),
+ SWITCH_CPF_SOFT_LOOKUP = (1 << 4)
} switch_caller_profile_flag_enum_t;
typedef uint32_t switch_caller_profile_flag_t;
@@ -713,6 +717,21 @@ typedef struct {
uint32_t init;
} switch_rtcp_numbers_t;
+typedef struct {
+ uint16_t nack_count;
+ uint16_t fir_count;
+ uint16_t pli_count;
+ uint16_t sr_count;
+ uint16_t rr_count;
+} switch_rtcp_video_counters_t;
+
+typedef struct {
+ /* counters and stats for the incoming video stream and outgoing RTCP*/
+ switch_rtcp_video_counters_t video_in;
+ /* counters and stats for the outgoing video stream and incoming RTCP*/
+ switch_rtcp_video_counters_t video_out;
+} switch_rtcp_video_stats_t;
+
typedef struct {
switch_rtp_numbers_t inbound;
switch_rtp_numbers_t outbound;
@@ -1573,6 +1592,7 @@ typedef enum {
CF_STREAM_CHANGED,
CF_ARRANGED_BRIDGE,
CF_STATE_REPEAT,
+ CF_WANT_DTLSv1_2,
/* WARNING: DO NOT ADD ANY FLAGS BELOW THIS LINE */
/* IF YOU ADD NEW ONES CHECK IF THEY SHOULD PERSIST OR ZERO THEM IN switch_core_session.c switch_core_session_request_xml() */
CF_FLAG_MAX
@@ -2170,7 +2190,13 @@ typedef enum {
SWITCH_CAUSE_INVALID_URL = 610,
SWITCH_CAUSE_INVALID_PROFILE = 611,
SWITCH_CAUSE_NO_PICKUP = 612,
- SWITCH_CAUSE_SRTP_READ_ERROR = 613
+ SWITCH_CAUSE_SRTP_READ_ERROR = 613,
+ SWITCH_CAUSE_BOWOUT = 614,
+ SWITCH_CAUSE_BUSY_EVERYWHERE = 615,
+ SWITCH_CAUSE_DECLINE = 616,
+ SWITCH_CAUSE_DOES_NOT_EXIST_ANYWHERE = 617,
+ SWITCH_CAUSE_NOT_ACCEPTABLE = 618,
+ SWITCH_CAUSE_UNWANTED = 619
} switch_call_cause_t;
typedef enum {
@@ -2642,7 +2668,8 @@ typedef enum {
typedef enum {
ICE_GOOGLE_JINGLE = (1 << 0),
ICE_VANILLA = (1 << 1),
- ICE_CONTROLLED = (1 << 2)
+ ICE_CONTROLLED = (1 << 2),
+ ICE_LITE = (1 << 3)
} switch_core_media_ice_type_t;
typedef enum {
diff --git a/src/include/switch_utils.h b/src/include/switch_utils.h
index 10242525f1..62ec7c8d41 100644
--- a/src/include/switch_utils.h
+++ b/src/include/switch_utils.h
@@ -46,6 +46,16 @@ SWITCH_BEGIN_EXTERN_C
#define SWITCH_URL_UNSAFE "\r\n #%&+:;<=>?@[\\]^`{|}\""
+#define MAX_NETWORK_PORTS 10
+
+struct switch_network_port_range {
+ int port;
+ int ports[MAX_NETWORK_PORTS];
+ int min_port;
+ int max_port;
+};
+typedef struct switch_network_port_range switch_network_port_range_t;
+typedef switch_network_port_range_t* switch_network_port_range_p;
static inline char *switch_get_hex_bytes(switch_byte_t *buf, switch_size_t datalen, char *new_buf, switch_size_t new_datalen)
{
@@ -1270,6 +1280,12 @@ SWITCH_DECLARE(switch_status_t) switch_network_list_add_cidr_token(switch_networ
SWITCH_DECLARE(char *) switch_network_ipv4_mapped_ipv6_addr(const char* ip_str);
SWITCH_DECLARE(switch_status_t) switch_network_list_add_host_mask(switch_network_list_t *list, const char *host, const char *mask_str, switch_bool_t ok);
+
+SWITCH_DECLARE(switch_status_t) switch_network_list_add_cidr_port_token(switch_network_list_t *list, const char *cidr_str, switch_bool_t ok, const char *token, switch_network_port_range_p port);
+SWITCH_DECLARE(switch_status_t) switch_network_list_add_host_port_mask(switch_network_list_t *list, const char *host, const char *mask_str, switch_bool_t ok, switch_network_port_range_p port);
+
+SWITCH_DECLARE(switch_bool_t) switch_network_list_validate_ip_port_token(switch_network_list_t *list, uint32_t ip, int port, const char **token);
+SWITCH_DECLARE(switch_bool_t) switch_network_list_validate_ip6_port_token(switch_network_list_t *list, ip_t ip, int port, const char **token);
SWITCH_DECLARE(switch_bool_t) switch_network_list_validate_ip_token(switch_network_list_t *list, uint32_t ip, const char **token);
SWITCH_DECLARE(switch_bool_t) switch_network_list_validate_ip6_token(switch_network_list_t *list, ip_t ip, const char **token);
#define switch_network_list_validate_ip(_list, _ip) switch_network_list_validate_ip_token(_list, _ip, NULL);
diff --git a/src/mod/Makefile.am b/src/mod/Makefile.am
index 36ed523311..b4f3eb5b0a 100644
--- a/src/mod/Makefile.am
+++ b/src/mod/Makefile.am
@@ -8,6 +8,8 @@ uninstall: $(OUR_UNINSTALL_MODULES) $(OUR_DISABLED_UNINSTALL_MODULES)
mod_skypopen-all: mod_gsmopen-all
mod_gsmopen-all: mod_spandsp-all
mod_unimrcp-all: mod_sofia-all
+mod_rayo-all: mod_dingaling-all
+mod_ssml-all: mod_rayo-all
$(OUR_MODULES) $(OUR_CLEAN_MODULES) $(OUR_INSTALL_MODULES) $(OUR_UNINSTALL_MODULES) $(OUR_DISABLED_MODULES) $(OUR_DISABLED_CLEAN_MODULES) $(OUR_DISABLED_INSTALL_MODULES) $(OUR_DISABLED_UNINSTALL_MODULES):
@set fnord $$MAKEFLAGS; amf=$$2; \
diff --git a/src/mod/applications/mod_av/mod_av.2017.vcxproj b/src/mod/applications/mod_av/mod_av.2017.vcxproj
index 3bd1816c6f..e2cbaa7315 100644
--- a/src/mod/applications/mod_av/mod_av.2017.vcxproj
+++ b/src/mod/applications/mod_av/mod_av.2017.vcxproj
@@ -1,155 +1,219 @@
-
-
-
-
- Debug
- Win32
-
-
- Debug
- x64
-
-
- Release
- Win32
-
-
- Release
- x64
-
-
-
- mod_av
- mod_av
- Win32Proj
- {7AEE504B-23B6-4B05-829E-7CD34855F146}
-
-
-
- DynamicLibrary
- MultiByte
- v141
-
-
- DynamicLibrary
- MultiByte
- v141
-
-
- DynamicLibrary
- MultiByte
- v141
-
-
- DynamicLibrary
- MultiByte
- v141
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- <_ProjectFileVersion>10.0.30319.1
-
-
-
- "../../libvpx";$(SolutionDir)\src\include;%(AdditionalIncludeDirectories)
- WIN32;_DEBUG;_WINDOWS;_USRDLL;MOD_EXPORTS;_CRT_SECURE_NO_DEPRECATE;HAVE_AV_CONFIG_H;_ISOC99_SOURCE;_FILE_OFFSET_BITS=64;_LARGEFILE_SOURCE;_USE_MATH_DEFINES;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WIN32_WINNT=0x0502;%(PreprocessorDefinitions)
- 4244;4127;4018;4389;4146;4057;4204;4706;4305;4152;4324;4013;4100;4214;4273;4554;4701;%(DisableSpecificWarnings)
-
-
- ..\..\..\..\libs\libav\Win32\$(OutDir);%(AdditionalLibraryDirectories)
- false
-
-
-
-
-
-
- X64
-
-
- "../../libvpx";$(SolutionDir)\src\include;%(AdditionalIncludeDirectories)
- WIN32;_DEBUG;_WINDOWS;_USRDLL;MOD_EXPORTS;_CRT_SECURE_NO_DEPRECATE;HAVE_AV_CONFIG_H;_ISOC99_SOURCE;_FILE_OFFSET_BITS=64;_LARGEFILE_SOURCE;_USE_MATH_DEFINES;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WIN32_WINNT=0x0502;%(PreprocessorDefinitions)
- 4244;4127;4018;4389;4146;4057;4204;4706;4305;4152;4324;4013;4100;4214;4273;4554;4701;%(DisableSpecificWarnings)
-
-
-
-
- ..\..\..\..\libs\libav\Win32\$(OutDir);%(AdditionalLibraryDirectories)
- false
-
-
- MachineX64
-
-
-
-
- "../../libvpx";$(SolutionDir)\src\include;%(AdditionalIncludeDirectories)
- WIN32;_DEBUG;_WINDOWS;_USRDLL;MOD_EXPORTS;_CRT_SECURE_NO_DEPRECATE;HAVE_AV_CONFIG_H;_ISOC99_SOURCE;_FILE_OFFSET_BITS=64;_LARGEFILE_SOURCE;_USE_MATH_DEFINES;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WIN32_WINNT=0x0502;%(PreprocessorDefinitions)
- 4244;4127;4018;4389;4146;4057;4204;4706;4305;4152;4324;4013;4100;4214;4273;4554;4701;%(DisableSpecificWarnings)
-
-
-
-
- ..\..\..\..\libs\libav\Win32\$(OutDir);%(AdditionalLibraryDirectories)
- false
-
-
-
-
-
-
- X64
-
-
- "../../libvpx";$(SolutionDir)\src\include;%(AdditionalIncludeDirectories)
- WIN32;_DEBUG;_WINDOWS;_USRDLL;MOD_EXPORTS;_CRT_SECURE_NO_DEPRECATE;HAVE_AV_CONFIG_H;_ISOC99_SOURCE;_FILE_OFFSET_BITS=64;_LARGEFILE_SOURCE;_USE_MATH_DEFINES;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WIN32_WINNT=0x0502;%(PreprocessorDefinitions)
- 4244;4127;4018;4389;4146;4057;4204;4706;4305;4152;4324;4013;4100;4214;4273;4554;4701;%(DisableSpecificWarnings)
-
-
-
-
- ..\..\..\..\libs\libav\Win32\$(OutDir);%(AdditionalLibraryDirectories)
- false
-
-
- MachineX64
-
-
-
-
-
-
-
-
-
- {bc1fd72e-1cd5-4525-a7f5-17c5740bfded}
-
-
- {202d7a4e-760d-4d0e-afa1-d7459ced30ff}
- false
-
-
-
-
-
+
+
+
+
+ Debug-x264
+ Win32
+
+
+ Debug-x264
+ x64
+
+
+ Debug-openh264
+ x64
+
+
+ Release-x264
+ Win32
+
+
+ Release-x264
+ x64
+
+
+ Release-openh264
+ x64
+
+
+
+ mod_av
+ mod_av
+ Win32Proj
+ {7AEE504B-23B6-4B05-829E-7CD34855F146}
+
+
+
+ DynamicLibrary
+ MultiByte
+ v141
+
+
+ DynamicLibrary
+ MultiByte
+ v141
+
+
+ DynamicLibrary
+ MultiByte
+ v141
+
+
+ DynamicLibrary
+ MultiByte
+ v141
+
+
+ DynamicLibrary
+ MultiByte
+ v141
+
+
+ DynamicLibrary
+ MultiByte
+ v141
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ProjectFileVersion>10.0.30319.1
+
+
+
+ "../../libvpx";$(SolutionDir)\src\include;%(AdditionalIncludeDirectories)
+ WIN32;_DEBUG;_WINDOWS;_USRDLL;MOD_EXPORTS;_CRT_SECURE_NO_DEPRECATE;HAVE_AV_CONFIG_H;_ISOC99_SOURCE;_FILE_OFFSET_BITS=64;_LARGEFILE_SOURCE;_USE_MATH_DEFINES;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WIN32_WINNT=0x0502;%(PreprocessorDefinitions)
+ 4244;4127;4018;4389;4146;4057;4204;4706;4305;4152;4324;4013;4100;4214;4273;4554;4701;%(DisableSpecificWarnings)
+
+
+ ..\..\..\..\libs\libav\Win32\$(OutDir);%(AdditionalLibraryDirectories)
+ false
+
+
+
+
+
+
+ X64
+
+
+ "../../libvpx";$(SolutionDir)\src\include;%(AdditionalIncludeDirectories)
+ WIN32;_DEBUG;_WINDOWS;_USRDLL;MOD_EXPORTS;_CRT_SECURE_NO_DEPRECATE;HAVE_AV_CONFIG_H;_ISOC99_SOURCE;_FILE_OFFSET_BITS=64;_LARGEFILE_SOURCE;_USE_MATH_DEFINES;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WIN32_WINNT=0x0502;%(PreprocessorDefinitions)
+ 4244;4127;4018;4389;4146;4057;4204;4706;4305;4152;4324;4013;4100;4214;4273;4554;4701;%(DisableSpecificWarnings)
+
+
+
+
+ ..\..\..\..\libs\libav\Win32\$(OutDir);%(AdditionalLibraryDirectories)
+ false
+
+
+ MachineX64
+
+
+
+
+ X64
+
+
+ "../../libvpx";$(SolutionDir)\src\include;%(AdditionalIncludeDirectories)
+ WIN32;_DEBUG;_WINDOWS;_USRDLL;MOD_EXPORTS;_CRT_SECURE_NO_DEPRECATE;HAVE_AV_CONFIG_H;_ISOC99_SOURCE;_FILE_OFFSET_BITS=64;_LARGEFILE_SOURCE;_USE_MATH_DEFINES;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WIN32_WINNT=0x0502;%(PreprocessorDefinitions)
+ 4244;4127;4018;4389;4146;4057;4204;4706;4305;4152;4324;4013;4100;4214;4273;4554;4701;%(DisableSpecificWarnings)
+
+
+
+
+ ..\..\..\..\libs\libav\Win32\$(OutDir);%(AdditionalLibraryDirectories)
+ false
+
+
+ MachineX64
+
+
+
+
+ "../../libvpx";$(SolutionDir)\src\include;%(AdditionalIncludeDirectories)
+ WIN32;_DEBUG;_WINDOWS;_USRDLL;MOD_EXPORTS;_CRT_SECURE_NO_DEPRECATE;HAVE_AV_CONFIG_H;_ISOC99_SOURCE;_FILE_OFFSET_BITS=64;_LARGEFILE_SOURCE;_USE_MATH_DEFINES;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WIN32_WINNT=0x0502;%(PreprocessorDefinitions)
+ 4244;4127;4018;4389;4146;4057;4204;4706;4305;4152;4324;4013;4100;4214;4273;4554;4701;%(DisableSpecificWarnings)
+
+
+
+
+ ..\..\..\..\libs\libav\Win32\$(OutDir);%(AdditionalLibraryDirectories)
+ false
+
+
+
+
+
+
+ X64
+
+
+ "../../libvpx";$(SolutionDir)\src\include;%(AdditionalIncludeDirectories)
+ WIN32;_DEBUG;_WINDOWS;_USRDLL;MOD_EXPORTS;_CRT_SECURE_NO_DEPRECATE;HAVE_AV_CONFIG_H;_ISOC99_SOURCE;_FILE_OFFSET_BITS=64;_LARGEFILE_SOURCE;_USE_MATH_DEFINES;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WIN32_WINNT=0x0502;%(PreprocessorDefinitions)
+ 4244;4127;4018;4389;4146;4057;4204;4706;4305;4152;4324;4013;4100;4214;4273;4554;4701;%(DisableSpecificWarnings)
+
+
+
+
+ ..\..\..\..\libs\libav\Win32\$(OutDir);%(AdditionalLibraryDirectories)
+ false
+
+
+ MachineX64
+
+
+
+
+ X64
+
+
+ "../../libvpx";$(SolutionDir)\src\include;%(AdditionalIncludeDirectories)
+ WIN32;_DEBUG;_WINDOWS;_USRDLL;MOD_EXPORTS;_CRT_SECURE_NO_DEPRECATE;HAVE_AV_CONFIG_H;_ISOC99_SOURCE;_FILE_OFFSET_BITS=64;_LARGEFILE_SOURCE;_USE_MATH_DEFINES;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_WIN32_WINNT=0x0502;%(PreprocessorDefinitions)
+ 4244;4127;4018;4389;4146;4057;4204;4706;4305;4152;4324;4013;4100;4214;4273;4554;4701;%(DisableSpecificWarnings)
+
+
+
+
+ ..\..\..\..\libs\libav\Win32\$(OutDir);%(AdditionalLibraryDirectories)
+ false
+
+
+ MachineX64
+
+
+
+
+
+
+
+
+
+ {bc1fd72e-1cd5-4525-a7f5-17c5740bfded}
+
+
+ {202d7a4e-760d-4d0e-afa1-d7459ced30ff}
+ false
+
+
+
+
+
\ No newline at end of file
diff --git a/src/mod/applications/mod_avmd/mod_avmd.c b/src/mod/applications/mod_avmd/mod_avmd.c
index 828cf1fced..aabd96c1ae 100644
--- a/src/mod/applications/mod_avmd/mod_avmd.c
+++ b/src/mod/applications/mod_avmd/mod_avmd.c
@@ -644,11 +644,11 @@ static switch_bool_t avmd_callback(switch_media_bug_t * bug, void *user_data, sw
case SWITCH_ABC_TYPE_CLOSE:
avmd_session_close(avmd_session);
- switch_mutex_lock(avmd_globals.mutex);
+ switch_mutex_lock(avmd_globals.mutex);
if (avmd_globals.session_n > 0) {
--avmd_globals.session_n;
}
- switch_mutex_unlock(avmd_globals.mutex);
+ switch_mutex_unlock(avmd_globals.mutex);
break;
default:
@@ -1151,7 +1151,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_avmd_load) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No memory pool assigned!\n");
return SWITCH_STATUS_TERM;
}
- switch_mutex_init(&avmd_globals.mutex, SWITCH_MUTEX_DEFAULT, pool);
+ switch_mutex_init(&avmd_globals.mutex, SWITCH_MUTEX_NESTED, pool);
avmd_globals.pool = pool;
if (avmd_load_xml_configuration(NULL) != SWITCH_STATUS_SUCCESS) {
diff --git a/src/mod/applications/mod_callcenter/mod_callcenter.c b/src/mod/applications/mod_callcenter/mod_callcenter.c
index bc320eb0d2..b3f5ca6fee 100644
--- a/src/mod/applications/mod_callcenter/mod_callcenter.c
+++ b/src/mod/applications/mod_callcenter/mod_callcenter.c
@@ -435,6 +435,7 @@ static struct {
switch_mutex_t *mutex;
switch_memory_pool_t *pool;
switch_event_node_t *node;
+ int agent_originate_timeout;
} globals;
#define CC_QUEUE_CONFIGITEM_COUNT 100
@@ -1495,6 +1496,8 @@ static switch_status_t load_config(void)
globals.global_database_lock = switch_true(val);
} else if (!strcasecmp(var, "cc-instance-id")) {
globals.cc_instance_id = strdup(val);
+ } else if (!strcasecmp(var, "agent-originate-timeout")) {
+ globals.agent_originate_timeout = atoi(val);
}
}
}
@@ -1511,9 +1514,11 @@ static switch_status_t load_config(void)
}
if (!globals.global_database_lock) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Disabling global database lock\n");
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Disabling global database lock\n");
}
+ if (!globals.agent_originate_timeout) globals.agent_originate_timeout = 60;
+
/* Initialize database */
if (!(dbh = cc_get_db_handle())) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Cannot open DB!\n");
@@ -1707,7 +1712,7 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
dialstr = switch_channel_expand_variables(member_channel, h->originate_string);
switch_channel_set_app_flag_key(CC_APP_KEY, member_channel, CC_APP_AGENT_CONNECTING);
- status = switch_ivr_originate(NULL, &agent_session, &cause, dialstr, 60, NULL, cid_name ? cid_name : h->member_cid_name, cid_number ? cid_number : h->member_cid_number, NULL, ovars, SOF_NONE, NULL, NULL);
+ status = switch_ivr_originate(NULL, &agent_session, &cause, dialstr, globals.agent_originate_timeout, NULL, cid_name ? cid_name : h->member_cid_name, cid_number ? cid_number : h->member_cid_number, NULL, ovars, SOF_NONE, NULL, NULL);
/* Search for loopback agent */
if (status == SWITCH_STATUS_SUCCESS) {
diff --git a/src/mod/applications/mod_commands/mod_commands.c b/src/mod/applications/mod_commands/mod_commands.c
index 38a688792e..025f27f98b 100644
--- a/src/mod/applications/mod_commands/mod_commands.c
+++ b/src/mod/applications/mod_commands/mod_commands.c
@@ -3886,8 +3886,11 @@ SWITCH_STANDARD_API(uuid_broadcast_function)
flags = SMF_ECHO_ALEG | SMF_HOLD_BLEG;
}
- switch_ivr_broadcast(argv[0], argv[1], flags);
- stream->write_function(stream, "+OK Message sent\n");
+ if (switch_ivr_broadcast(argv[0], argv[1], flags) == SWITCH_STATUS_SUCCESS) {
+ stream->write_function(stream, "+OK Message sent\n");
+ } else {
+ stream->write_function(stream, "-ERR invalid uuid\n");
+ }
}
switch_safe_free(mycmd);
@@ -4657,14 +4660,16 @@ SWITCH_STANDARD_API(uuid_bridge_function)
return SWITCH_STATUS_SUCCESS;
}
-#define SESS_REC_SYNTAX " [start|stop|mask|unmask] []"
+#define SESS_REC_SYNTAX " [start|stop|mask|unmask] [] []"
SWITCH_STANDARD_API(session_record_function)
{
switch_core_session_t *rsession = NULL;
- char *mycmd = NULL, *argv[4] = { 0 };
+ char *mycmd = NULL, *argv[5] = { 0 };
char *uuid = NULL, *action = NULL, *path = NULL;
int argc = 0;
uint32_t limit = 0;
+ switch_event_t *vars = NULL;
+ char *new_fp = NULL;
if (zstr(cmd)) {
goto usage;
@@ -4693,11 +4698,16 @@ SWITCH_STANDARD_API(session_record_function)
}
if (!strcasecmp(action, "start")) {
- if (switch_ivr_record_session(rsession, path, limit, NULL) != SWITCH_STATUS_SUCCESS) {
+ if(argc > 3) {
+ switch_url_decode(argv[4]);
+ switch_event_create_brackets(argv[4], '{', '}',',', &vars, &new_fp, SWITCH_FALSE);
+ }
+ if (switch_ivr_record_session_event(rsession, path, limit, NULL, vars) != SWITCH_STATUS_SUCCESS) {
stream->write_function(stream, "-ERR Cannot record session!\n");
} else {
stream->write_function(stream, "+OK Success\n");
}
+ switch_event_safe_destroy(vars);
} else if (!strcasecmp(action, "stop")) {
if (switch_ivr_stop_record_session(rsession, path) != SWITCH_STATUS_SUCCESS) {
stream->write_function(stream, "-ERR Cannot stop record session!\n");
@@ -4934,6 +4944,8 @@ SWITCH_STANDARD_API(break_function)
}
}
+ stream->write_function(stream, "+OK\n");
+
done:
if (psession) {
diff --git a/src/mod/applications/mod_conference/conference_api.c b/src/mod/applications/mod_conference/conference_api.c
index 3e15aa9fd8..7fcf005c30 100644
--- a/src/mod/applications/mod_conference/conference_api.c
+++ b/src/mod/applications/mod_conference/conference_api.c
@@ -810,10 +810,16 @@ switch_status_t conference_api_sub_hup(conference_member_t *member, switch_strea
switch_event_t *event;
if (member == NULL) {
+ if (stream != NULL) {
+ stream->write_function(stream, "-ERR Invalid member!\n");
+ }
return SWITCH_STATUS_GENERR;
}
conference_utils_member_clear_flag(member, MFLAG_RUNNING);
+ if (stream != NULL) {
+ stream->write_function(stream, "+OK hup %u\n", member->id);
+ }
if (member->conference && test_eflag(member->conference, EFLAG_HUP_MEMBER)) {
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) {
@@ -1852,7 +1858,12 @@ switch_status_t conference_api_sub_vid_res(conference_obj_t *conference, switch_
}
if (canvas_w < 320 || canvas_h < 180) {
- stream->write_function(stream, "-ERR Invalid size\n");
+ stream->write_function(stream, "-ERR Invalid size, [%dx%d] is too small\n", canvas_w, canvas_h);
+ return SWITCH_STATUS_SUCCESS;
+ }
+
+ if (canvas_w > 7680 || canvas_h > 4320) {
+ stream->write_function(stream, "-ERR Invalid size, [%dx%d] is too large.\n", canvas_w, canvas_h);
return SWITCH_STATUS_SUCCESS;
}
@@ -1877,7 +1888,11 @@ switch_status_t conference_api_sub_vid_res(conference_obj_t *conference, switch_
id = 1;
}
- conference_video_change_res(conference, canvas_w, canvas_h, id - 1);
+ if (conference_video_change_res(conference, canvas_w, canvas_h, id - 1) == SWITCH_STATUS_SUCCESS) {
+ stream->write_function(stream, "+OK Resolution set to [%dx%d]\n", canvas_w, canvas_h);
+ } else {
+ stream->write_function(stream, "-ERR Resolution not set\n");
+ }
return SWITCH_STATUS_SUCCESS;
}
@@ -3556,9 +3571,9 @@ switch_status_t conference_api_sub_dial(conference_obj_t *conference, switch_str
}
if (conference) {
- conference_outcall(conference, NULL, NULL, argv[2], 60, NULL, argv[4], argv[3], NULL, &cause, NULL, NULL);
+ conference_outcall(conference, NULL, NULL, argv[2], 60, NULL, argv[4], argv[3], NULL, &cause, NULL, NULL, NULL);
} else {
- conference_outcall(NULL, argv[0], NULL, argv[2], 60, NULL, argv[4], argv[3], NULL, &cause, NULL, NULL);
+ conference_outcall(NULL, argv[0], NULL, argv[2], 60, NULL, argv[4], argv[3], NULL, &cause, NULL, NULL, NULL);
}
stream->write_function(stream, "+OK Call Requested: result: [%s]\n", switch_channel_cause2str(cause));
diff --git a/src/mod/applications/mod_conference/conference_event.c b/src/mod/applications/mod_conference/conference_event.c
index cd9b5c2b81..083dd35490 100644
--- a/src/mod/applications/mod_conference/conference_event.c
+++ b/src/mod/applications/mod_conference/conference_event.c
@@ -398,7 +398,7 @@ void conference_event_mod_channel_handler(const char *event_channel, cJSON *json
} else if (exec) {
cJSON_AddItemToObject(jdata, "conf-command", cJSON_CreateString(exec));
cJSON_AddItemToObject(jdata, "response", cJSON_CreateString((char *)stream.data));
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ALERT,"RES [%s][%s]\n", exec, (char *)stream.data);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"RES [%s][%s]\n", exec, (char *)stream.data);
} else {
cJSON_AddItemToObject(jdata, "error", cJSON_CreateString("Invalid Command"));
}
@@ -741,10 +741,12 @@ switch_status_t conference_event_add_data(conference_obj_t *conference, switch_e
switch_status_t status = SWITCH_STATUS_SUCCESS;
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Conference-Name", conference->name);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Conference-Domain", conference->domain);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Conference-Size", "%u", conference->count);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Conference-Ghosts", "%u", conference->count_ghosts);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Conference-Profile-Name", conference->profile_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Conference-Unique-ID", conference->uuid_str);
+ switch_event_merge(event, conference->variables);
return status;
}
diff --git a/src/mod/applications/mod_conference/conference_loop.c b/src/mod/applications/mod_conference/conference_loop.c
index 49377312c6..78024f10de 100644
--- a/src/mod/applications/mod_conference/conference_loop.c
+++ b/src/mod/applications/mod_conference/conference_loop.c
@@ -939,6 +939,10 @@ void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, void *ob
goto do_continue;
}
+ if (!switch_channel_test_app_flag(channel, CF_AUDIO)) {
+ goto do_continue;
+ }
+
/* if the member can speak, compute the audio energy level and */
/* generate events when the level crosses the threshold */
if (((conference_utils_member_test_flag(member, MFLAG_CAN_SPEAK) && !conference_utils_member_test_flag(member, MFLAG_HOLD)) ||
@@ -1228,7 +1232,7 @@ void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, void *ob
if (datalen) {
switch_size_t ok = 1;
-
+
/* Write the audio into the input buffer */
switch_mutex_lock(member->audio_in_mutex);
if (switch_buffer_inuse(member->audio_buffer) > flush_len) {
diff --git a/src/mod/applications/mod_conference/conference_member.c b/src/mod/applications/mod_conference/conference_member.c
index 152dfb8aa5..9f43417fe9 100644
--- a/src/mod/applications/mod_conference/conference_member.c
+++ b/src/mod/applications/mod_conference/conference_member.c
@@ -76,6 +76,7 @@ void conference_member_bind_controls(conference_member_t *member, const char *co
switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "Conf-Profile", member->conference->profile_name);
switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "Action", "request-controls");
switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "Controls", controls);
+ switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "Fetch-Call-UUID", switch_core_session_get_uuid(member->session));
if (!(cxml = switch_xml_open_cfg(mod_conference_cf_name, &cfg, params))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", mod_conference_cf_name);
@@ -762,7 +763,7 @@ switch_status_t conference_member_add(conference_obj_t *conference, conference_m
}
if ((var = switch_channel_get_variable_dup(member->channel, "conference_join_volume_in", SWITCH_FALSE, -1))) {
- uint32_t id = atoi(var);
+ int id = atoi(var);
if (id > -5 && id < 5) {
member->volume_in_level = id;
@@ -770,7 +771,7 @@ switch_status_t conference_member_add(conference_obj_t *conference, conference_m
}
if ((var = switch_channel_get_variable_dup(member->channel, "conference_join_volume_out", SWITCH_FALSE, -1))) {
- uint32_t id = atoi(var);
+ int id = atoi(var);
if (id > -5 && id < 5) {
member->volume_out_level = id;
@@ -779,15 +780,15 @@ switch_status_t conference_member_add(conference_obj_t *conference, conference_m
if ((var = switch_channel_get_variable_dup(member->channel, "conference_join_energy_level", SWITCH_FALSE, -1))) {
- uint32_t id = atoi(var);
+ int id = atoi(var);
- if (id > -5 && id < 5) {
+ if (id > -2 && id < 1801) {
member->energy_level = id;
}
}
if ((var = switch_channel_get_variable_dup(member->channel, "video_initial_canvas", SWITCH_FALSE, -1))) {
- uint32_t id = atoi(var) - 1;
+ int id = atoi(var) - 1;
if (id < conference->canvas_count) {
member->canvas_id = id;
member->layer_timeout = DEFAULT_LAYER_TIMEOUT;
@@ -795,7 +796,7 @@ switch_status_t conference_member_add(conference_obj_t *conference, conference_m
}
if ((var = switch_channel_get_variable_dup(member->channel, "video_initial_watching_canvas", SWITCH_FALSE, -1))) {
- uint32_t id = atoi(var) - 1;
+ int id = atoi(var) - 1;
if (id == 0) {
id = conference->canvas_count;
diff --git a/src/mod/applications/mod_conference/conference_record.c b/src/mod/applications/mod_conference/conference_record.c
index c02bb3bcff..d4ccf81c5e 100644
--- a/src/mod/applications/mod_conference/conference_record.c
+++ b/src/mod/applications/mod_conference/conference_record.c
@@ -91,7 +91,6 @@ switch_status_t conference_record_stop(conference_obj_t *conference, switch_stre
switch_mutex_lock(conference->member_mutex);
for (member = conference->members; member; member = member->next) {
if (conference_utils_member_test_flag(member, MFLAG_NOCHANNEL) && (!path || !strcmp(path, member->rec_path))) {
- conference->record_count--;
if (!conference_utils_test_flag(conference, CFLAG_CONF_RESTART_AUTO_RECORD) && member->rec && member->rec->autorec) {
stream->write_function(stream, "Stopped AUTO recording file %s (Auto Recording Now Disabled)\n", member->rec_path);
conference->auto_record = 0;
@@ -155,7 +154,7 @@ void *SWITCH_THREAD_FUNC conference_record_thread_run(switch_thread_t *thread, v
{
int16_t *data_buf;
conference_member_t smember = { 0 }, *member;
- conference_record_t *rp, *last = NULL, *rec = (conference_record_t *) obj;
+ conference_record_t *rp, *rec = (conference_record_t *) obj;
conference_obj_t *conference = rec->conference;
uint32_t samples = switch_samples_per_packet(conference->rate, conference->interval);
uint32_t mux_used;
@@ -422,6 +421,7 @@ void *SWITCH_THREAD_FUNC conference_record_thread_run(switch_thread_t *thread, v
switch_core_file_close(&member->rec->fh);
}
+ conference->record_count--;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Recording of %s Stopped\n", rec->path);
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) {
@@ -455,11 +455,7 @@ void *SWITCH_THREAD_FUNC conference_record_thread_run(switch_thread_t *thread, v
switch_mutex_lock(conference->flag_mutex);
for (rp = conference->rec_node_head; rp; rp = rp->next) {
if (rec == rp) {
- if (last) {
- last->next = rp->next;
- } else {
- conference->rec_node_head = rp->next;
- }
+ conference->rec_node_head = rp->next;
}
}
switch_mutex_unlock(conference->flag_mutex);
diff --git a/src/mod/applications/mod_conference/conference_video.c b/src/mod/applications/mod_conference/conference_video.c
index 7a78e1b1a8..ba736bcea1 100644
--- a/src/mod/applications/mod_conference/conference_video.c
+++ b/src/mod/applications/mod_conference/conference_video.c
@@ -2031,6 +2031,8 @@ video_layout_t *conference_video_get_layout(conference_obj_t *conference, const
layout_group_t *lg = NULL;
video_layout_t *vlayout = NULL;
+ if (!video_layout_name) return NULL;
+
if (video_layout_group) {
lg = switch_core_hash_find(conference->layout_group_hash, video_layout_group);
vlayout = conference_video_find_best_layout(conference, lg, 0, 0);
diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c
index ccac9cc99f..86be4911a8 100644
--- a/src/mod/applications/mod_conference/mod_conference.c
+++ b/src/mod/applications/mod_conference/mod_conference.c
@@ -611,7 +611,7 @@ void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, void *ob
for (omember = conference->members; omember; omember = omember->next) {
switch_size_t ok = 1;
- if (!conference_utils_member_test_flag(omember, MFLAG_RUNNING)) {
+ if (!conference_utils_member_test_flag(omember, MFLAG_RUNNING) || !switch_channel_test_flag(omember->channel, CF_AUDIO)) {
continue;
}
@@ -667,13 +667,14 @@ void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, void *ob
write_frame[x] = (int16_t) z;
}
- switch_mutex_lock(omember->audio_out_mutex);
- ok = switch_buffer_write(omember->mux_buffer, write_frame, bytes);
- switch_mutex_unlock(omember->audio_out_mutex);
-
- if (!ok) {
- switch_mutex_unlock(conference->mutex);
- goto end;
+ if (switch_channel_test_flag(omember->channel, CF_AUDIO)) {
+ switch_mutex_lock(omember->audio_out_mutex);
+ ok = switch_buffer_write(omember->mux_buffer, write_frame, bytes);
+ switch_mutex_unlock(omember->audio_out_mutex);
+ if (!ok) {
+ switch_mutex_unlock(conference->mutex);
+ goto end;
+ }
}
}
} else { /* There is no source audio. Push silence into all of the buffers */
@@ -688,7 +689,7 @@ void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, void *ob
for (omember = conference->members; omember; omember = omember->next) {
switch_size_t ok = 1;
- if (!conference_utils_member_test_flag(omember, MFLAG_RUNNING)) {
+ if (!conference_utils_member_test_flag(omember, MFLAG_RUNNING) || !switch_channel_test_flag(omember->channel, CF_AUDIO)) {
continue;
}
@@ -1133,7 +1134,8 @@ switch_xml_t add_x_tag(switch_xml_t x_member, const char *name, const char *valu
void conference_xlist(conference_obj_t *conference, switch_xml_t x_conference, int off)
{
conference_member_t *member = NULL;
- switch_xml_t x_member = NULL, x_members = NULL, x_flags;
+ switch_xml_t x_member = NULL, x_members = NULL, x_flags, x_variables;
+ switch_event_header_t *hp;
int moff = 0;
char i[30] = "";
char *ival = i;
@@ -1218,6 +1220,13 @@ void conference_xlist(conference_obj_t *conference, switch_xml_t x_conference, i
switch_snprintf(i, sizeof(i), "%d", switch_epoch_time_now(NULL) - conference->run_time);
switch_xml_set_attr_d(x_conference, "run_time", ival);
+ x_variables = switch_xml_add_child_d(x_conference, "variables", 0);
+ for (hp = conference->variables->headers; hp; hp = hp->next) {
+ switch_xml_t x_variable = switch_xml_add_child_d(x_variables, "variable", 0);
+ switch_xml_set_attr_d(x_variable, "name", hp->name);
+ switch_xml_set_attr_d(x_variable, "value", hp->value);
+ }
+
x_members = switch_xml_add_child_d(x_conference, "members", 0);
switch_assert(x_members);
@@ -1339,7 +1348,8 @@ void conference_xlist(conference_obj_t *conference, switch_xml_t x_conference, i
void conference_jlist(conference_obj_t *conference, cJSON *json_conferences)
{
conference_member_t *member = NULL;
- static cJSON *json_conference, *json_conference_members, *json_conference_member, *json_conference_member_flags;
+ static cJSON *json_conference, *json_conference_variables, *json_conference_members, *json_conference_member, *json_conference_member_flags;
+ switch_event_header_t *hp;
switch_assert(conference != NULL);
json_conference = cJSON_CreateObject();
@@ -1379,6 +1389,11 @@ void conference_jlist(conference_obj_t *conference, cJSON *json_conferences)
cJSON_AddNumberToObject(json_conference, "max_members", conference->max_members);
}
+ cJSON_AddItemToObject(json_conference, "variables", json_conference_variables = cJSON_CreateObject());
+ for (hp = conference->variables->headers; hp; hp = hp->next) {
+ cJSON_AddStringToObject(json_conference_variables, hp->name, hp->value);
+ }
+
cJSON_AddItemToObject(json_conference, "members", json_conference_members = cJSON_CreateArray());
switch_mutex_lock(conference->member_mutex);
for (member = conference->members; member; member = member->next) {
@@ -1498,7 +1513,10 @@ switch_status_t conference_outcall(conference_obj_t *conference,
char *cid_num,
char *profile,
switch_call_cause_t *cause,
- switch_call_cause_t *cancel_cause, switch_event_t *var_event)
+ switch_call_cause_t *cancel_cause,
+ switch_event_t *var_event,
+ char** peer_uuid
+ )
{
switch_core_session_t *peer_session = NULL;
switch_channel_t *peer_channel;
@@ -1608,6 +1626,10 @@ switch_status_t conference_outcall(conference_obj_t *conference,
if (switch_channel_test_flag(peer_channel, CF_ANSWERED) || switch_channel_test_flag(peer_channel, CF_EARLY_MEDIA)) {
switch_caller_extension_t *extension = NULL;
+ if(peer_uuid) {
+ *peer_uuid = switch_channel_get_uuid(peer_channel);
+ }
+
/* build an extension name object */
if ((extension = switch_caller_extension_new(peer_session, conference_name, conference_name)) == 0) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Memory Error!\n");
@@ -1654,6 +1676,7 @@ switch_status_t conference_outcall(conference_obj_t *conference,
void *SWITCH_THREAD_FUNC conference_outcall_run(switch_thread_t *thread, void *obj)
{
struct bg_call *call = (struct bg_call *) obj;
+ char* peer_uuid = NULL;
if (call) {
switch_call_cause_t cause;
@@ -1662,7 +1685,7 @@ void *SWITCH_THREAD_FUNC conference_outcall_run(switch_thread_t *thread, void *o
conference_outcall(call->conference, call->conference_name,
call->session, call->bridgeto, call->timeout,
- call->flags, call->cid_name, call->cid_num, call->profile, &cause, call->cancel_cause, call->var_event);
+ call->flags, call->cid_name, call->cid_num, call->profile, &cause, call->cancel_cause, call->var_event, &peer_uuid);
if (call->conference && test_eflag(call->conference, EFLAG_BGDIAL_RESULT) &&
switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) {
@@ -1670,6 +1693,7 @@ void *SWITCH_THREAD_FUNC conference_outcall_run(switch_thread_t *thread, void *o
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action", "bgdial-result");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Result", switch_channel_cause2str(cause));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Job-UUID", call->uuid);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Peer-UUID", peer_uuid);
switch_event_fire(&event);
}
@@ -1715,6 +1739,8 @@ switch_status_t conference_outcall_bg(conference_obj_t *conference,
if (var_event) {
call->var_event = *var_event;
var_event = NULL;
+ } else {
+ switch_event_create_plain(&call->var_event, SWITCH_EVENT_GENERAL);
}
if (conference) {
@@ -1743,6 +1769,9 @@ switch_status_t conference_outcall_bg(conference_obj_t *conference,
if (call_uuid) {
call->uuid = strdup(call_uuid);
+ if (call->var_event) {
+ switch_event_add_header_string(call->var_event, SWITCH_STACK_BOTTOM, "conference_bgdial_jobid", call->uuid);
+ }
}
if (profile) {
@@ -1986,6 +2015,7 @@ SWITCH_STANDARD_APP(conference_function)
switch_assert(params);
switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "conference_name", conference_name);
switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "profile_name", profile_name);
+ switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "Fetch-Call-UUID", switch_core_session_get_uuid(session));
/* Open the config from the xml registry */
if (!(cxml = switch_xml_open_cfg(mod_conference_cf_name, &cfg, params))) {
@@ -2340,7 +2370,7 @@ SWITCH_STANDARD_APP(conference_function)
/* if we're using "bridge:" make an outbound call and bridge it in */
if (!zstr(bridgeto) && strcasecmp(bridgeto, "none")) {
switch_call_cause_t cause;
- if (conference_outcall(conference, NULL, session, bridgeto, 60, NULL, NULL, NULL, NULL, &cause, NULL, NULL) != SWITCH_STATUS_SUCCESS) {
+ if (conference_outcall(conference, NULL, session, bridgeto, 60, NULL, NULL, NULL, NULL, &cause, NULL, NULL, NULL) != SWITCH_STATUS_SUCCESS) {
goto done;
}
} else {
@@ -3748,10 +3778,22 @@ conference_obj_t *conference_new(char *name, conference_xml_cfg_t cfg, switch_co
}
}
+ if (cfg.profile) {
+ switch_xml_t xml_profile_variables;
+ if ((xml_profile_variables = switch_xml_child(cfg.profile, "variables")) != NULL) {
+ for (xml_kvp = switch_xml_child(xml_profile_variables, "variable"); xml_kvp; xml_kvp = xml_kvp->next) {
+ char *var = (char *) switch_xml_attr_soft(xml_kvp, "name");
+ char *val = (char *) switch_xml_attr_soft(xml_kvp, "value");
+ if (var && val) {
+ conference_set_variable(conference, var, val);
+ }
+ }
+ }
+ }
switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT);
conference_event_add_data(conference, event);
- if(conference->verbose_events && channel) {
+ if (conference->verbose_events && channel) {
switch_channel_event_set_data(channel, event);
}
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action", "conference-create");
diff --git a/src/mod/applications/mod_conference/mod_conference.h b/src/mod/applications/mod_conference/mod_conference.h
index bb887536e1..ccded3bfb5 100644
--- a/src/mod/applications/mod_conference/mod_conference.h
+++ b/src/mod/applications/mod_conference/mod_conference.h
@@ -1135,7 +1135,9 @@ switch_status_t conference_outcall(conference_obj_t *conference,
char *cid_num,
char *profile,
switch_call_cause_t *cause,
- switch_call_cause_t *cancel_cause, switch_event_t *var_event);
+ switch_call_cause_t *cancel_cause,
+ switch_event_t *var_event,
+ char** peer_uuid);
switch_status_t conference_outcall_bg(conference_obj_t *conference,
char *conference_name,
switch_core_session_t *session, char *bridgeto, uint32_t timeout, const char *flags, const char *cid_name,
diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c
index aa68cb2c5b..60105de3c9 100644
--- a/src/mod/applications/mod_dptools/mod_dptools.c
+++ b/src/mod/applications/mod_dptools/mod_dptools.c
@@ -587,6 +587,23 @@ SWITCH_STANDARD_APP(sched_heartbeat_function)
}
+#define FILTER_CODECS_SYNTAX ""
+SWITCH_STANDARD_APP(filter_codecs_function)
+{
+ const char *r_sdp;
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+
+
+ r_sdp = switch_channel_get_variable(channel, SWITCH_R_SDP_VARIABLE);
+
+ if (data && r_sdp) {
+ switch_core_media_merge_sdp_codec_string(session, r_sdp, SDP_TYPE_REQUEST, data);
+ switch_channel_set_variable(channel, "filter_codec_string", data);
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Incomplete data\n");
+ }
+}
+
#define HEARTBEAT_SYNTAX "[0|]"
SWITCH_STANDARD_APP(heartbeat_function)
@@ -2913,6 +2930,50 @@ SWITCH_STANDARD_APP(phrase_function)
}
+SWITCH_STANDARD_APP(broadcast_function)
+{
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ char * uuid = switch_channel_get_uuid(channel);
+ switch_media_flag_t flags = SMF_ECHO_ALEG | SMF_ECHO_BLEG;
+ char *mycmd = NULL, *argv[4] = { 0 };
+ int argc = 0;
+
+ if (zstr(data)) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "invalid args for broadcast app\n");
+ return;
+ }
+
+ mycmd = switch_core_session_strdup(session, data);
+ argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
+
+ if (argc > 2) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "invalid args for broadcast app [%s]\n", data);
+ return;
+ } else {
+ if (argv[1]) {
+ if (switch_stristr("both", (argv[1]))) {
+ flags |= (SMF_ECHO_ALEG | SMF_ECHO_BLEG);
+ }
+
+ if (switch_stristr("aleg", argv[1])) {
+ flags |= SMF_ECHO_ALEG;
+ }
+
+ if (switch_stristr("bleg", argv[1])) {
+ flags &= ~SMF_HOLD_BLEG;
+ flags |= SMF_ECHO_BLEG;
+ }
+
+ if (switch_stristr("holdb", argv[1])) {
+ flags &= ~SMF_ECHO_BLEG;
+ flags |= SMF_HOLD_BLEG;
+ }
+ }
+ switch_ivr_broadcast(uuid, argv[0], flags);
+ switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "BROADCAST_SENT");
+ }
+}
+
SWITCH_STANDARD_APP(playback_function)
{
switch_input_args_t args = { 0 };
@@ -3190,40 +3251,43 @@ SWITCH_STANDARD_APP(record_session_unmask_function)
SWITCH_STANDARD_APP(record_session_function)
{
+ char *array[5] = {0};
+ char *args = NULL;
+ int argc;
+
char *path = NULL;
- char *path_end;
uint32_t limit = 0;
+ switch_event_t *vars = NULL;
+ char *new_fp = NULL;
if (zstr(data)) {
return;
}
- path = switch_core_session_strdup(session, data);
+ args = switch_core_session_strdup(session, data);
+ argc = switch_split(args, ' ', array);
- /* Search for a space then a plus followed by only numbers at the end of the path,
- if found trim any spaces to the left/right of the plus use the left side as the
- path and right side as a time limit on the recording
- */
+ if (argc == 0) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "usage: [+] [{var1=x,var2=y}]\n");
+ }
- /* if we find a + and the character before it is a space */
- if ((path_end = strrchr(path, '+')) && path_end > path && *(path_end - 1) == ' ') {
- char *limit_start = path_end + 1;
+ path = array[0];
- /* not at the end and the rest is numbers lets parse out the limit and fix up the path */
- if (*limit_start != '\0' && switch_is_number(limit_start) == SWITCH_TRUE) {
- limit = atoi(limit_start);
- /* back it off by one character to the char before the + */
- path_end--;
-
- /* trim spaces to the left of the plus */
- while (path_end > path && *path_end == ' ') {
- path_end--;
+ if (argc > 1) {
+ if (*array[1] == '+') {
+ limit = atoi(++array[1]);
+ if (argc > 2) {
+ switch_url_decode(array[2]);
+ switch_event_create_brackets(array[2], '{', '}',',', &vars, &new_fp, SWITCH_FALSE);
}
-
- *(path_end + 1) = '\0';
+ } else {
+ switch_url_decode(array[1]);
+ switch_event_create_brackets(array[1], '{', '}',',', &vars, &new_fp, SWITCH_FALSE);
}
}
- switch_ivr_record_session(session, path, limit, NULL);
+
+ switch_ivr_record_session_event(session, path, limit, NULL, vars);
+ switch_event_safe_destroy(vars);
}
SWITCH_STANDARD_APP(stop_record_session_function)
@@ -5646,7 +5710,7 @@ void *SWITCH_THREAD_FUNC page_thread(switch_thread_t *thread, void *obj)
switch_mutex_unlock(pd->mutex);
}
- switch_event_safe_destroy(&pd->var_event);
+ switch_event_safe_destroy(pd->var_event);
if (pool) {
switch_core_destroy_memory_pool(&pool);
@@ -6460,6 +6524,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load)
SWITCH_ADD_APP(app_interface, "enable_heartbeat", "Enable Media Heartbeat", "Enable Media Heartbeat",
heartbeat_function, HEARTBEAT_SYNTAX, SAF_SUPPORT_NOMEDIA);
+ SWITCH_ADD_APP(app_interface, "filter_codecs", "Filter Codecs", "Filter Codecs", filter_codecs_function, FILTER_CODECS_SYNTAX, SAF_SUPPORT_NOMEDIA);
+
SWITCH_ADD_APP(app_interface, "enable_keepalive", "Enable Keepalive", "Enable Keepalive",
keepalive_function, KEEPALIVE_SYNTAX, SAF_SUPPORT_NOMEDIA);
@@ -6495,6 +6561,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load)
SWITCH_ADD_APP(app_interface, "park_state", "Park State", "Park State", park_state_function, "", SAF_NONE);
SWITCH_ADD_APP(app_interface, "gentones", "Generate Tones", "Generate tones to the channel", gentones_function, "[|]", SAF_NONE);
SWITCH_ADD_APP(app_interface, "playback", "Playback File", "Playback a file to the channel", playback_function, "", SAF_NONE);
+ SWITCH_ADD_APP(app_interface, "broadcast", "Broadcast File", "Broadcast a file to the session", broadcast_function, " ", SAF_NONE);
SWITCH_ADD_APP(app_interface, "endless_playback", "Playback File Endlessly", "Endlessly Playback a file to the channel",
endless_playback_function, "", SAF_NONE);
SWITCH_ADD_APP(app_interface, "loop_playback", "Playback File looply", "Playback a file to the channel looply for limted times",
diff --git a/src/mod/applications/mod_enum/mod_enum.c b/src/mod/applications/mod_enum/mod_enum.c
index 493e2c176a..3e458dd129 100644
--- a/src/mod/applications/mod_enum/mod_enum.c
+++ b/src/mod/applications/mod_enum/mod_enum.c
@@ -833,12 +833,14 @@ SWITCH_STANDARD_API(enum_function)
if (!strcasecmp(dest, "reload")) {
do_load();
stream->write_function(stream, "+OK ENUM Reloaded.\n");
+ switch_safe_free(mydata);
return SWITCH_STATUS_SUCCESS;
}
if (enum_lookup(root, dest, &results, NULL, session) != SWITCH_STATUS_SUCCESS) {
stream->write_function(stream, "No Match!\n");
+ switch_safe_free(mydata);
return SWITCH_STATUS_SUCCESS;
}
diff --git a/src/mod/applications/mod_http_cache/mod_http_cache.c b/src/mod/applications/mod_http_cache/mod_http_cache.c
index dd4b1ef2c8..e3f8d06493 100644
--- a/src/mod/applications/mod_http_cache/mod_http_cache.c
+++ b/src/mod/applications/mod_http_cache/mod_http_cache.c
@@ -416,10 +416,10 @@ static switch_status_t http_put(url_cache_t *cache, http_profile_t *profile, swi
if (!zstr(cache->ssl_cacert)) {
switch_curl_easy_setopt(curl_handle, CURLOPT_CAINFO, cache->ssl_cacert);
}
- /* verify that the host name matches the cert */
- if (!cache->ssl_verifyhost) {
- switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0L);
- }
+ }
+ /* verify that the host name matches the cert */
+ if (!cache->ssl_verifyhost) {
+ switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0L);
}
switch_curl_easy_perform(curl_handle);
switch_curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, httpRes);
@@ -1098,6 +1098,7 @@ static switch_status_t http_get(url_cache_t *cache, http_profile_t *profile, cac
http_get_data_t get_data = {0};
long httpRes = 0;
int start_time_ms = switch_time_now() / 1000;
+ switch_CURLcode curl_status = CURLE_UNKNOWN_OPTION;
/* set up HTTP GET */
get_data.fd = 0;
@@ -1117,6 +1118,7 @@ static switch_status_t http_get(url_cache_t *cache, http_profile_t *profile, cac
if ((get_data.fd = open(get_data.url->filename, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR)) > -1) {
switch_curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1);
switch_curl_easy_setopt(curl_handle, CURLOPT_MAXREDIRS, 10);
+ switch_curl_easy_setopt(curl_handle, CURLOPT_FAILONERROR, 1);
switch_curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1);
if (headers) {
switch_curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers);
@@ -1140,12 +1142,14 @@ static switch_status_t http_get(url_cache_t *cache, http_profile_t *profile, cac
if (!zstr(cache->ssl_cacert)) {
switch_curl_easy_setopt(curl_handle, CURLOPT_CAINFO, cache->ssl_cacert);
}
- /* verify that the host name matches the cert */
- if (!cache->ssl_verifyhost) {
- switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0L);
- }
}
- switch_curl_easy_perform(curl_handle);
+
+ /* verify that the host name matches the cert */
+ if (!cache->ssl_verifyhost) {
+ switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0L);
+ }
+
+ curl_status = switch_curl_easy_perform(curl_handle);
switch_curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &httpRes);
switch_curl_easy_cleanup(curl_handle);
close(get_data.fd);
@@ -1155,7 +1159,7 @@ static switch_status_t http_get(url_cache_t *cache, http_profile_t *profile, cac
goto done;
}
- if (httpRes == 200) {
+ if (curl_status == CURLE_OK) {
int duration_ms = (switch_time_now() / 1000) - start_time_ms;
if (duration_ms > 500) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "URL %s downloaded in %d ms\n", url->url, duration_ms);
@@ -1167,7 +1171,7 @@ static switch_status_t http_get(url_cache_t *cache, http_profile_t *profile, cac
}
} else {
url->size = 0; // nothing downloaded or download interrupted
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Received HTTP error %ld trying to fetch %s\n", httpRes, url->url);
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Received curl error %d HTTP error code %ld trying to fetch %s\n", curl_status, httpRes, url->url);
status = SWITCH_STATUS_GENERR;
goto done;
}
@@ -1729,6 +1733,7 @@ static switch_status_t http_cache_file_open(switch_file_handle_t *handle, const
}
}
+ context->fh.pre_buffer_datalen = handle->pre_buffer_datalen;
if ((status = switch_core_file_open(&context->fh,
context->local_path,
handle->channels,
@@ -1750,6 +1755,7 @@ static switch_status_t http_cache_file_open(switch_file_handle_t *handle, const
handle->interval = context->fh.interval;
handle->channels = context->fh.channels;
handle->flags |= SWITCH_FILE_NOMUX;
+ handle->pre_buffer_datalen = 0;
if (switch_test_flag((&context->fh), SWITCH_FILE_NATIVE)) {
switch_set_flag_locked(handle, SWITCH_FILE_NATIVE);
@@ -1858,6 +1864,17 @@ static switch_status_t http_file_close(switch_file_handle_t *handle)
return status;
}
+static switch_status_t http_cache_file_seek(switch_file_handle_t *handle, unsigned int *cur_sample, int64_t samples, int whence)
+{
+ struct http_context *context = (struct http_context *)handle->private_info;
+
+ if (!handle->seekable) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "File is not seekable\n");
+ return SWITCH_STATUS_NOTIMPL;
+ }
+ return switch_core_file_seek(&context->fh, cur_sample, samples, whence);
+}
+
static char *http_supported_formats[] = { "http", NULL };
static char *https_supported_formats[] = { "https", NULL };
static char *http_cache_supported_formats[] = { "http_cache", NULL };
@@ -1901,6 +1918,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_http_cache_load)
file_interface->file_write = http_file_write;
file_interface->file_read_video = http_file_read_video;
file_interface->file_write_video = http_file_write_video;
+ file_interface->file_seek = http_cache_file_seek;
if (gcache.enable_file_formats) {
file_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_FILE_INTERFACE);
@@ -1912,6 +1930,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_http_cache_load)
file_interface->file_write = http_file_write;
file_interface->file_read_video = http_file_read_video;
file_interface->file_write_video = http_file_write_video;
+ file_interface->file_seek = http_cache_file_seek;
file_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_FILE_INTERFACE);
file_interface->interface_name = modname;
@@ -1922,6 +1941,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_http_cache_load)
file_interface->file_write = http_file_write;
file_interface->file_read_video = http_file_read_video;
file_interface->file_write_video = http_file_write_video;
+ file_interface->file_seek = http_cache_file_seek;
}
/* create the queue from configuration */
diff --git a/src/mod/applications/mod_spandsp/mod_spandsp.h b/src/mod/applications/mod_spandsp/mod_spandsp.h
index 4e8f1d2427..7ffd334ef3 100644
--- a/src/mod/applications/mod_spandsp/mod_spandsp.h
+++ b/src/mod/applications/mod_spandsp/mod_spandsp.h
@@ -110,7 +110,7 @@ typedef enum {
* TONE DETECTION WITH CADENCE
*/
-#define MAX_TONES 32
+#define MAX_TONES 128
#define STRLEN 128
/**
* Tone descriptor
diff --git a/src/mod/applications/mod_spandsp/mod_spandsp_fax.c b/src/mod/applications/mod_spandsp/mod_spandsp_fax.c
index a78b63e5b1..b75ac89423 100644
--- a/src/mod/applications/mod_spandsp/mod_spandsp_fax.c
+++ b/src/mod/applications/mod_spandsp/mod_spandsp_fax.c
@@ -59,6 +59,25 @@ typedef enum {
T38_MODE_REFUSED = -1,
} t38_mode_t;
+const char * get_t38_status(t38_mode_t mode)
+{
+ const char *str = "off";
+ switch(mode) {
+ case T38_MODE_NEGOTIATED:
+ str = "negotiated";
+ break;
+ case T38_MODE_REQUESTED:
+ str = "requested";
+ break;
+ case T38_MODE_REFUSED:
+ str = "refused";
+ break;
+ default:
+ break;
+ }
+ return str;
+}
+
struct pvt_s {
switch_core_session_t *session;
@@ -316,6 +335,7 @@ static int phase_b_handler(void *user_data, int result)
}
switch_channel_set_variable(channel, "fax_ecm_used", (t30_stats.error_correcting_mode) ? "on" : "off");
+ switch_channel_set_variable(channel, "fax_t38_status", get_t38_status(pvt->t38_mode));
switch_channel_set_variable(channel, "fax_local_station_id", local_ident);
switch_channel_set_variable(channel, "fax_remote_station_id", far_ident);
switch_channel_set_variable(channel, "fax_remote_country", switch_str_nil(t30_get_rx_country(pvt->t30)));
@@ -328,9 +348,10 @@ static int phase_b_handler(void *user_data, int result)
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Local station id: %s\n", local_ident);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Transfer Rate: %i\n", t30_stats.bit_rate);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "ECM status %s\n", (t30_stats.error_correcting_mode) ? "on" : "off");
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "remote country: %s\n", switch_str_nil(t30_get_rx_country(pvt->t30)));
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "remote vendor: %s\n", switch_str_nil(t30_get_rx_vendor(pvt->t30)));
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "remote model: %s\n", switch_str_nil(t30_get_rx_model(pvt->t30)));
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "T38 status %s\n", get_t38_status(pvt->t38_mode));
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "remote country: %s\n", switch_str_nil(t30_get_rx_country(pvt->t30)));
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "remote vendor: %s\n", switch_str_nil(t30_get_rx_vendor(pvt->t30)));
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "remote model: %s\n", switch_str_nil(t30_get_rx_model(pvt->t30)));
if (pvt->app_mode == FUNCTION_TX) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Total fax pages: %s\n", fax_document_total_pages);
}
@@ -347,6 +368,7 @@ static int phase_b_handler(void *user_data, int result)
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "uuid", switch_core_session_get_uuid(session));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-transfer-rate", fax_transfer_rate);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-ecm-used", (t30_stats.error_correcting_mode) ? "on" : "off");
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-t38-status", get_t38_status(pvt->t38_mode));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-local-station-id", local_ident);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-remote-station-id", far_ident);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-remote-country", switch_str_nil(t30_get_rx_country(pvt->t30)));
@@ -546,9 +568,10 @@ static void phase_e_handler(void *user_data, int result)
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Transfer Rate: %i\n", t.bit_rate);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "ECM status %s\n", (t.error_correcting_mode) ? "on" : "off");
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "remote country: %s\n", switch_str_nil(t30_get_rx_country(pvt->t30)));
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "remote vendor: %s\n", switch_str_nil(t30_get_rx_vendor(pvt->t30)));
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "remote model: %s\n", switch_str_nil(t30_get_rx_model(pvt->t30)));
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "T38 status %s\n", get_t38_status(pvt->t38_mode));
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "remote country: %s\n", switch_str_nil(t30_get_rx_country(pvt->t30)));
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "remote vendor: %s\n", switch_str_nil(t30_get_rx_vendor(pvt->t30)));
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "remote model: %s\n", switch_str_nil(t30_get_rx_model(pvt->t30)));
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "==============================================================================\n");
@@ -564,6 +587,7 @@ static void phase_e_handler(void *user_data, int result)
switch_channel_set_variable(channel, "fax_result_text", t30_completion_code_to_str(result));
switch_channel_set_variable(channel, "fax_ecm_used", (t.error_correcting_mode) ? "on" : "off");
+ switch_channel_set_variable(channel, "fax_t38_status", get_t38_status(pvt->t38_mode));
switch_channel_set_variable(channel, "fax_local_station_id", local_ident);
switch_channel_set_variable(channel, "fax_remote_station_id", far_ident);
@@ -616,6 +640,7 @@ static void phase_e_handler(void *user_data, int result)
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-bad-rows", fax_bad_rows);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-transfer-rate", fax_transfer_rate);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-ecm-used", (t.error_correcting_mode) ? "on" : "off");
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-t38-status", get_t38_status(pvt->t38_mode));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-local-station-id", local_ident);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-remote-station-id", far_ident);
switch_event_fire(&event);
diff --git a/src/mod/codecs/mod_com_g729/Makefile.am b/src/mod/codecs/mod_com_g729/Makefile.am
index 8af9c4d795..128a9f9628 100644
--- a/src/mod/codecs/mod_com_g729/Makefile.am
+++ b/src/mod/codecs/mod_com_g729/Makefile.am
@@ -1,13 +1,13 @@
include $(top_srcdir)/build/modmake.rulesam
MODNAME=mod_com_g729
-VERSION=201506221434
+VERSION=latest
if ISLINUX
G729INSTALLER = $(top_srcdir)/libs/fs-$(VERSION)-installer
-LICSERVER=/usr/sbin/freeswitch_licence_server
-VALIDATOR=$(bindir)/validator
+LICSERVER=/usr/sbin/freeswitch-license-server
+VALIDATOR=$(bindir)/freeswitch-license-validator
MOD=$(moddir)/mod_com_g729.so
BUILT_SOURCES = $(G729INSTALLER)
diff --git a/src/mod/endpoints/mod_loopback/mod_loopback.c b/src/mod/endpoints/mod_loopback/mod_loopback.c
index 202dfa186b..cf52370aa8 100644
--- a/src/mod/endpoints/mod_loopback/mod_loopback.c
+++ b/src/mod/endpoints/mod_loopback/mod_loopback.c
@@ -94,7 +94,14 @@ typedef struct loopback_private_object loopback_private_t;
static struct {
int debug;
-} globals;
+ int early_set_loopback_id;
+ int fire_bowout_event_bridge;
+ int ignore_channel_ready;
+ switch_call_cause_t bowout_hangup_cause;
+ int bowout_controlled_hangup;
+ int bowout_transfer_recordings;
+ int bowout_disable_on_inner_bridge;
+} loopback_globals;
static switch_status_t channel_on_init(switch_core_session_t *session);
static switch_status_t channel_on_hangup(switch_core_session_t *session);
@@ -263,6 +270,10 @@ static switch_status_t channel_on_init(switch_core_session_t *session)
switch_snprintf(name, sizeof(name), "loopback/%s-b", tech_pvt->caller_profile->destination_number);
switch_channel_set_name(b_channel, name);
+ if (loopback_globals.early_set_loopback_id) {
+ switch_channel_set_variable(channel, "loopback_leg", "B");
+ switch_channel_set_variable(channel, "is_loopback", "1");
+ }
if (tech_init(b_tech_pvt, b_session, switch_core_session_get_read_codec(session)) != SWITCH_STATUS_SUCCESS) {
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
switch_core_session_destroy(&b_session);
@@ -320,7 +331,7 @@ static switch_status_t channel_on_init(switch_core_session_t *session)
if (!zstr(argv[i])) {
const char *val = switch_channel_get_variable(channel, argv[i]);
- if(!zstr(val)) {
+ if (!zstr(val)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Transfer variable [%s]=[%s] %s -> %s\n",
argv[i], val, switch_channel_get_name(channel), switch_channel_get_name(tech_pvt->other_channel));
@@ -338,6 +349,8 @@ static switch_status_t channel_on_init(switch_core_session_t *session)
switch_channel_set_variable(channel, "other_loopback_leg_uuid", switch_channel_get_uuid(b_channel));
switch_channel_set_variable(b_channel, "other_loopback_leg_uuid", switch_channel_get_uuid(channel));
+ switch_channel_set_variable(b_channel, "other_loopback_from_uuid", switch_channel_get_variable(channel, "loopback_from_uuid"));
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(b_session), SWITCH_LOG_DEBUG, "setting other_loopback_from_uuid on b leg to %s\n", switch_channel_get_variable(channel, "loopback_from_uuid"));
if (switch_core_session_thread_launch(b_session) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Error spawning thread\n");
@@ -474,6 +487,7 @@ static switch_status_t channel_on_execute(switch_core_session_t *session)
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, "loopback::bowout") == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Resigning-UUID", switch_channel_get_uuid(channel));
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Resigning-Peer-UUID", switch_channel_get_uuid(tech_pvt->other_channel));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Acquired-UUID", switch_channel_get_uuid(other_channel));
switch_event_fire(&event);
}
@@ -485,12 +499,14 @@ static switch_status_t channel_on_execute(switch_core_session_t *session)
switch_channel_set_caller_profile(other_channel, clone);
}
+ switch_channel_set_variable(channel, "loopback_hangup_cause", "bowout");
+ switch_channel_set_variable(tech_pvt->channel, "loopback_bowout_other_uuid", switch_channel_get_uuid(other_channel));
switch_channel_caller_extension_masquerade(channel, other_channel, 0);
switch_channel_set_state(other_channel, CS_RESET);
switch_channel_wait_for_state(other_channel, NULL, CS_RESET);
switch_channel_set_state(other_channel, CS_EXECUTE);
switch_core_session_rwunlock(other_session);
- switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_UNSPECIFIED);
+ switch_channel_hangup(channel, loopback_globals.bowout_hangup_cause);
}
}
@@ -588,6 +604,7 @@ static switch_status_t channel_kill_channel(switch_core_session_t *session, int
case SWITCH_SIG_BREAK:
break;
case SWITCH_SIG_KILL:
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s CHANNEL KILL\n", switch_channel_get_name(channel));
switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
switch_clear_flag_locked(tech_pvt, TFLAG_LINKED);
switch_mutex_lock(tech_pvt->mutex);
@@ -600,8 +617,6 @@ static switch_status_t channel_kill_channel(switch_core_session_t *session, int
break;
}
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s CHANNEL KILL\n", switch_channel_get_name(channel));
-
return SWITCH_STATUS_SUCCESS;
}
@@ -700,7 +715,12 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch
*frame = NULL;
if (!switch_channel_ready(channel)) {
- goto end;
+ if (loopback_globals.ignore_channel_ready) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "CHANNEL NOT READY - IGNORED\n");
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "CHANNEL NOT READY\n");
+ goto end;
+ }
}
switch_core_timer_next(&tech_pvt->timer);
@@ -840,6 +860,7 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc
tech_pvt->other_tech_pvt &&
switch_test_flag(tech_pvt, TFLAG_BRIDGE) &&
!switch_test_flag(tech_pvt, TFLAG_BLEG) &&
+ (!loopback_globals.bowout_disable_on_inner_bridge || !switch_channel_test_flag(tech_pvt->channel, CF_INNER_BRIDGE)) &&
switch_test_flag(tech_pvt->other_tech_pvt, TFLAG_BRIDGE) &&
switch_channel_test_flag(tech_pvt->channel, CF_BRIDGED) &&
switch_channel_test_flag(tech_pvt->other_channel, CF_BRIDGED) &&
@@ -889,8 +910,47 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
"%s detected bridge on both ends, attempting direct connection.\n", switch_channel_get_name(channel));
+ if (loopback_globals.bowout_transfer_recordings) {
+ switch_ivr_transfer_recordings(session, br_a);
+ switch_ivr_transfer_recordings(tech_pvt->other_session, br_b);
+ }
+
+ if (loopback_globals.fire_bowout_event_bridge) {
+ switch_event_t *event = NULL;
+ if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, "loopback::direct") == SWITCH_STATUS_SUCCESS) {
+ switch_channel_event_set_data(tech_pvt->channel, event);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Resigning-UUID", switch_channel_get_uuid(tech_pvt->channel));
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Resigning-Peer-UUID", switch_channel_get_uuid(tech_pvt->other_channel));
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Connecting-Leg-A-UUID", switch_channel_get_uuid(ch_a));
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Connecting-Leg-B-UUID", switch_channel_get_uuid(ch_b));
+ switch_event_fire(&event);
+ }
+
+ if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, "loopback::direct") == SWITCH_STATUS_SUCCESS) {
+ switch_channel_event_set_data(tech_pvt->other_channel, event);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Resigning-UUID", switch_channel_get_uuid(tech_pvt->other_channel));
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Resigning-Peer-UUID", switch_channel_get_uuid(tech_pvt->channel));
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Connecting-Leg-A-UUID", switch_channel_get_uuid(ch_b));
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Connecting-Leg-B-UUID", switch_channel_get_uuid(ch_a));
+ switch_event_fire(&event);
+ }
+ }
+
/* channel_masquerade eat your heart out....... */
switch_ivr_uuid_bridge(a_uuid, b_uuid);
+
+ switch_channel_set_variable(tech_pvt->channel, "loopback_hangup_cause", "bridge");
+ switch_channel_set_variable(tech_pvt->channel, "loopback_bowout_other_uuid", switch_channel_get_uuid(ch_a));
+ switch_channel_set_variable(tech_pvt->other_channel, "loopback_hangup_cause", "bridge");
+ switch_channel_set_variable(tech_pvt->other_channel, "loopback_bowout_other_uuid", switch_channel_get_uuid(ch_b));
+
+ if (loopback_globals.bowout_controlled_hangup) {
+ switch_channel_set_flag(tech_pvt->channel, CF_INTERCEPTED);
+ switch_channel_set_flag(tech_pvt->other_channel, CF_INTERCEPTED);
+ switch_channel_hangup(tech_pvt->channel, loopback_globals.bowout_hangup_cause);
+ switch_channel_hangup(tech_pvt->other_channel, loopback_globals.bowout_hangup_cause);
+ }
+
good_to_go = 1;
switch_mutex_unlock(tech_pvt->mutex);
}
@@ -971,6 +1031,18 @@ static switch_status_t channel_receive_message(switch_core_session_t *session, s
case SWITCH_MESSAGE_INDICATE_BRIDGE:
{
switch_set_flag_locked(tech_pvt, TFLAG_BRIDGE);
+ if (switch_test_flag(tech_pvt, TFLAG_BLEG)) {
+ if (msg->string_arg) {
+ switch_core_session_t *bridged_session;
+ switch_channel_t *bridged_channel;
+ if ((bridged_session = switch_core_session_force_locate(msg->string_arg)) != NULL) {
+ bridged_channel = switch_core_session_get_channel(bridged_session);
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(bridged_session), SWITCH_LOG_DEBUG, "setting other_leg_true_id to %s\n", switch_channel_get_variable(channel, "other_loopback_from_uuid"));
+ switch_channel_set_variable(bridged_channel, "other_leg_true_id", switch_channel_get_variable(channel, "other_loopback_from_uuid"));
+ switch_core_session_rwunlock(bridged_session);
+ }
+ }
+ }
}
break;
case SWITCH_MESSAGE_INDICATE_UNBRIDGE:
@@ -1092,6 +1164,10 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
channel = switch_core_session_get_channel(*new_session);
switch_snprintf(name, sizeof(name), "loopback/%s-a", outbound_profile->destination_number);
switch_channel_set_name(channel, name);
+ if (loopback_globals.early_set_loopback_id) {
+ switch_channel_set_variable(channel, "loopback_leg", "A");
+ switch_channel_set_variable(channel, "is_loopback", "1");
+ }
if (tech_init(tech_pvt, *new_session, session ? switch_core_session_get_read_codec(session) : NULL) != SWITCH_STATUS_SUCCESS) {
switch_core_session_destroy(new_session);
return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
@@ -1106,6 +1182,11 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
switch_channel_set_private(channel, "__loopback_vars__", clone);
}
+ if (ochannel) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(*new_session), SWITCH_LOG_DEBUG, "setting loopback_from_uuid to %s\n", switch_channel_get_uuid(ochannel));
+ switch_channel_set_variable(channel, "loopback_from_uuid", switch_channel_get_uuid(ochannel));
+ }
+
if (outbound_profile) {
char *dialplan = NULL, *context = NULL;
@@ -1566,6 +1647,62 @@ static switch_io_routines_t null_channel_io_routines = {
/*.receive_message */ null_channel_receive_message
};
+switch_status_t load_loopback_configuration(switch_bool_t reload)
+{
+ switch_xml_t xml = NULL, x_lists = NULL, x_list = NULL, cfg = NULL;
+ switch_status_t status = SWITCH_STATUS_FALSE;
+
+ memset(&loopback_globals, 0, sizeof(loopback_globals));
+
+ loopback_globals.bowout_hangup_cause = SWITCH_CAUSE_NORMAL_UNSPECIFIED;
+
+ if ((xml = switch_xml_open_cfg("loopback.conf", &cfg, NULL))) {
+ status = SWITCH_STATUS_SUCCESS;
+
+ if ((x_lists = switch_xml_child(cfg, "settings"))) {
+ for (x_list = switch_xml_child(x_lists, "param"); x_list; x_list = x_list->next) {
+ const char *name = switch_xml_attr(x_list, "name");
+ const char *value = switch_xml_attr(x_list, "value");
+
+ if (zstr(name)) {
+ continue;
+ }
+
+ if (zstr(value)) {
+ continue;
+ }
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s = %s\n", name, value);
+
+ if (!strcmp(name, "early-set-loopback-id")) {
+ loopback_globals.early_set_loopback_id = switch_true(value);
+ } else if (!strcmp(name, "fire-bowout-on-bridge")) {
+ loopback_globals.fire_bowout_event_bridge = switch_true(value);
+ } else if (!strcmp(name, "ignore-channel-ready")) {
+ loopback_globals.ignore_channel_ready = switch_true(value);
+ } else if (!strcmp(name, "bowout-hangup-cause")) {
+ loopback_globals.bowout_hangup_cause = switch_channel_str2cause(value);
+ } else if (!strcmp(name, "bowout-controlled-hangup")) {
+ loopback_globals.bowout_controlled_hangup = switch_true(value);
+ } else if (!strcmp(name, "bowout-transfer-recording")) {
+ loopback_globals.bowout_transfer_recordings = switch_true(value);
+ } else if (!strcmp(name, "bowout-disable-on-inner-bridge")) {
+ loopback_globals.bowout_disable_on_inner_bridge = switch_true(value);
+ }
+
+ }
+ }
+
+ switch_xml_free(xml);
+ }
+
+ return status;
+}
+
+static void loopback_reload_xml_event_handler(switch_event_t *event)
+{
+ load_loopback_configuration(1);
+}
SWITCH_MODULE_LOAD_FUNCTION(mod_loopback_load)
{
@@ -1576,8 +1713,12 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_loopback_load)
return SWITCH_STATUS_TERM;
}
+ if (switch_event_reserve_subclass("loopback::direct") != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", "loopback::direct");
+ return SWITCH_STATUS_TERM;
+ }
- memset(&globals, 0, sizeof(globals));
+ load_loopback_configuration(0);
/* connect my internal structure to the blank pointer passed to me */
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
@@ -1593,6 +1734,11 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_loopback_load)
SWITCH_ADD_APP(app_interface, "unloop", "Tell loopback to unfold", "Tell loopback to unfold", unloop_function, "", SAF_NO_LOOPBACK);
+ if ((switch_event_bind(modname, SWITCH_EVENT_RELOADXML, NULL, loopback_reload_xml_event_handler, NULL) != SWITCH_STATUS_SUCCESS)) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind our reloadxml handler!\n");
+ /* Not such severe to prevent loading */
+ }
+
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS;
}
@@ -1601,6 +1747,8 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_loopback_shutdown)
{
switch_event_free_subclass("loopback::bowout");
+ switch_event_free_subclass("loopback::direct");
+ switch_event_unbind_callback(loopback_reload_xml_event_handler);
return SWITCH_STATUS_SUCCESS;
}
diff --git a/src/mod/endpoints/mod_sofia/Makefile.am b/src/mod/endpoints/mod_sofia/Makefile.am
index 9d98a976a3..3adcb8ccea 100644
--- a/src/mod/endpoints/mod_sofia/Makefile.am
+++ b/src/mod/endpoints/mod_sofia/Makefile.am
@@ -9,7 +9,7 @@ SOFIAUA_BUILDDIR=$(SOFIA_BUILDDIR)/libsofia-sip-ua
SOFIALA=$(SOFIAUA_BUILDDIR)/libsofia-sip-ua.la
mod_LTLIBRARIES = mod_sofia.la
-mod_sofia_la_SOURCES = mod_sofia.c sofia.c sofia_glue.c sofia_presence.c sofia_reg.c sofia_media.c sip-dig.c rtp.c mod_sofia.h
+mod_sofia_la_SOURCES = mod_sofia.c sofia.c sofia_json_api.c sofia_glue.c sofia_presence.c sofia_reg.c sofia_media.c sip-dig.c rtp.c mod_sofia.h
mod_sofia_la_CFLAGS = $(AM_CFLAGS) -I. $(SOFIA_CMD_LINE_CFLAGS)
mod_sofia_la_CFLAGS += -I$(SOFIAUA_DIR)/bnf -I$(SOFIAUA_BUILDDIR)/bnf
mod_sofia_la_CFLAGS += -I$(SOFIAUA_DIR)/http -I$(SOFIAUA_BUILDDIR)/http
diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.2017.vcxproj b/src/mod/endpoints/mod_sofia/mod_sofia.2017.vcxproj
index 442a50e830..e90e806c9d 100644
--- a/src/mod/endpoints/mod_sofia/mod_sofia.2017.vcxproj
+++ b/src/mod/endpoints/mod_sofia/mod_sofia.2017.vcxproj
@@ -167,6 +167,7 @@
+
diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c
index d4e6bb2285..c2900cf515 100644
--- a/src/mod/endpoints/mod_sofia/mod_sofia.c
+++ b/src/mod/endpoints/mod_sofia/mod_sofia.c
@@ -340,6 +340,17 @@ static int hangup_cause_to_sip(switch_call_cause_t cause)
return 487;
case SWITCH_CAUSE_EXCHANGE_ROUTING_ERROR:
return 483;
+ /* Custom mappings not part of RFC */
+ case SWITCH_CAUSE_BUSY_EVERYWHERE:
+ return 600;
+ case SWITCH_CAUSE_DECLINE:
+ return 603;
+ case SWITCH_CAUSE_DOES_NOT_EXIST_ANYWHERE:
+ return 604;
+ case SWITCH_CAUSE_NOT_ACCEPTABLE:
+ return 606;
+ case SWITCH_CAUSE_UNWANTED:
+ return 607;
default:
return 480;
}
@@ -502,7 +513,7 @@ switch_status_t sofia_on_hangup(switch_core_session_t *session)
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Sending BYE to %s\n", switch_channel_get_name(channel));
if (!sofia_test_flag(tech_pvt, TFLAG_BYE)) {
nua_bye(tech_pvt->nh,
- TAG_IF(tech_pvt->record_route, NUTAG_PROXY(tech_pvt->record_route)),
+ TAG_IF(!zstr(tech_pvt->route_uri), NUTAG_PROXY(tech_pvt->route_uri)),
SIPTAG_CONTACT(SIP_NONE),
TAG_IF(!zstr(reason), SIPTAG_REASON_STR(reason)),
TAG_IF(call_info, SIPTAG_CALL_INFO_STR(call_info)),
@@ -2172,7 +2183,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
break;
case SWITCH_MESSAGE_INDICATE_RESPOND:
{
-
+ printf("WHAT THE FUCKING HELL? %d\n", switch_channel_test_flag(tech_pvt->channel, CF_AWAITING_STREAM_CHANGE));
if (switch_channel_test_flag(tech_pvt->channel, CF_AWAITING_STREAM_CHANGE)) {
switch_channel_clear_flag(tech_pvt->channel, CF_AWAITING_STREAM_CHANGE);
@@ -2627,7 +2638,7 @@ static switch_status_t sofia_receive_event(switch_core_session_t *session, switc
typedef switch_status_t (*sofia_command_t) (char **argv, int argc, switch_stream_handle_t *stream);
-static const char *sofia_state_names[] = {
+const char *sofia_state_names[] = {
"UNREGED",
"TRYING",
"REGISTER",
@@ -2755,7 +2766,7 @@ static int sql2str_callback(void *pArg, int argc, char **argv, char **columnName
return 0;
}
-static uint32_t sofia_profile_reg_count(sofia_profile_t *profile)
+uint32_t sofia_profile_reg_count(sofia_profile_t *profile)
{
struct cb_helper_sql2str cb;
char reg_count[80] = "";
@@ -4363,6 +4374,8 @@ SWITCH_STANDARD_API(sofia_function)
func = cmd_status;
} else if (!strcasecmp(argv[0], "xmlstatus")) {
func = cmd_xml_status;
+ } else if (!strcasecmp(argv[0], "jsonstatus")) {
+ func = cmd_json_status;
} else if (!strcasecmp(argv[0], "filter")) {
if (argc > 1) {
if (!strcasecmp(argv[1],"off")) {
@@ -6265,6 +6278,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sofia_load)
management_interface->relative_oid = "1001";
management_interface->management_function = sofia_manage;
+ add_sofia_json_apis(module_interface);
+
SWITCH_ADD_APP(app_interface, "sofia_sla", "private sofia sla function",
"private sofia sla function", sofia_sla_function, "", SAF_NONE);
diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h
index cdb311f35a..de44aac283 100644
--- a/src/mod/endpoints/mod_sofia/mod_sofia.h
+++ b/src/mod/endpoints/mod_sofia/mod_sofia.h
@@ -303,12 +303,16 @@ typedef enum {
PFLAG_MAKE_EVERY_TRANSFER_A_NIGHTMARE,
PFLAG_FIRE_TRANFER_EVENTS,
PFLAG_BLIND_AUTH_ENFORCE_RESULT,
+ PFLAG_BLIND_AUTH_REPLY_403,
PFLAG_PROXY_HOLD,
PFLAG_PROXY_INFO,
PFLAG_PROXY_MESSAGE,
PFLAG_FIRE_BYE_RESPONSE_EVENTS,
PFLAG_AUTO_INVITE_100,
PFLAG_UPDATE_REFRESHER,
+ PFLAG_AUTH_REQUIRE_USER,
+ PFLAG_AUTH_CALLS_ACL_ONLY,
+ PFLAG_USE_PORT_FOR_ACL_CHECK,
/* No new flags below this line */
PFLAG_MAX
@@ -786,6 +790,8 @@ struct sofia_profile {
int bind_attempt_interval;
char *proxy_notify_events;
char *proxy_info_content_types;
+ char *acl_inbound_x_token_header;
+ char *acl_proxy_x_token_header;
};
@@ -964,6 +970,7 @@ void sofia_handle_sip_i_info(nua_t *nua, sofia_profile_t *profile, nua_handle_t
switch_status_t sofia_proxy_sip_i_message(nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, switch_core_session_t *session, sip_t const *sip,
sofia_dispatch_event_t *de, tagi_t tags[]);
void sofia_handle_sip_i_invite(switch_core_session_t *session, nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip, sofia_dispatch_event_t *de, tagi_t tags[]);
+void sofia_handle_sip_i_invite_replaces(switch_core_session_t *session, switch_channel_t *channel, switch_channel_t *b_channel, char* uuid, private_object_t *tech_pvt, sip_call_info_t *call_info, sofia_profile_t *profile, char *is_nat, sip_t const *sip);
void sofia_reg_handle_sip_i_register(nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t **sofia_private, sip_t const *sip,
@@ -1163,6 +1170,11 @@ void sofia_glue_restart_all_profiles(void);
const char *sofia_state_string(int state);
void sofia_wait_for_reply(struct private_object *tech_pvt, nua_event_t event, uint32_t timeout);
+/* sofia api */
+switch_status_t cmd_json_status(char **argv, int argc, switch_stream_handle_t *stream);
+uint32_t sofia_profile_reg_count(sofia_profile_t *profile);
+void add_sofia_json_apis(switch_loadable_module_interface_t **module_interface);
+
/*
* Logging control functions
*/
diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c
index 4a5f64fa51..d1e32a096f 100644
--- a/src/mod/endpoints/mod_sofia/sofia.c
+++ b/src/mod/endpoints/mod_sofia/sofia.c
@@ -4591,6 +4591,10 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
sofia_clear_pflag(profile, PFLAG_MAKE_EVERY_TRANSFER_A_NIGHTMARE);
sofia_clear_pflag(profile, PFLAG_FIRE_TRANFER_EVENTS);
sofia_clear_pflag(profile, PFLAG_BLIND_AUTH_ENFORCE_RESULT);
+ sofia_clear_pflag(profile, PFLAG_BLIND_AUTH_REPLY_403);
+ sofia_clear_pflag(profile, PFLAG_AUTH_REQUIRE_USER);
+ sofia_clear_pflag(profile, PFLAG_AUTH_CALLS_ACL_ONLY);
+ sofia_clear_pflag(profile, PFLAG_USE_PORT_FOR_ACL_CHECK);
profile->shutdown_type = "false";
profile->local_network = "localnet.auto";
sofia_set_flag(profile, TFLAG_ENABLE_SOA);
@@ -5486,6 +5490,12 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
profile->nonce_ttl = atoi(val);
} else if (!strcasecmp(var, "max-auth-validity") && !zstr(val)) {
profile->max_auth_validity = atoi(val);
+ } else if (!strcasecmp(var, "auth-require-user")) {
+ if (switch_true(val)) {
+ sofia_set_pflag(profile, PFLAG_AUTH_REQUIRE_USER);
+ } else {
+ sofia_clear_pflag(profile, PFLAG_AUTH_REQUIRE_USER);
+ }
} else if (!strcasecmp(var, "accept-blind-reg")) {
if (switch_true(val)) {
sofia_set_pflag(profile, PFLAG_BLIND_REG);
@@ -5901,6 +5911,28 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
} else {
sofia_clear_pflag(profile, PFLAG_BLIND_AUTH_ENFORCE_RESULT);
}
+ } else if (!strcasecmp(var, "blind-auth-reply-403")) {
+ if(switch_true(val)) {
+ sofia_set_pflag(profile, PFLAG_BLIND_AUTH_REPLY_403);
+ } else {
+ sofia_clear_pflag(profile, PFLAG_BLIND_AUTH_REPLY_403);
+ }
+ } else if (!strcasecmp(var, "auth-calls-acl-only")) {
+ if(switch_true(val)) {
+ sofia_set_pflag(profile, PFLAG_AUTH_CALLS_ACL_ONLY);
+ } else {
+ sofia_clear_pflag(profile, PFLAG_AUTH_CALLS_ACL_ONLY);
+ }
+ } else if (!strcasecmp(var, "use-port-for-acl-check")) {
+ if(switch_true(val)) {
+ sofia_set_pflag(profile, PFLAG_USE_PORT_FOR_ACL_CHECK);
+ } else {
+ sofia_clear_pflag(profile, PFLAG_USE_PORT_FOR_ACL_CHECK);
+ }
+ } else if (!strcasecmp(var, "apply-inbound-acl-x-token")) {
+ profile->acl_inbound_x_token_header = switch_core_strdup(profile->pool, val);
+ } else if (!strcasecmp(var, "apply-proxy-acl-x-token")) {
+ profile->acl_proxy_x_token_header = switch_core_strdup(profile->pool, val);
} else if (!strcasecmp(var, "proxy-hold")) {
if(switch_true(val)) {
sofia_set_pflag(profile, PFLAG_PROXY_HOLD);
@@ -9992,6 +10024,46 @@ void sofia_handle_sip_i_reinvite(switch_core_session_t *session,
}
+switch_status_t sofia_locate_user(char* user, switch_core_session_t *session, sip_t const *sip, switch_xml_t* x_user)
+{
+ char *username, *domain;
+ switch_event_t *v_event = NULL;
+ switch_status_t result = SWITCH_STATUS_FALSE;
+
+ if (!session) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+ if (zstr(user)) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+ if (!(username = switch_core_session_strdup(session, user))) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+ if (!(domain = strchr(username, '@'))) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+ *domain++ = '\0';
+
+ if (switch_event_create(&v_event, SWITCH_EVENT_REQUEST_PARAMS) == SWITCH_STATUS_SUCCESS) {
+ sip_unknown_t *un;
+ for (un = sip->sip_unknown; un; un = un->un_next) {
+ switch_event_add_header_string(v_event, SWITCH_STACK_BOTTOM, un->un_name, un->un_value);
+ };
+ }
+
+ result = switch_xml_locate_user_merged("id", username, domain, NULL, x_user, v_event);
+
+ if (v_event) {
+ switch_event_destroy(&v_event);
+ }
+
+ return result;
+}
+
void sofia_handle_sip_i_invite(switch_core_session_t *session, nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip, sofia_dispatch_event_t *de, tagi_t tags[])
{
char key[128] = "";
@@ -10181,14 +10253,23 @@ void sofia_handle_sip_i_invite(switch_core_session_t *session, nua_t *nua, sofia
int ok = 1;
char *last_acl = NULL;
const char *token = NULL;
+ int acl_port = sofia_test_pflag(profile, PFLAG_USE_PORT_FOR_ACL_CHECK) ? network_port : 0;
for (x = 0; x < profile->acl_count; x++) {
last_acl = profile->acl[x];
- if ((ok = switch_check_network_list_ip_token(network_ip, last_acl, &token))) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "verifying acl \"%s\" for ip/port %s:%i.\n",
+ switch_str_nil(last_acl), network_ip, acl_port);
+ if ((ok = switch_check_network_list_ip_port_token(network_ip, acl_port, last_acl, &token))) {
if (profile->acl_pass_context[x]) {
acl_context = profile->acl_pass_context[x];
}
+ if(!token && profile->acl_inbound_x_token_header) {
+ const char * x_auth_token = sofia_glue_get_unknown_header(sip, profile->acl_inbound_x_token_header);
+ if (!zstr(x_auth_token)) {
+ token = x_auth_token;
+ }
+ }
break;
}
@@ -10213,75 +10294,105 @@ void sofia_handle_sip_i_invite(switch_core_session_t *session, nua_t *nua, sofia
}
} else {
int network_ip_is_proxy = 0;
+ const char* x_auth_ip = network_ip;
/* Check if network_ip is a proxy allowed to send us calls */
if (profile->proxy_acl_count) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%d acls to check for proxy\n", profile->proxy_acl_count);
- }
-
- for (x = 0; x < profile->proxy_acl_count; x++) {
- last_acl = profile->proxy_acl[x];
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "checking %s against acl %s\n", network_ip, last_acl);
- if (switch_check_network_list_ip_token(network_ip, last_acl, &token)) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s is a proxy according to the %s acl\n", network_ip, last_acl);
- network_ip_is_proxy = 1;
- break;
+ for (x = 0; x < profile->proxy_acl_count; x++) {
+ last_acl = profile->proxy_acl[x];
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "checking %s against acl %s\n", network_ip, last_acl);
+ if (switch_check_network_list_ip_port_token(network_ip, network_port, last_acl, &token)) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s is a proxy according to the %s acl\n", network_ip, last_acl);
+ network_ip_is_proxy = 1;
+ break;
+ }
}
}
+
/*
* if network_ip is a proxy allowed to send calls, check for auth
* ip header and see if it matches against the inbound acl
*/
if (network_ip_is_proxy) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "network ip is a proxy\n");
+ const char * x_auth_port = sofia_glue_get_unknown_header(sip, "X-AUTH-PORT");
+ int x_auth_port_i = sofia_test_pflag(profile, PFLAG_USE_PORT_FOR_ACL_CHECK) ? zstr(x_auth_port) ? 0 : atoi(x_auth_port) : 0;
- for (un = sip->sip_unknown; un; un = un->un_next) {
- if (!strcasecmp(un->un_name, "X-AUTH-IP")) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "found auth ip [%s] header of [%s]\n", un->un_name, un->un_value);
- if (!zstr(un->un_value)) {
- for (x = 0; x < profile->acl_count; x++) {
- last_acl = profile->acl[x];
- if ((ok = switch_check_network_list_ip_token(un->un_value, last_acl, &token))) {
- switch_copy_string(proxied_client_ip, un->un_value, sizeof(proxied_client_ip));
- break;
- }
+ /*
+ * if network_ip is a proxy allowed to send calls,
+ * authorize call if proxy provided matched token header
+ */
+ if (profile->acl_proxy_x_token_header) {
+ const char * x_auth_token = sofia_glue_get_unknown_header(sip, profile->acl_proxy_x_token_header);
+ if (!zstr(x_auth_token)) {
+ token = x_auth_token;
+ switch_copy_string(proxied_client_ip, x_auth_ip, sizeof(proxied_client_ip));
+ ok = 1;
+ }
+ }
+
+ if (!ok && (x_auth_ip = sofia_glue_get_unknown_header(sip, "X-AUTH-IP")) && !zstr(x_auth_ip)) {
+ for (x = 0; x < profile->acl_count; x++) {
+ last_acl = profile->acl[x];
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "verifying acl \"%s\" from proxy for ip/port %s:%i.\n",
+ switch_str_nil(last_acl), x_auth_ip, x_auth_port_i);
+ if ((ok = switch_check_network_list_ip_port_token(x_auth_ip, x_auth_port_i, last_acl, &token))) {
+
+ switch_copy_string(proxied_client_ip, x_auth_ip, sizeof(proxied_client_ip));
+
+ if (profile->acl_pass_context[x]) {
+ acl_context = profile->acl_pass_context[x];
}
+
+ break;
+ }
+
+ if (profile->acl_fail_context[x]) {
+ acl_context = profile->acl_fail_context[x];
+ } else {
+ acl_context = NULL;
}
}
+ } else {
+ x_auth_ip = network_ip;
}
}
- if (!ok) {
-
- if (!sofia_test_pflag(profile, PFLAG_AUTH_CALLS)) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "IP %s Rejected by acl \"%s\"\n", network_ip, switch_str_nil(last_acl));
-
- if (!acl_context) {
- nua_respond(nh, SIP_403_FORBIDDEN, TAG_END());
- goto fail;
- }
- } else {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "IP %s Rejected by acl \"%s\". Falling back to Digest auth.\n",
- network_ip, switch_str_nil(last_acl));
- }
- } else {
+ if (ok) {
if (token) {
switch_set_string(acl_token, token);
}
if (sofia_test_pflag(profile, PFLAG_AUTH_CALLS)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "IP %s Approved by acl \"%s[%s]\". Access Granted.\n",
- proxied_client_ip, switch_str_nil(last_acl), acl_token);
+ x_auth_ip, switch_str_nil(last_acl), acl_token);
switch_set_string(sip_acl_authed_by, last_acl);
switch_set_string(sip_acl_token, acl_token);
-
is_auth = 1;
-
+ }
+ } else {
+ if (!sofia_test_pflag(profile, PFLAG_AUTH_CALLS)) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "IP %s Rejected by acl \"%s\"\n", x_auth_ip, switch_str_nil(last_acl));
+ if (!acl_context) {
+ nua_respond(nh, SIP_403_FORBIDDEN, TAG_END());
+ goto fail;
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "IP %s Rejected by acl \"%s\". Falling back to Digest auth.\n",
+ x_auth_ip, switch_str_nil(last_acl));
+ }
}
}
}
}
+
+ if (!is_auth && sofia_test_pflag(profile, PFLAG_AUTH_CALLS) && sofia_test_pflag(profile, PFLAG_AUTH_CALLS_ACL_ONLY)) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "IP/Port %s %i Rejected by acls and auth-calls-acl-only flag is set, rejecting call\n",
+ network_ip, network_port);
+ nua_respond(nh, SIP_403_FORBIDDEN, TAG_END());
+ goto fail;
+ }
+
if (!is_auth && sofia_test_pflag(profile, PFLAG_AUTH_CALLS) && sofia_test_pflag(profile, PFLAG_BLIND_AUTH)) {
- char *user;
+ char *user = NULL;
switch_status_t blind_result = SWITCH_STATUS_FALSE;
if (!strcmp(network_ip, profile->sipip) && network_port == profile->sip_port) {
@@ -10290,15 +10401,14 @@ void sofia_handle_sip_i_invite(switch_core_session_t *session, nua_t *nua, sofia
if (sip && sip->sip_from) {
user = switch_core_session_sprintf(session, "%s@%s", sip->sip_from->a_url->url_user, sip->sip_from->a_url->url_host);
- switch_event_create(&v_event, SWITCH_EVENT_REQUEST_PARAMS);
- for (un = sip->sip_unknown; un; un = un->un_next) {
- switch_event_add_header_string(v_event, SWITCH_STACK_BOTTOM, un->un_name, un->un_value);
- };
- blind_result = switch_ivr_set_user_extended(session, user, v_event);
- switch_event_destroy(&v_event);
+ blind_result = sofia_locate_user(user, session, sip, &x_user);
}
- if(!sofia_test_pflag(profile, PFLAG_BLIND_AUTH_ENFORCE_RESULT) || blind_result == SWITCH_STATUS_SUCCESS) {
+ if (!sofia_test_pflag(profile, PFLAG_BLIND_AUTH_ENFORCE_RESULT) || blind_result == SWITCH_STATUS_SUCCESS) {
is_auth++;
+ } else if (sofia_test_pflag(profile, PFLAG_BLIND_AUTH_REPLY_403)) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "blind auth enforce 403 enabled and couldn't find user %s, rejecting call\n", user);
+ nua_respond(nh, SIP_403_FORBIDDEN, TAG_END());
+ goto fail;
}
}
@@ -10342,11 +10452,13 @@ void sofia_handle_sip_i_invite(switch_core_session_t *session, nua_t *nua, sofia
if (*acl_token) {
switch_channel_set_variable(channel, "acl_token", acl_token);
- if (strchr(acl_token, '@')) {
- if (switch_ivr_set_user(session, acl_token) == SWITCH_STATUS_SUCCESS) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Authenticating user %s\n", acl_token);
- } else {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Error Authenticating user %s\n", acl_token);
+ if (sofia_locate_user(acl_token, session, sip, &x_user) == SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Authenticating user %s\n", acl_token);
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Error Authenticating user %s\n", acl_token);
+ if (sofia_test_pflag(profile, PFLAG_AUTH_REQUIRE_USER)) {
+ nua_respond(nh, SIP_480_TEMPORARILY_UNAVAILABLE, TAG_END());
+ goto fail;
}
}
}
@@ -11016,186 +11128,44 @@ void sofia_handle_sip_i_invite(switch_core_session_t *session, nua_t *nua, sofia
}
}
+ if (sip && sip->sip_replaces) {
+ msg_common_t *rp_common = sip->sip_replaces->rp_common;
+ switch_channel_set_variable(channel, "sip_replaces_call_id", sip->sip_replaces->rp_call_id);
+ if (rp_common && rp_common->h_class->hc_params) {
+ int i, n;
+ msg_param_t const *params = * (msg_param_t const **) ((char *)rp_common + rp_common->h_class->hc_params);
+ for (i = 0; params[i]; i++) {
+ msg_param_t param = params[i];
+ if (strchr(param, '=')) {
+ n = strcspn(param, "=");
+ switch_channel_set_variable_name_printf(channel, param + n + 1, "sip_replaces_%.*s", n, param);
+ } else {
+ switch_channel_set_variable_name_printf(channel, "true", "sip_replaces_%s", param);
+ }
+ }
+ }
+ }
+
if (bnh) {
sofia_private_t *b_private = NULL;
if ((b_private = nua_handle_magic(bnh))) {
switch_core_session_t *b_session = NULL;
-
if ((b_session = switch_core_session_locate(b_private->uuid))) {
switch_channel_t *b_channel = switch_core_session_get_channel(b_session);
- const char *bridge_uuid;
- switch_caller_profile_t *orig_cp, *cp;
- //const char *sent_name, *sent_number;
- orig_cp = switch_channel_get_caller_profile(b_channel);
- tech_pvt->caller_profile->callee_id_name = switch_core_strdup(tech_pvt->caller_profile->pool, orig_cp->callee_id_name);
- tech_pvt->caller_profile->callee_id_number = switch_core_strdup(tech_pvt->caller_profile->pool, orig_cp->callee_id_number);
-
- if (!call_info) {
- tech_pvt->caller_profile->caller_id_name = switch_core_strdup(tech_pvt->caller_profile->pool, orig_cp->caller_id_name);
- tech_pvt->caller_profile->caller_id_number = switch_core_strdup(tech_pvt->caller_profile->pool, orig_cp->caller_id_number);
- }
-
- if (orig_cp) {
- cp = switch_caller_profile_dup(tech_pvt->caller_profile->pool, orig_cp);
- switch_channel_set_originator_caller_profile(channel, cp);
- }
-
-#if 0
- sent_name = switch_channel_get_variable(b_channel, "last_sent_callee_id_name");
- sent_number = switch_channel_get_variable(b_channel, "last_sent_callee_id_number");
-
- if (!zstr(sent_name) && !zstr(sent_number)) {
- tech_pvt->caller_profile->callee_id_name = switch_core_strdup(tech_pvt->caller_profile->pool, sent_name);
- tech_pvt->caller_profile->callee_id_number = switch_core_strdup(tech_pvt->caller_profile->pool, sent_number);
- } else {
- if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
- tech_pvt->caller_profile->callee_id_name = switch_core_strdup(tech_pvt->caller_profile->pool, orig_cp->callee_id_name);
- tech_pvt->caller_profile->callee_id_number = switch_core_strdup(tech_pvt->caller_profile->pool, orig_cp->callee_id_number);
- } else {
- tech_pvt->caller_profile->callee_id_name = switch_core_strdup(tech_pvt->caller_profile->pool, orig_cp->caller_id_name);
- tech_pvt->caller_profile->callee_id_number = switch_core_strdup(tech_pvt->caller_profile->pool, orig_cp->caller_id_number);
- }
- }
-#endif
-
- if (is_nat) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Setting NAT mode based on %s\n", is_nat);
- }
-
- tech_pvt->caller_profile->dialplan = "inline";
-
- bridge_uuid = switch_channel_get_partner_uuid(b_channel);
-
- if (call_info) {
- switch_event_t *event = NULL;
-
- if (!zstr(bridge_uuid) && switch_channel_test_flag(b_channel, CF_LEG_HOLDING)) {
- const char *b_call_id = switch_channel_get_variable(b_channel, "sip_call_id");
-
- if (b_call_id) {
- char *sql = switch_mprintf("update sip_dialogs set call_info_state='idle' where call_id='%q'", b_call_id);
- if (mod_sofia_globals.debug_sla > 1) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "QUERY SQL %s\n", sql);
- }
- sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
-
- switch_channel_presence(b_channel, "unknown", "idle", NULL);
- }
- switch_channel_set_flag(tech_pvt->channel, CF_SLA_INTERCEPT);
- tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool,
- "answer,intercept:%s", bridge_uuid);
-
- if (sofia_test_pflag(profile, PFLAG_FIRE_TRANFER_EVENTS)
- && switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_REPLACED) == SWITCH_STATUS_SUCCESS) {
- switch_channel_event_set_data(b_channel, event);
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "att_xfer_replaced_by", sip->sip_call_id->i_id);
- switch_event_fire(&event);
- }
- } else {
- switch_caller_profile_t *bcp = switch_channel_get_caller_profile(b_channel);
-
- if (switch_channel_test_flag(b_channel, CF_BRIDGE_ORIGINATOR)) {
- switch_channel_set_flag(tech_pvt->channel, CF_BRIDGE_ORIGINATOR);
- }
-
- if (!zstr(bcp->callee_id_name)) {
- tech_pvt->caller_profile->callee_id_name = switch_core_strdup(tech_pvt->caller_profile->pool, bcp->callee_id_name);
- }
-
- if (!zstr(bcp->callee_id_number)) {
- tech_pvt->caller_profile->callee_id_number = switch_core_strdup(tech_pvt->caller_profile->pool, bcp->callee_id_number);
- }
-
-
- if (!zstr(bcp->caller_id_name)) {
- tech_pvt->caller_profile->caller_id_name = switch_core_strdup(tech_pvt->caller_profile->pool, bcp->caller_id_name);
- }
-
- if (!zstr(bcp->caller_id_number)) {
- tech_pvt->caller_profile->caller_id_number = switch_core_strdup(tech_pvt->caller_profile->pool, bcp->caller_id_number);
- }
-
- if (bcp->originatee_caller_profile) {
- switch_caller_profile_t *cp;
-
- cp = switch_caller_profile_dup(tech_pvt->caller_profile->pool,
- bcp->originatee_caller_profile);
-
- switch_channel_set_originatee_caller_profile(tech_pvt->channel, cp);
- }
-
- tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool,
- "answer,sofia_sla:%s", b_private->uuid);
- }
- } else {
- char const *a_leg = NULL;
- char const *nightmare_xfer_uuid = NULL;
-
- switch_event_t *event = NULL;
- if (sip->sip_replaces && sip->sip_replaces->rp_params && sip->sip_replaces->rp_call_id) {
- a_leg = msg_header_find_param(sip->sip_replaces->rp_common, "a-leg");
- }
- if(a_leg && switch_true(a_leg)) {
- switch_channel_mark_hold(b_channel, SWITCH_FALSE);
- tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool, "answer,intercept:%s", sip->sip_replaces->rp_call_id);
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "call %s picked up on a-leg\n", sip->sip_replaces->rp_call_id);
- if (sofia_test_pflag(profile, PFLAG_FIRE_TRANFER_EVENTS)
- && switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_INTERCEPTED) == SWITCH_STATUS_SUCCESS) {
- switch_channel_event_set_data(b_channel, event);
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "intercepted_by", sip->sip_call_id->i_id);
- switch_event_fire(&event);
- }
- } else {
- if ((nightmare_xfer_uuid = sofia_glue_get_unknown_header(sip, "X-FS-Refer-For"))) {
- switch_channel_set_variable(b_channel, "transfer_refer_for", nightmare_xfer_uuid);
- }
- if ((nightmare_xfer_uuid = sofia_glue_get_unknown_header(sip, "X-FS-Refer-From"))) {
- switch_channel_set_variable(b_channel, "transfer_refer_from", nightmare_xfer_uuid);
- }
-
- if (!zstr(bridge_uuid)) {
- if (sip->sip_replaces && sip->sip_replaces->rp_params && sip->sip_replaces->rp_call_id && switch_channel_test_flag(b_channel, CF_BRIDGED) &&
- switch_true(switch_find_parameter(*(sip->sip_replaces->rp_params), "early-only", switch_core_session_get_pool(session)))) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "call %s intercept rejected\n", bridge_uuid);
- tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool, "hangup:CALL_REJECTED");
- } else {
- switch_channel_mark_hold(b_channel, SWITCH_FALSE);
- tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool, "answer,intercept:%s", bridge_uuid);
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "call %s intercepted\n", bridge_uuid);
- if (sofia_test_pflag(profile, PFLAG_FIRE_TRANFER_EVENTS) &&
- switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_INTERCEPTED) == SWITCH_STATUS_SUCCESS) {
- switch_channel_event_set_data(b_channel, event);
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "intercepted_by", sip->sip_call_id->i_id);
- switch_event_fire(&event);
- }
- }
- } else {
- const char *b_app = switch_channel_get_variable(b_channel, SWITCH_CURRENT_APPLICATION_VARIABLE);
- const char *b_data = switch_channel_get_variable(b_channel, SWITCH_CURRENT_APPLICATION_DATA_VARIABLE);
- if (b_data && b_app) {
- tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool, "answer,%s:%s", b_app, b_data);
- } else if (b_app) {
- tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool, "answer,%s", b_app);
- }
- if (sofia_test_pflag(profile, PFLAG_FIRE_TRANFER_EVENTS)
- && switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_REPLACED) == SWITCH_STATUS_SUCCESS) {
- switch_channel_event_set_data(b_channel, event);
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "att_xfer_replaced_by", sip->sip_call_id->i_id);
- switch_event_fire(&event);
- }
- switch_channel_hangup(b_channel, SWITCH_CAUSE_ATTENDED_TRANSFER);
- }
- }
- }
-
+ sofia_handle_sip_i_invite_replaces(session, channel, b_channel, b_private->uuid, tech_pvt, call_info, profile, is_nat, sip);
switch_core_session_rwunlock(b_session);
}
}
nua_handle_unref(bnh);
+ } else if (sip && sip->sip_replaces && sip->sip_replaces->rp_call_id) {
+ switch_core_session_t *b_session = NULL;
+ if ((b_session = switch_core_session_locate((char*) sip->sip_replaces->rp_call_id))) {
+ switch_channel_t *b_channel = switch_core_session_get_channel(b_session);
+ sofia_handle_sip_i_invite_replaces(session, channel, b_channel, (char*) sip->sip_replaces->rp_call_id, tech_pvt, call_info, profile, is_nat, sip);
+ switch_core_session_rwunlock(b_session);
+ }
}
-
-
if (tech_pvt->caller_profile) {
int first_history_info = 1;
@@ -11410,6 +11380,183 @@ void sofia_handle_sip_i_invite(switch_core_session_t *session, nua_t *nua, sofia
}
+void sofia_handle_sip_i_invite_replaces(switch_core_session_t *session, switch_channel_t *channel, switch_channel_t *b_channel, char* uuid, private_object_t *tech_pvt, sip_call_info_t *call_info, sofia_profile_t *profile, char *is_nat, sip_t const *sip)
+{
+ const char *bridge_uuid;
+ switch_caller_profile_t *orig_cp, *cp;
+ //const char *sent_name, *sent_number;
+ orig_cp = switch_channel_get_caller_profile(b_channel);
+ tech_pvt->caller_profile->callee_id_name = switch_core_strdup(tech_pvt->caller_profile->pool, orig_cp->callee_id_name);
+ tech_pvt->caller_profile->callee_id_number = switch_core_strdup(tech_pvt->caller_profile->pool, orig_cp->callee_id_number);
+
+ if (!call_info) {
+ tech_pvt->caller_profile->caller_id_name = switch_core_strdup(tech_pvt->caller_profile->pool, orig_cp->caller_id_name);
+ tech_pvt->caller_profile->caller_id_number = switch_core_strdup(tech_pvt->caller_profile->pool, orig_cp->caller_id_number);
+ }
+
+ if (orig_cp) {
+ cp = switch_caller_profile_dup(tech_pvt->caller_profile->pool, orig_cp);
+ switch_channel_set_originator_caller_profile(channel, cp);
+ }
+
+#if 0
+ sent_name = switch_channel_get_variable(b_channel, "last_sent_callee_id_name");
+ sent_number = switch_channel_get_variable(b_channel, "last_sent_callee_id_number");
+
+ if (!zstr(sent_name) && !zstr(sent_number)) {
+ tech_pvt->caller_profile->callee_id_name = switch_core_strdup(tech_pvt->caller_profile->pool, sent_name);
+ tech_pvt->caller_profile->callee_id_number = switch_core_strdup(tech_pvt->caller_profile->pool, sent_number);
+ } else {
+ if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
+ tech_pvt->caller_profile->callee_id_name = switch_core_strdup(tech_pvt->caller_profile->pool, orig_cp->callee_id_name);
+ tech_pvt->caller_profile->callee_id_number = switch_core_strdup(tech_pvt->caller_profile->pool, orig_cp->callee_id_number);
+ } else {
+ tech_pvt->caller_profile->callee_id_name = switch_core_strdup(tech_pvt->caller_profile->pool, orig_cp->caller_id_name);
+ tech_pvt->caller_profile->callee_id_number = switch_core_strdup(tech_pvt->caller_profile->pool, orig_cp->caller_id_number);
+ }
+ }
+#endif
+
+ if (is_nat) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Setting NAT mode based on %s\n", is_nat);
+ }
+
+ tech_pvt->caller_profile->dialplan = "inline";
+
+ bridge_uuid = switch_channel_get_partner_uuid(b_channel);
+ if (bridge_uuid) {
+ switch_core_session_t *bridge_session = NULL;
+ if ((bridge_session = switch_core_session_locate(bridge_uuid))) {
+ switch_core_session_rwunlock(bridge_session);
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "could not locate partner_uuid %s, resetting\n", bridge_uuid);
+ bridge_uuid = NULL;
+ }
+ }
+
+ if (call_info) {
+ switch_event_t *event = NULL;
+
+ if (!zstr(bridge_uuid) && switch_channel_test_flag(b_channel, CF_LEG_HOLDING)) {
+ const char *b_call_id = switch_channel_get_variable(b_channel, "sip_call_id");
+
+ if (b_call_id) {
+ char *sql = switch_mprintf("update sip_dialogs set call_info_state='idle' where call_id='%q'", b_call_id);
+ if (mod_sofia_globals.debug_sla > 1) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "QUERY SQL %s\n", sql);
+ }
+ sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
+
+ switch_channel_presence(b_channel, "unknown", "idle", NULL);
+ }
+ switch_channel_set_flag(tech_pvt->channel, CF_SLA_INTERCEPT);
+ tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool,
+ "answer,intercept:%s", bridge_uuid);
+
+ if (sofia_test_pflag(profile, PFLAG_FIRE_TRANFER_EVENTS)
+ && sip && sip->sip_call_id
+ && switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_REPLACED) == SWITCH_STATUS_SUCCESS) {
+ switch_channel_event_set_data(b_channel, event);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "att_xfer_replaced_by", sip->sip_call_id->i_id);
+ switch_event_fire(&event);
+ }
+ } else {
+ switch_caller_profile_t *bcp = switch_channel_get_caller_profile(b_channel);
+
+ if (switch_channel_test_flag(b_channel, CF_BRIDGE_ORIGINATOR)) {
+ switch_channel_set_flag(tech_pvt->channel, CF_BRIDGE_ORIGINATOR);
+ }
+
+ if (!zstr(bcp->callee_id_name)) {
+ tech_pvt->caller_profile->callee_id_name = switch_core_strdup(tech_pvt->caller_profile->pool, bcp->callee_id_name);
+ }
+
+ if (!zstr(bcp->callee_id_number)) {
+ tech_pvt->caller_profile->callee_id_number = switch_core_strdup(tech_pvt->caller_profile->pool, bcp->callee_id_number);
+ }
+
+
+ if (!zstr(bcp->caller_id_name)) {
+ tech_pvt->caller_profile->caller_id_name = switch_core_strdup(tech_pvt->caller_profile->pool, bcp->caller_id_name);
+ }
+
+ if (!zstr(bcp->caller_id_number)) {
+ tech_pvt->caller_profile->caller_id_number = switch_core_strdup(tech_pvt->caller_profile->pool, bcp->caller_id_number);
+ }
+
+ if (bcp->originatee_caller_profile) {
+ switch_caller_profile_t *cp;
+
+ cp = switch_caller_profile_dup(tech_pvt->caller_profile->pool,
+ bcp->originatee_caller_profile);
+
+ switch_channel_set_originatee_caller_profile(tech_pvt->channel, cp);
+ }
+
+ tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool,
+ "answer,sofia_sla:%s", uuid);
+ }
+ } else {
+ char const *nightmare_xfer_uuid = NULL;
+ switch_event_t *event = NULL;
+ if (switch_channel_var_true(channel, "sip_replaces_a-leg")) {
+ switch_channel_mark_hold(b_channel, SWITCH_FALSE);
+ tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool, "answer,intercept:%s", sip->sip_replaces->rp_call_id);
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "call %s picked up on a-leg\n", sip->sip_replaces->rp_call_id);
+ if (sofia_test_pflag(profile, PFLAG_FIRE_TRANFER_EVENTS)
+ && sip && sip->sip_call_id
+ && switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_INTERCEPTED) == SWITCH_STATUS_SUCCESS) {
+ switch_channel_event_set_data(b_channel, event);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "intercepted_by", sip->sip_call_id->i_id);
+ switch_event_fire(&event);
+ }
+ } else {
+ if ((nightmare_xfer_uuid = sofia_glue_get_unknown_header(sip, "X-FS-Refer-For"))) {
+ switch_channel_set_variable(b_channel, "transfer_refer_for", nightmare_xfer_uuid);
+ }
+ if ((nightmare_xfer_uuid = sofia_glue_get_unknown_header(sip, "X-FS-Refer-From"))) {
+ switch_channel_set_variable(b_channel, "transfer_refer_from", nightmare_xfer_uuid);
+ }
+
+ if (!zstr(bridge_uuid)) {
+ if (sip->sip_replaces && sip->sip_replaces->rp_params && sip->sip_replaces->rp_call_id && switch_channel_test_flag(b_channel, CF_BRIDGED) &&
+ switch_true(switch_find_parameter(*(sip->sip_replaces->rp_params), "early-only", switch_core_session_get_pool(session)))) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "call %s intercept rejected\n", bridge_uuid);
+ tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool, "hangup:CALL_REJECTED");
+ } else {
+ switch_channel_mark_hold(b_channel, SWITCH_FALSE);
+ tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool, "answer,intercept:%s", bridge_uuid);
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "call %s intercepted\n", bridge_uuid);
+ if (sofia_test_pflag(profile, PFLAG_FIRE_TRANFER_EVENTS)
+ && sip && sip->sip_call_id
+ && switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_INTERCEPTED) == SWITCH_STATUS_SUCCESS) {
+ switch_channel_event_set_data(b_channel, event);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "intercepted_by", sip->sip_call_id->i_id);
+ switch_event_fire(&event);
+ }
+ }
+ } else {
+ const char *b_app = switch_channel_get_variable(b_channel, SWITCH_CURRENT_APPLICATION_VARIABLE);
+ const char *b_data = switch_channel_get_variable(b_channel, SWITCH_CURRENT_APPLICATION_DATA_VARIABLE);
+ if (b_data && b_app) {
+ tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool, "answer,%s:%s", b_app, b_data);
+ } else if (b_app) {
+ tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool, "answer,%s", b_app);
+ }
+ if (sofia_test_pflag(profile, PFLAG_FIRE_TRANFER_EVENTS)
+ && sip && sip->sip_call_id
+ && switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_REPLACED) == SWITCH_STATUS_SUCCESS) {
+ switch_channel_event_set_data(b_channel, event);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "att_xfer_replaced_by", sip->sip_call_id->i_id);
+ switch_event_fire(&event);
+ }
+ switch_channel_hangup(b_channel, SWITCH_CAUSE_ATTENDED_TRANSFER);
+ }
+ }
+ }
+
+}
+
void sofia_handle_sip_i_options(int status,
char const *phrase,
nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip,
diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c
index d1431a1e57..46853771b9 100644
--- a/src/mod/endpoints/mod_sofia/sofia_glue.c
+++ b/src/mod/endpoints/mod_sofia/sofia_glue.c
@@ -926,12 +926,21 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session)
rpid_domain = "cluecon.com";
}
+ if (!zstr(tech_pvt->dest)) {
+ dst = sofia_glue_get_destination(tech_pvt->dest);
+ }
+
/*
* Ignore transport chanvar and uri parameter for gateway connections
* since all of them have been already taken care of in mod_sofia.c:sofia_outgoing_channel()
*/
if (tech_pvt->transport == SOFIA_TRANSPORT_UNKNOWN && zstr(tech_pvt->gateway_name)) {
- if ((p = (char *) switch_stristr("port=", url))) {
+ if (dst && dst->route_uri) {
+ p = dst->route_uri;
+ } else {
+ p = url;
+ }
+ if ((p = (char *) switch_stristr("port=", p))) {
p += 5;
tech_pvt->transport = sofia_glue_str2transport(p);
} else {
@@ -1079,7 +1088,9 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session)
|| ((val = switch_channel_get_variable(channel, "sip_sticky_contact")) && switch_true(val)))) {
sofia_set_flag(tech_pvt, TFLAG_NAT);
tech_pvt->record_route = switch_core_session_strdup(tech_pvt->session, url_str);
- route_uri = tech_pvt->record_route;
+ if (!dst || !dst->route_uri) {
+ route_uri = tech_pvt->record_route;
+ }
session_timeout = SOFIA_NAT_SESSION_TIMEOUT;
switch_channel_set_variable(channel, "sip_nat_detected", "true");
}
@@ -1251,7 +1262,9 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session)
}
if (!zstr(tech_pvt->dest)) {
- dst = sofia_glue_get_destination(tech_pvt->dest);
+ if (!dst) {
+ dst = sofia_glue_get_destination(tech_pvt->dest);
+ }
if (dst->route_uri) {
route_uri = sofia_overcome_sip_uri_weakness(tech_pvt->session, dst->route_uri, tech_pvt->transport, SWITCH_TRUE, NULL, NULL);
@@ -1449,6 +1462,7 @@ switch_call_cause_t sofia_glue_sip_cause_to_freeswitch(int status)
case 403:
case 407:
case 603:
+ case 607:
return SWITCH_CAUSE_CALL_REJECTED;
case 404:
return SWITCH_CAUSE_UNALLOCATED_NUMBER;
diff --git a/src/mod/endpoints/mod_sofia/sofia_json_api.c b/src/mod/endpoints/mod_sofia/sofia_json_api.c
new file mode 100644
index 0000000000..49005b2021
--- /dev/null
+++ b/src/mod/endpoints/mod_sofia/sofia_json_api.c
@@ -0,0 +1,229 @@
+/*
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005-2014, Anthony Minessale II
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ *
+ * The Initial Developer of the Original Code is
+ * Anthony Minessale II
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Anthony Minessale II
+ * Ken Rice
+ * Paul D. Tinsley
+ * Bret McDanel
+ * Raymond Chandler
+ * Emmanuel Schmidbauer
+ * Kathleen King
+ *
+ *
+ * mod_sofia.c -- SOFIA SIP Endpoint
+ *
+ */
+
+/* Best viewed in a 160 x 60 VT100 Terminal or so the line below at least fits across your screen*/
+/*************************************************************************************************************************************************************/
+#include "mod_sofia.h"
+
+
+typedef switch_status_t (*sofia_command_t) (char **argv, int argc, switch_stream_handle_t *stream);
+
+extern const char *sofia_state_names[];
+
+switch_status_t build_sofia_status_json(cJSON * container)
+{
+ sofia_profile_t *profile = NULL;
+ sofia_gateway_t *gp;
+ switch_hash_index_t *hi;
+ void *val;
+ const void *vvar;
+ switch_mutex_lock(mod_sofia_globals.hash_mutex);
+ for (hi = switch_core_hash_first(mod_sofia_globals.profile_hash); hi; hi = switch_core_hash_next(&hi)) {
+ cJSON * jprofile = cJSON_CreateObject();
+ cJSON * jstatus = cJSON_CreateObject();
+ switch_core_hash_this(hi, &vvar, NULL, &val);
+ cJSON_AddItemToObject(container, (const char *)vvar, jprofile);
+ cJSON_AddItemToObject(jprofile, "status", jstatus);
+ profile = (sofia_profile_t *) val;
+ if (strcmp(vvar, profile->name)) {
+ cJSON_AddItemToObject(jstatus, "type", cJSON_CreateString("alias"));
+ cJSON_AddItemToObject(jstatus, "data", cJSON_CreateString(profile->name));
+ cJSON_AddItemToObject(jstatus, "state", cJSON_CreateString("ALIASED"));
+ } else {
+ cJSON_AddItemToObject(jstatus, "type", cJSON_CreateString("profile"));
+ cJSON_AddItemToObject(jstatus, "state", cJSON_CreateString(sofia_test_pflag(profile, PFLAG_RUNNING) ? "RUNNING" : "DOWN"));
+ cJSON_AddItemToObject(jstatus, "in-use", cJSON_CreateNumber(profile->inuse));
+ if (! sofia_test_pflag(profile, PFLAG_TLS) || ! profile->tls_only) {
+ cJSON_AddItemToObject(jstatus, "data", cJSON_CreateString(profile->url));
+ } else if (sofia_test_pflag(profile, PFLAG_TLS)) {
+ cJSON_AddItemToObject(jstatus, "data", cJSON_CreateString(profile->tls_url));
+ cJSON_AddItemToObject(jstatus, "transport", cJSON_CreateString("tls"));
+ } else if (profile->ws_bindurl) {
+ cJSON_AddItemToObject(jprofile, "data", cJSON_CreateString(profile->ws_bindurl));
+ cJSON_AddItemToObject(jprofile, "transport", cJSON_CreateString("ws"));
+ } else if (profile->wss_bindurl) {
+ cJSON_AddItemToObject(jprofile, "data", cJSON_CreateString(profile->wss_bindurl));
+ cJSON_AddItemToObject(jprofile, "transport", cJSON_CreateString("wss"));
+ }
+
+ if (profile->gateways) {
+ cJSON *gateways = cJSON_CreateObject();
+ cJSON_AddItemToObject(jprofile, "gateways", gateways);
+ for (gp = profile->gateways; gp; gp = gp->next) {
+ cJSON *gateway = cJSON_CreateObject();
+ cJSON_AddItemToObject(gateways, gp->name, gateway);
+ switch_assert(gp->state < REG_STATE_LAST);
+ cJSON_AddItemToObject(gateway, "type", cJSON_CreateString("gateway"));
+ cJSON_AddItemToObject(gateway, "data", cJSON_CreateString(gp->register_to));
+ cJSON_AddItemToObject(gateway, "state", cJSON_CreateString(sofia_state_names[gp->state]));
+ if (gp->state == REG_STATE_FAILED || gp->state == REG_STATE_TRYING) {
+ time_t now = switch_epoch_time_now(NULL);
+ if (gp->retry > now) {
+ cJSON_AddItemToObject(gateway, "retry", cJSON_CreateNumber(gp->retry - now));
+ } else {
+ cJSON_AddItemToObject(gateway, "retry", cJSON_CreateString("never"));
+ }
+ }
+ }
+ }
+ }
+ }
+ switch_mutex_unlock(mod_sofia_globals.hash_mutex);
+ return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t build_sofia_profile_info_json(cJSON * container)
+{
+ sofia_profile_t *profile = NULL;
+ cJSON *item, *iter = container->child;
+ while(iter) {
+ if ( (profile = sofia_glue_find_profile(iter->string))) {
+ cJSON *info = cJSON_CreateObject();
+ cJSON_AddItemToObject(iter, "info", info);
+
+ cJSON_AddItemToObject(info, "domain-name", cJSON_CreateString(profile->domain_name ? profile->domain_name : "N/A"));
+ if (strcasecmp(iter->string, profile->name)) {
+ cJSON_AddItemToObject(info, "alias-of", cJSON_CreateString(switch_str_nil(profile->name)));
+ }
+
+ cJSON_AddItemToObject(info, "auto-nat", cJSON_CreateString(sofia_test_pflag(profile, PFLAG_AUTO_NAT) ? "true" : "false"));
+ cJSON_AddItemToObject(info, "db-name", cJSON_CreateString(profile->dbname ? profile->dbname : switch_str_nil(profile->odbc_dsn)));
+ cJSON_AddItemToObject(info, "pres-hosts", cJSON_CreateString(switch_str_nil(profile->presence_hosts)));
+ cJSON_AddItemToObject(info, "dialplan", cJSON_CreateString(switch_str_nil(profile->dialplan)));
+ cJSON_AddItemToObject(info, "context", cJSON_CreateString(switch_str_nil(profile->context)));
+ cJSON_AddItemToObject(info, "challenge-realm", cJSON_CreateString(zstr(profile->challenge_realm) ? "auto_to" : profile->challenge_realm));
+
+ item = cJSON_CreateStringArray((const char **)profile->rtpip, profile->rtpip_index);
+ cJSON_AddItemToObject(info, "rtp-ip", item);
+
+ cJSON_AddItemToObject(info, "ext-rtp-ip", cJSON_CreateString(profile->extrtpip));
+ cJSON_AddItemToObject(info, "sip-ip", cJSON_CreateString(switch_str_nil(profile->sipip)));
+ cJSON_AddItemToObject(info, "ext-sip-ip", cJSON_CreateString(switch_str_nil(profile->extsipip)));
+
+ if (! sofia_test_pflag(profile, PFLAG_TLS) || ! profile->tls_only) {
+ cJSON_AddItemToObject(info, "url", cJSON_CreateString(switch_str_nil(profile->url)));
+ cJSON_AddItemToObject(info, "bind-url", cJSON_CreateString(switch_str_nil(profile->bindurl)));
+ }
+ if (sofia_test_pflag(profile, PFLAG_TLS)) {
+ cJSON_AddItemToObject(info, "tls-url", cJSON_CreateString(switch_str_nil(profile->tls_url)));
+ cJSON_AddItemToObject(info, "tls-bind-url", cJSON_CreateString(switch_str_nil(profile->tls_bindurl)));
+ }
+ if (profile->ws_bindurl) {
+ cJSON_AddItemToObject(info, "ws-bind-url", cJSON_CreateString(switch_str_nil(profile->ws_bindurl)));
+ }
+ if (profile->wss_bindurl) {
+ cJSON_AddItemToObject(info, "wss-bind-url", cJSON_CreateString(switch_str_nil(profile->wss_bindurl)));
+ }
+
+ cJSON_AddItemToObject(info, "hold-music", cJSON_CreateString(switch_str_nil(profile->hold_music)));
+ cJSON_AddItemToObject(info, "outbound-proxy", cJSON_CreateString(zstr(profile->outbound_proxy) ? "N/A" : profile->outbound_proxy));
+
+ sofia_glue_release_profile(profile);
+
+ }
+
+ iter = iter->next;
+
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+SWITCH_STANDARD_JSON_API(sofia_status_json_function)
+{
+ cJSON *ret = cJSON_CreateObject();
+ cJSON *profiles = cJSON_CreateObject();
+ cJSON_AddItemToObject(ret, "profiles", profiles);
+ build_sofia_status_json(profiles);
+
+ *json_reply = ret;
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+SWITCH_STANDARD_JSON_API(sofia_status_info_json_function)
+{
+ cJSON *ret = cJSON_CreateObject();
+ cJSON *profiles = cJSON_CreateObject();
+ cJSON_AddItemToObject(ret, "profiles", profiles);
+ build_sofia_status_json(profiles);
+ build_sofia_profile_info_json(profiles);
+
+ *json_reply = ret;
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t cmd_json_status(char **argv, int argc, switch_stream_handle_t *stream)
+{
+ char * json;
+ cJSON *ret = cJSON_CreateObject();
+ cJSON *profiles = cJSON_CreateObject();
+ cJSON_AddItemToObject(ret, "profiles", profiles);
+ build_sofia_status_json(profiles);
+ build_sofia_profile_info_json(profiles);
+
+ json = cJSON_Print(ret);
+ stream->write_function(stream, "%s\n", json);
+
+ switch_safe_free(json);
+ cJSON_Delete(ret);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+void add_sofia_json_apis(switch_loadable_module_interface_t **module_interface)
+{
+ switch_json_api_interface_t *json_api_interface;
+ SWITCH_ADD_JSON_API(json_api_interface, "sofia.status", "sofia status JSON API", sofia_status_json_function, "");
+ SWITCH_ADD_JSON_API(json_api_interface, "sofia.status.info", "sofia status JSON API", sofia_status_info_json_function, "");
+}
+
+
+
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
+ */
diff --git a/src/mod/endpoints/mod_verto/mod_verto.c b/src/mod/endpoints/mod_verto/mod_verto.c
index 6ad57d2760..0143b8487f 100644
--- a/src/mod/endpoints/mod_verto/mod_verto.c
+++ b/src/mod/endpoints/mod_verto/mod_verto.c
@@ -62,7 +62,8 @@ SWITCH_MODULE_DEFINITION(mod_verto, mod_verto_load, mod_verto_shutdown, mod_vert
#define strerror_r(errno, buf, len) strerror_s(buf, len, errno)
#endif
-#define die(...) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, __VA_ARGS__); goto error
+#define log_and_exit(severity, ...) switch_log_printf(SWITCH_CHANNEL_LOG, (severity), __VA_ARGS__); goto error
+#define die(...) log_and_exit(SWITCH_LOG_WARNING, __VA_ARGS__)
#define die_errno(fmt) do { char errbuf[BUFSIZ] = {0}; strerror_r(errno, (char *)&errbuf, sizeof(errbuf)); die(fmt ", errno=%d, %s\n", errno, (char *)&errbuf); } while(0)
#define die_errnof(fmt, ...) do { char errbuf[BUFSIZ] = {0}; strerror_r(errno, (char *)&errbuf, sizeof(errbuf)); die(fmt ", errno=%d, %s\n", __VA_ARGS__, errno, (char *)&errbuf); } while(0)
@@ -915,7 +916,7 @@ static switch_bool_t check_auth(jsock_t *jsock, cJSON *params, int *code, char *
}
- if (!strcmp(login, "root")) {
+ if (!strcmp(login, "root") && jsock->profile->root_passwd) {
if (!(r = !strcmp(passwd, jsock->profile->root_passwd))) {
*code = CODE_AUTH_FAILED;
switch_snprintf(message, mlen, "Authentication Failure");
@@ -1797,14 +1798,21 @@ done:
*wsh->buffer = '\0';
while(jsock->profile->running) {
- int pflags = switch_wait_sock(jsock->client_socket, 3000, SWITCH_POLL_READ | SWITCH_POLL_ERROR | SWITCH_POLL_HUP);
+ int pflags;
+
+ if (wsh->ssl && SSL_pending(wsh->ssl) > 0) {
+ pflags = SWITCH_POLL_READ;
+ } else {
+ pflags = switch_wait_sock(jsock->client_socket, 3000, SWITCH_POLL_READ | SWITCH_POLL_ERROR | SWITCH_POLL_HUP);
+ }
if (jsock->drop) { die("%s Dropping Connection\n", jsock->name); }
- if (pflags < 0 && (errno != EINTR)) { die_errnof("%s POLL FAILED", jsock->name); }
- if (pflags & SWITCH_POLL_HUP) { die("%s POLL HANGUP DETECTED (peer closed its end of socket)\n", jsock->name); }
- if (pflags & SWITCH_POLL_ERROR) { die("%s POLL ERROR\n", jsock->name); }
- if (pflags & SWITCH_POLL_INVALID) { die("%s POLL INVALID SOCKET (not opened or already closed)\n", jsock->name); }
- if (pflags & SWITCH_POLL_READ) {
+ if (pflags < 0 && (errno != EINTR)) { die_errnof("%s POLL FAILED with %d", jsock->name, pflags); }
+ if (pflags == 0) { /* keepalive socket poll timeout */ break; }
+ if (pflags > 0 && (pflags & SWITCH_POLL_HUP)) { log_and_exit(SWITCH_LOG_INFO, "%s POLL HANGUP DETECTED (peer closed its end of socket)\n", jsock->name); }
+ if (pflags > 0 && (pflags & SWITCH_POLL_ERROR)) { die("%s POLL ERROR\n", jsock->name); }
+ if (pflags > 0 && (pflags & SWITCH_POLL_INVALID)) { die("%s POLL INVALID SOCKET (not opened or already closed)\n", jsock->name); }
+ if (pflags > 0 && (pflags & SWITCH_POLL_READ)) {
ssize_t bytes;
bytes = ws_raw_read(wsh, wsh->buffer + wsh->datalen, wsh->buflen - wsh->datalen - 1, wsh->block);
@@ -1834,8 +1842,6 @@ done:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "socket %s is going to handle a new request\n", jsock->name);
goto new_req;
}
- } else {
- break;
}
}
}
@@ -1862,19 +1868,26 @@ static void client_run(jsock_t *jsock)
ws_close(&jsock->ws, WS_NONE);
goto error;
} else {
- die("%s WS SETUP FAILED\n", jsock->name);
+ log_and_exit(SWITCH_LOG_NOTICE, "%s WS SETUP FAILED\n", jsock->name);
}
}
while(jsock->profile->running) {
- int pflags = switch_wait_sock(jsock->client_socket, 50, SWITCH_POLL_READ | SWITCH_POLL_ERROR | SWITCH_POLL_HUP);
+ int pflags;
+
+ if (jsock->ws.ssl && SSL_pending(jsock->ws.ssl) > 0) {
+ pflags = SWITCH_POLL_READ;
+ } else {
+ pflags = switch_wait_sock(jsock->client_socket, 50, SWITCH_POLL_READ | SWITCH_POLL_ERROR | SWITCH_POLL_HUP);
+ }
if (jsock->drop) { die("%s Dropping Connection\n", jsock->name); }
- if (pflags < 0 && (errno != EINTR)) { die_errnof("%s POLL FAILED", jsock->name); }
- if (pflags & SWITCH_POLL_HUP) { die("%s POLL HANGUP DETECTED (peer closed its end of socket)\n", jsock->name); }
- if (pflags & SWITCH_POLL_ERROR) { die("%s POLL ERROR\n", jsock->name); }
- if (pflags & SWITCH_POLL_INVALID) { die("%s POLL INVALID SOCKET (not opened or already closed)\n", jsock->name); }
- if (pflags & SWITCH_POLL_READ) {
+ if (pflags < 0 && (errno != EINTR)) { die_errnof("%s POLL FAILED with %d", jsock->name, pflags); }
+ if (pflags == 0) {/* socket poll timeout */ jsock_check_event_queue(jsock); }
+ if (pflags > 0 && (pflags & SWITCH_POLL_HUP)) { log_and_exit(SWITCH_LOG_INFO, "%s POLL HANGUP DETECTED (peer closed its end of socket)\n", jsock->name); }
+ if (pflags > 0 && (pflags & SWITCH_POLL_ERROR)) { die("%s POLL ERROR\n", jsock->name); }
+ if (pflags > 0 && (pflags & SWITCH_POLL_INVALID)) { die("%s POLL INVALID SOCKET (not opened or already closed)\n", jsock->name); }
+ if (pflags > 0 && (pflags & SWITCH_POLL_READ)) {
switch_ssize_t bytes;
ws_opcode_t oc;
uint8_t *data;
@@ -1883,7 +1896,7 @@ static void client_run(jsock_t *jsock)
if (bytes < 0) {
if (bytes == -WS_RECV_CLOSE) {
- die("%s Client sent close request\n", jsock->name);
+ log_and_exit(SWITCH_LOG_INFO, "%s Client sent close request\n", jsock->name);
} else {
die("%s BAD READ %" SWITCH_SSIZE_T_FMT "\n", jsock->name, bytes);
}
@@ -1963,8 +1976,6 @@ static void client_run(jsock_t *jsock)
switch_set_flag(jsock, JPFLAG_CHECK_ATTACH);
}
}
- } else {
- jsock_check_event_queue(jsock);
}
}
@@ -4410,8 +4421,9 @@ static int profile_one_loop(verto_profile_t *profile)
if ((res = switch_wait_socklist(pfds, max, 100)) < 0) {
if (errno != EINTR) {
- die_errnof("%s POLL FAILED", profile->name);
+ die_errnof("%s POLL FAILED with %d", profile->name, res);
}
+ return 0;
}
if (res == 0) {
@@ -4419,7 +4431,7 @@ static int profile_one_loop(verto_profile_t *profile)
}
for (x = 0; x < max; x++) {
- if (pfds[x].revents & SWITCH_POLL_HUP) { die("%s POLL HANGUP DETECTED (peer closed its end of socket)\n", profile->name); }
+ if (pfds[x].revents & SWITCH_POLL_HUP) { log_and_exit(SWITCH_LOG_INFO, "%s POLL HANGUP DETECTED (peer closed its end of socket)\n", profile->name); }
if (pfds[x].revents & SWITCH_POLL_ERROR) { die("%s POLL ERROR\n", profile->name); }
if (pfds[x].revents & SWITCH_POLL_INVALID) { die("%s POLL INVALID SOCKET (not opened or already closed)\n", profile->name); }
if (pfds[x].revents & SWITCH_POLL_READ) {
@@ -4523,9 +4535,9 @@ static int runtime(verto_profile_t *profile)
}
if (ok) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s MCAST Bound to %s:%d/%d\n", profile->name, profile->mcast_ip, profile->mcast_port, profile->mcast_port + 1);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s MCAST Bound to %s:%d/%d\n", profile->name, profile->mcast_ip, profile->mcast_port, profile->mcast_port + 1);
} else {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s MCAST Disabled\n", profile->name);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s MCAST Disabled\n", profile->name);
}
}
diff --git a/src/mod/event_handlers/mod_amqp/mod_amqp_producer.c b/src/mod/event_handlers/mod_amqp/mod_amqp_producer.c
index 305b366ddb..d4479b1752 100644
--- a/src/mod/event_handlers/mod_amqp/mod_amqp_producer.c
+++ b/src/mod/event_handlers/mod_amqp/mod_amqp_producer.c
@@ -175,7 +175,7 @@ switch_status_t mod_amqp_producer_create(char *name, switch_xml_t cfg)
char *format_fields[MAX_ROUTING_KEY_FORMAT_FIELDS+1];
int format_fields_size = 0;
- memset(format_fields, 0, MAX_ROUTING_KEY_FORMAT_FIELDS + 1);
+ memset(format_fields, 0, (MAX_ROUTING_KEY_FORMAT_FIELDS + 1) * sizeof(char *));
if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {
goto err;
diff --git a/src/mod/event_handlers/mod_kazoo/Makefile.am b/src/mod/event_handlers/mod_kazoo/Makefile.am
index 53fd7112e1..668d9ffed2 100644
--- a/src/mod/event_handlers/mod_kazoo/Makefile.am
+++ b/src/mod/event_handlers/mod_kazoo/Makefile.am
@@ -3,12 +3,31 @@ MODNAME=mod_kazoo
if HAVE_ERLANG
+KAZOO_DEFS=kazoo_definitions.o
+
mod_LTLIBRARIES = mod_kazoo.la
-mod_kazoo_la_SOURCES = mod_kazoo.c kazoo_utils.c kazoo_node.c kazoo_event_stream.c kazoo_fetch_agent.c kazoo_commands.c kazoo_dptools.c
-mod_kazoo_la_CFLAGS = $(AM_CFLAGS) @ERLANG_CFLAGS@ -D_REENTRANT
-mod_kazoo_la_LIBADD = $(switch_builddir)/libfreeswitch.la
+mod_kazoo_la_SOURCES = mod_kazoo.c kazoo_utils.c kazoo_dptools.c kazoo_tweaks.c
+mod_kazoo_la_SOURCES += kazoo_api.c kazoo_commands.c kazoo_config.c
+mod_kazoo_la_SOURCES += kazoo_message.c
+mod_kazoo_la_SOURCES += kazoo_ei_config.c kazoo_ei_utils.c kazoo_event_stream.c
+mod_kazoo_la_SOURCES += kazoo_fetch_agent.c kazoo_node.c
+mod_kazoo_la_SOURCES += kazoo_endpoints.c
+mod_kazoo_la_SOURCES += kz_node.c
+
+mod_kazoo_la_CFLAGS = $(AM_CFLAGS) @ERLANG_CFLAGS@ -D_REENTRANT -DERLANG_VERSION=@ERLANG_VERSION@ -DERLANG_MAJOR=@ERLANG_MAJOR@ -DERLANG_MINOR=@ERLANG_MINOR@
+mod_kazoo_la_LIBADD = $(KAZOO_DEFS) $(switch_builddir)/libfreeswitch.la
mod_kazoo_la_LDFLAGS = -avoid-version -module -no-undefined -shared @ERLANG_LDFLAGS@
+BUILT_SOURCES = $(KAZOO_DEFS)
+
+$(KAZOO_DEFS): kazoo.conf.xml
+
+.S.o: $<
+ @$(CC) $(CFLAGS) -o $@ -c $<
+
+install-exec-am:
+ @install `which epmd` $(DESTDIR)$(bindir)/fs_epmd
+
else
install: error
all: error
diff --git a/src/mod/event_handlers/mod_kazoo/kazoo.conf.xml b/src/mod/event_handlers/mod_kazoo/kazoo.conf.xml
new file mode 100644
index 0000000000..a869420681
--- /dev/null
+++ b/src/mod/event_handlers/mod_kazoo/kazoo.conf.xml
@@ -0,0 +1,1205 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/mod/event_handlers/mod_kazoo/kazoo_api.c b/src/mod/event_handlers/mod_kazoo/kazoo_api.c
new file mode 100644
index 0000000000..b070f86336
--- /dev/null
+++ b/src/mod/event_handlers/mod_kazoo/kazoo_api.c
@@ -0,0 +1,551 @@
+/*
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005-2012, Anthony Minessale II
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ *
+ * The Initial Developer of the Original Code is
+ * Anthony Minessale II
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Karl Anderson
+ * Darren Schreiber
+ *
+ *
+ * mod_kazoo.c -- Socket Controlled Event Handler
+ *
+ */
+#include "mod_kazoo.h"
+
+#define KAZOO_DESC "kazoo information"
+#define KAZOO_SYNTAX " []"
+
+#define API_COMMAND_DISCONNECT 0
+#define API_COMMAND_REMOTE_IP 1
+#define API_COMMAND_STREAMS 2
+#define API_COMMAND_BINDINGS 3
+#define API_COMMAND_OPTION 4
+
+#define API_NODE_OPTION_FRAMING 0
+#define API_NODE_OPTION_LEGACY 1
+#define API_NODE_OPTION_MAX 99
+
+static const char *node_runtime_options[] = {
+ "event-stream-framing",
+ "enable-legacy",
+ NULL
+};
+
+static int api_find_node_option(char *option) {
+ int i;
+ for(i = 0; node_runtime_options[i] != NULL; i++) {
+ if(!strcasecmp(option, node_runtime_options[i])) {
+ return i;
+ }
+ }
+ return API_NODE_OPTION_MAX;
+}
+
+static switch_status_t api_get_node_option(ei_node_t *ei_node, switch_stream_handle_t *stream, char *arg) {
+ int option = api_find_node_option(arg);
+ switch_status_t ret = SWITCH_STATUS_SUCCESS;
+ switch (option) {
+ case API_NODE_OPTION_FRAMING:
+ stream->write_function(stream, "+OK %i", ei_node->event_stream_framing);
+ break;
+
+ case API_NODE_OPTION_LEGACY:
+ stream->write_function(stream, "+OK %s", ei_node->legacy ? "true" : "false");
+ break;
+
+ default:
+ stream->write_function(stream, "-ERR invalid option %s", arg);
+ ret = SWITCH_STATUS_NOTFOUND;
+ break;
+ }
+
+ return ret;
+}
+
+static switch_status_t api_set_node_option(ei_node_t *ei_node, switch_stream_handle_t *stream, char *name, char *value) {
+ int option = api_find_node_option(name);
+ short val;
+ switch_status_t ret = SWITCH_STATUS_SUCCESS;
+ switch (option) {
+ case API_NODE_OPTION_FRAMING:
+ val = atoi(value);
+ if (val != 1 && val != 2 && val != 4) {
+ stream->write_function(stream, "-ERR Invalid event stream framing value (%i)", val);
+ ret = SWITCH_STATUS_GENERR;
+ } else {
+ stream->write_function(stream, "+OK %i", val);
+ ei_node->event_stream_framing = val;
+ }
+ break;
+
+ case API_NODE_OPTION_LEGACY:
+ ei_node->legacy = switch_true(value);
+ stream->write_function(stream, "+OK %s", ei_node->legacy ? "true" : "false");
+ break;
+
+ default:
+ stream->write_function(stream, "-ERR invalid option %s", name);
+ ret = SWITCH_STATUS_NOTFOUND;
+ break;
+ }
+
+ return ret;
+}
+
+static switch_status_t api_erlang_status(switch_stream_handle_t *stream) {
+ switch_sockaddr_t *sa;
+ uint16_t port;
+ char ipbuf[48];
+ const char *ip_addr;
+ ei_node_t *ei_node;
+
+ switch_socket_addr_get(&sa, SWITCH_FALSE, kazoo_globals.acceptor);
+
+ port = switch_sockaddr_get_port(sa);
+ ip_addr = switch_get_addr(ipbuf, sizeof (ipbuf), sa);
+
+ stream->write_function(stream, "Running %s\n", VERSION);
+ stream->write_function(stream, "Listening for new Erlang connections on %s:%u with cookie %s\n", ip_addr, port, kazoo_globals.ei_cookie);
+ stream->write_function(stream, "Registered as Erlang node %s, visible as %s\n", kazoo_globals.ei_cnode.thisnodename, kazoo_globals.ei_cnode.thisalivename);
+
+ if (kazoo_globals.ei_compat_rel) {
+ stream->write_function(stream, "Using Erlang compatibility mode: %d\n", kazoo_globals.ei_compat_rel);
+ }
+
+ switch_thread_rwlock_rdlock(kazoo_globals.ei_nodes_lock);
+ ei_node = kazoo_globals.ei_nodes;
+ if (!ei_node) {
+ stream->write_function(stream, "No erlang nodes connected\n");
+ } else {
+ stream->write_function(stream, "Connected to:\n");
+ while(ei_node != NULL) {
+ unsigned int year, day, hour, min, sec, delta;
+
+ delta = (switch_micro_time_now() - ei_node->created_time) / 1000000;
+ sec = delta % 60;
+ min = delta / 60 % 60;
+ hour = delta / 3600 % 24;
+ day = delta / 86400 % 7;
+ year = delta / 31556926 % 12;
+ stream->write_function(stream, " %s (%s:%d) up %d years, %d days, %d hours, %d minutes, %d seconds\n"
+ ,ei_node->peer_nodename, ei_node->remote_ip, ei_node->remote_port, year, day, hour, min, sec);
+ ei_node = ei_node->next;
+ }
+ }
+ switch_thread_rwlock_unlock(kazoo_globals.ei_nodes_lock);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t api_erlang_event_filter(switch_stream_handle_t *stream) {
+ switch_hash_index_t *hi = NULL;
+ int column = 0;
+ int idx = 0;
+
+ for (hi = (switch_hash_index_t *)switch_core_hash_first_iter(kazoo_globals.event_filter, hi); hi; hi = switch_core_hash_next(&hi)) {
+ const void *key;
+ void *val;
+ switch_core_hash_this(hi, &key, NULL, &val);
+ stream->write_function(stream, "%-50s", (char *)key);
+ if (++column > 2) {
+ stream->write_function(stream, "\n");
+ column = 0;
+ }
+ }
+
+ if (++column > 2) {
+ stream->write_function(stream, "\n");
+ column = 0;
+ }
+
+ while(kazoo_globals.kazoo_var_prefixes[idx] != NULL) {
+ char var[100];
+ char *prefix = kazoo_globals.kazoo_var_prefixes[idx];
+ sprintf(var, "%s*", prefix);
+ stream->write_function(stream, "%-50s", var);
+ idx++;
+ }
+
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t api_erlang_nodes_list(switch_stream_handle_t *stream) {
+ ei_node_t *ei_node;
+
+ switch_thread_rwlock_rdlock(kazoo_globals.ei_nodes_lock);
+ ei_node = kazoo_globals.ei_nodes;
+ while(ei_node != NULL) {
+ stream->write_function(stream, "%s (%s)\n", ei_node->peer_nodename, ei_node->remote_ip);
+ ei_node = ei_node->next;
+ }
+ switch_thread_rwlock_unlock(kazoo_globals.ei_nodes_lock);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t api_erlang_nodes_count(switch_stream_handle_t *stream) {
+ ei_node_t *ei_node;
+ int count = 0;
+
+ switch_thread_rwlock_rdlock(kazoo_globals.ei_nodes_lock);
+ ei_node = kazoo_globals.ei_nodes;
+ while(ei_node != NULL) {
+ count++;
+ ei_node = ei_node->next;
+ }
+ switch_thread_rwlock_unlock(kazoo_globals.ei_nodes_lock);
+
+ stream->write_function(stream, "%d\n", count);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t api_complete_erlang_node(const char *line, const char *cursor, switch_console_callback_match_t **matches) {
+ switch_console_callback_match_t *my_matches = NULL;
+ switch_status_t status = SWITCH_STATUS_FALSE;
+ ei_node_t *ei_node;
+
+ switch_thread_rwlock_rdlock(kazoo_globals.ei_nodes_lock);
+ ei_node = kazoo_globals.ei_nodes;
+ while(ei_node != NULL) {
+ switch_console_push_match(&my_matches, ei_node->peer_nodename);
+ ei_node = ei_node->next;
+ }
+ switch_thread_rwlock_unlock(kazoo_globals.ei_nodes_lock);
+
+ if (my_matches) {
+ *matches = my_matches;
+ status = SWITCH_STATUS_SUCCESS;
+ }
+
+ return status;
+}
+
+static switch_status_t handle_node_api_event_stream(ei_event_stream_t *event_stream, switch_stream_handle_t *stream) {
+ ei_event_binding_t *binding;
+ int column = 0;
+
+ switch_mutex_lock(event_stream->socket_mutex);
+ if (event_stream->connected == SWITCH_FALSE) {
+ switch_sockaddr_t *sa;
+ uint16_t port;
+ char ipbuf[48] = {0};
+ const char *ip_addr;
+
+ switch_socket_addr_get(&sa, SWITCH_TRUE, event_stream->acceptor);
+ port = switch_sockaddr_get_port(sa);
+ ip_addr = switch_get_addr(ipbuf, sizeof (ipbuf), sa);
+
+ if (zstr(ip_addr)) {
+ ip_addr = kazoo_globals.ip;
+ }
+
+ stream->write_function(stream, "%s:%d -> disconnected\n"
+ ,ip_addr, port);
+ } else {
+ stream->write_function(stream, "%s:%d -> %s:%d\n"
+ ,event_stream->local_ip, event_stream->local_port
+ ,event_stream->remote_ip, event_stream->remote_port);
+ }
+
+ binding = event_stream->bindings;
+ while(binding != NULL) {
+ if (binding->type == SWITCH_EVENT_CUSTOM) {
+ stream->write_function(stream, "CUSTOM %-43s", binding->subclass_name);
+ } else {
+ stream->write_function(stream, "%-50s", switch_event_name(binding->type));
+ }
+
+ if (++column > 2) {
+ stream->write_function(stream, "\n");
+ column = 0;
+ }
+
+ binding = binding->next;
+ }
+ switch_mutex_unlock(event_stream->socket_mutex);
+
+ if (!column) {
+ stream->write_function(stream, "\n");
+ } else {
+ stream->write_function(stream, "\n\n");
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t handle_node_api_event_streams(ei_node_t *ei_node, switch_stream_handle_t *stream) {
+ ei_event_stream_t *event_stream;
+
+ switch_mutex_lock(ei_node->event_streams_mutex);
+ event_stream = ei_node->event_streams;
+ while(event_stream != NULL) {
+ handle_node_api_event_stream(event_stream, stream);
+ event_stream = event_stream->next;
+ }
+ switch_mutex_unlock(ei_node->event_streams_mutex);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t handle_node_api_command(ei_node_t *ei_node, switch_stream_handle_t *stream, uint32_t command) {
+ unsigned int year, day, hour, min, sec, delta;
+
+ switch (command) {
+ case API_COMMAND_DISCONNECT:
+ stream->write_function(stream, "Disconnecting erlang node %s at managers request\n", ei_node->peer_nodename);
+ switch_clear_flag(ei_node, LFLAG_RUNNING);
+ break;
+ case API_COMMAND_REMOTE_IP:
+ delta = (switch_micro_time_now() - ei_node->created_time) / 1000000;
+ sec = delta % 60;
+ min = delta / 60 % 60;
+ hour = delta / 3600 % 24;
+ day = delta / 86400 % 7;
+ year = delta / 31556926 % 12;
+
+ stream->write_function(stream, "Uptime %d years, %d days, %d hours, %d minutes, %d seconds\n", year, day, hour, min, sec);
+ stream->write_function(stream, "Local Address %s:%d\n", ei_node->local_ip, ei_node->local_port);
+ stream->write_function(stream, "Remote Address %s:%d\n", ei_node->remote_ip, ei_node->remote_port);
+ break;
+ case API_COMMAND_STREAMS:
+ handle_node_api_event_streams(ei_node, stream);
+ break;
+ case API_COMMAND_BINDINGS:
+ handle_api_command_streams(ei_node, stream);
+ break;
+ default:
+ break;
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t api_erlang_node_command(switch_stream_handle_t *stream, const char *nodename, uint32_t command) {
+ ei_node_t *ei_node;
+
+ switch_thread_rwlock_rdlock(kazoo_globals.ei_nodes_lock);
+ ei_node = kazoo_globals.ei_nodes;
+ while(ei_node != NULL) {
+ int length = strlen(ei_node->peer_nodename);
+
+ if (!strncmp(ei_node->peer_nodename, nodename, length)) {
+ handle_node_api_command(ei_node, stream, command);
+ switch_thread_rwlock_unlock(kazoo_globals.ei_nodes_lock);
+ return SWITCH_STATUS_SUCCESS;
+ }
+
+ ei_node = ei_node->next;
+ }
+ switch_thread_rwlock_unlock(kazoo_globals.ei_nodes_lock);
+
+ return SWITCH_STATUS_NOTFOUND;
+}
+
+static switch_status_t handle_node_api_command_arg(ei_node_t *ei_node, switch_stream_handle_t *stream, uint32_t command, char *arg) {
+
+ switch (command) {
+ case API_COMMAND_OPTION:
+ return api_get_node_option(ei_node, stream, arg);
+ break;
+ default:
+ break;
+ }
+
+ return SWITCH_STATUS_NOTFOUND;
+}
+
+static switch_status_t handle_node_api_command_args(ei_node_t *ei_node, switch_stream_handle_t *stream, uint32_t command, int argc, char *argv[]) {
+
+ switch (command) {
+ case API_COMMAND_OPTION:
+ return api_set_node_option(ei_node, stream, argv[0], argv[1]);
+ break;
+ default:
+ break;
+ }
+
+ return SWITCH_STATUS_NOTFOUND;
+}
+
+static switch_status_t api_erlang_node_command_arg(switch_stream_handle_t *stream, const char *nodename, uint32_t command, char *arg) {
+ ei_node_t *ei_node;
+ switch_status_t ret = SWITCH_STATUS_NOTFOUND;
+
+ switch_thread_rwlock_rdlock(kazoo_globals.ei_nodes_lock);
+ ei_node = kazoo_globals.ei_nodes;
+ while(ei_node != NULL) {
+ int length = strlen(ei_node->peer_nodename);
+
+ if (!strncmp(ei_node->peer_nodename, nodename, length)) {
+ ret = handle_node_api_command_arg(ei_node, stream, command, arg);
+ switch_thread_rwlock_unlock(kazoo_globals.ei_nodes_lock);
+ return ret ;
+ }
+
+ ei_node = ei_node->next;
+ }
+ switch_thread_rwlock_unlock(kazoo_globals.ei_nodes_lock);
+
+ return ret;
+}
+
+static switch_status_t api_erlang_node_command_args(switch_stream_handle_t *stream, const char *nodename, uint32_t command, int argc, char *argv[]) {
+ ei_node_t *ei_node;
+ switch_status_t ret = SWITCH_STATUS_NOTFOUND;
+
+ switch_thread_rwlock_rdlock(kazoo_globals.ei_nodes_lock);
+ ei_node = kazoo_globals.ei_nodes;
+ while(ei_node != NULL) {
+ int length = strlen(ei_node->peer_nodename);
+
+ if (!strncmp(ei_node->peer_nodename, nodename, length)) {
+ ret = handle_node_api_command_args(ei_node, stream, command, argc, argv);
+ switch_thread_rwlock_unlock(kazoo_globals.ei_nodes_lock);
+ return ret;
+ }
+
+ ei_node = ei_node->next;
+ }
+ switch_thread_rwlock_unlock(kazoo_globals.ei_nodes_lock);
+
+ return ret;
+}
+
+SWITCH_STANDARD_API(exec_api_cmd)
+{
+ char *argv[1024] = { 0 };
+ int unknown_command = 1, argc = 0;
+ char *mycmd = NULL;
+
+ const char *usage_string = "USAGE:\n"
+ "--------------------------------------------------------------------------------------------------------------------\n"
+ "erlang status - provides an overview of the current status\n"
+ "erlang event_filter - lists the event headers that will be sent to Erlang nodes\n"
+ "erlang nodes list - lists connected Erlang nodes (usefull for monitoring tools)\n"
+ "erlang nodes count - provides a count of connected Erlang nodes (usefull for monitoring tools)\n"
+ "erlang node disconnect - disconnects an Erlang node\n"
+ "erlang node connection - Shows the connection info\n"
+ "erlang node event_streams - lists the event streams for an Erlang node\n"
+ "erlang node fetch_bindings - lists the XML fetch bindings for an Erlang node\n"
+ "---------------------------------------------------------------------------------------------------------------------\n";
+
+ if (zstr(cmd)) {
+ stream->write_function(stream, "%s", usage_string);
+ return SWITCH_STATUS_SUCCESS;
+ }
+
+ if (!(mycmd = strdup(cmd))) {
+ return SWITCH_STATUS_MEMERR;
+ }
+
+ if (!(argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) {
+ stream->write_function(stream, "%s", usage_string);
+ switch_safe_free(mycmd);
+ return SWITCH_STATUS_SUCCESS;
+ }
+
+ if (zstr(argv[0])) {
+ stream->write_function(stream, "%s", usage_string);
+ switch_safe_free(mycmd);
+ return SWITCH_STATUS_SUCCESS;
+ }
+
+ if (!strncmp(argv[0], "status", 7)) {
+ unknown_command = 0;
+ api_erlang_status(stream);
+ } else if (!strncmp(argv[0], "event_filter", 13)) {
+ unknown_command = 0;
+ api_erlang_event_filter(stream);
+ } else if (!strncmp(argv[0], "nodes", 6) && !zstr(argv[1])) {
+ if (!strncmp(argv[1], "list", 6)) {
+ unknown_command = 0;
+ api_erlang_nodes_list(stream);
+ } else if (!strncmp(argv[1], "count", 6)) {
+ unknown_command = 0;
+ api_erlang_nodes_count(stream);
+ }
+ } else if (!strncmp(argv[0], "node", 6) && !zstr(argv[1]) && !zstr(argv[2])) {
+ if (!strncmp(argv[2], "disconnect", 11)) {
+ unknown_command = 0;
+ api_erlang_node_command(stream, argv[1], API_COMMAND_DISCONNECT);
+ } else if (!strncmp(argv[2], "connection", 11)) {
+ unknown_command = 0;
+ api_erlang_node_command(stream, argv[1], API_COMMAND_REMOTE_IP);
+ } else if (!strncmp(argv[2], "event_streams", 14)) {
+ unknown_command = 0;
+ api_erlang_node_command(stream, argv[1], API_COMMAND_STREAMS);
+ } else if (!strncmp(argv[2], "fetch_bindings", 15)) {
+ unknown_command = 0;
+ api_erlang_node_command(stream, argv[1], API_COMMAND_BINDINGS);
+ } else if (!strncmp(argv[2], "option", 7) && !zstr(argv[3])) {
+ unknown_command = 0;
+ if(argc > 4 && !zstr(argv[4]))
+ api_erlang_node_command_args(stream, argv[1], API_COMMAND_OPTION, argc - 3, &argv[3]);
+ else
+ api_erlang_node_command_arg(stream, argv[1], API_COMMAND_OPTION, argv[3]);
+ }
+ }
+
+ if (unknown_command) {
+ stream->write_function(stream, "%s", usage_string);
+ }
+
+ switch_safe_free(mycmd);
+ return SWITCH_STATUS_SUCCESS;
+}
+
+void add_cli_api(switch_loadable_module_interface_t **module_interface, switch_api_interface_t *api_interface)
+{
+ SWITCH_ADD_API(api_interface, "erlang", KAZOO_DESC, exec_api_cmd, KAZOO_SYNTAX);
+ switch_console_set_complete("add erlang status");
+ switch_console_set_complete("add erlang event_filter");
+ switch_console_set_complete("add erlang nodes list");
+ switch_console_set_complete("add erlang nodes count");
+ switch_console_set_complete("add erlang node ::erlang::node disconnect");
+ switch_console_set_complete("add erlang node ::erlang::node connection");
+ switch_console_set_complete("add erlang node ::erlang::node event_streams");
+ switch_console_set_complete("add erlang node ::erlang::node fetch_bindings");
+ switch_console_add_complete_func("::erlang::node", api_complete_erlang_node);
+
+}
+
+void remove_cli_api()
+{
+ switch_console_set_complete("del erlang");
+ switch_console_del_complete_func("::erlang::node");
+
+}
+
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4:
+ */
diff --git a/src/mod/event_handlers/mod_kazoo/kazoo_commands.c b/src/mod/event_handlers/mod_kazoo/kazoo_commands.c
index 2494bb9495..d61a1054ac 100644
--- a/src/mod/event_handlers/mod_kazoo/kazoo_commands.c
+++ b/src/mod/event_handlers/mod_kazoo/kazoo_commands.c
@@ -31,6 +31,7 @@
*
*/
#include "mod_kazoo.h"
+#include
#include
#define UUID_SET_DESC "Set a variable"
@@ -42,7 +43,146 @@
#define KZ_HTTP_PUT_DESC "upload a local freeswitch file to a url"
#define KZ_HTTP_PUT_SYNTAX "localfile url"
-SWITCH_STANDARD_API(uuid_setvar_function) {
+#define KZ_FIRST_OF_DESC "returns first-of existing event header in params"
+#define KZ_FIRST_OF_SYNTAX "list of headers to check"
+
+#define MAX_FIRST_OF 25
+
+#define MAX_HISTORY 50
+#define HST_ARRAY_DELIM "|:"
+#define HST_ITEM_DELIM ':'
+
+static void process_history_item(char* value, cJSON *json)
+{
+ char *argv[4] = { 0 };
+ char *item = strdup(value);
+ int argc = switch_separate_string(item, HST_ITEM_DELIM, argv, (sizeof(argv) / sizeof(argv[0])));
+ cJSON *jitem = cJSON_CreateObject();
+ char *epoch = NULL, *callid = NULL, *type = NULL;
+ int add = 0;
+ if(argc == 4) {
+ add = 1;
+ epoch = argv[0];
+ callid = argv[1];
+ type = argv[2];
+
+ if(!strncmp(type, "bl_xfer", 7)) {
+ char *split = strchr(argv[3], '/');
+ if(split) *(split++) = '\0';
+ cJSON_AddItemToObject(jitem, "Call-ID", cJSON_CreateString(callid));
+ cJSON_AddItemToObject(jitem, "Type", cJSON_CreateString("blind"));
+ cJSON_AddItemToObject(jitem, "Extension", cJSON_CreateString(argv[3]));
+ } else if(!strncmp(type, "att_xfer", 8)) {
+ char *split = strchr(argv[3], '/');
+ if(split) {
+ *(split++) = '\0';
+ cJSON_AddItemToObject(jitem, "Call-ID", cJSON_CreateString(callid));
+ cJSON_AddItemToObject(jitem, "Type", cJSON_CreateString("attended"));
+ cJSON_AddItemToObject(jitem, "Transferee", cJSON_CreateString(argv[3]));
+ cJSON_AddItemToObject(jitem, "Transferer", cJSON_CreateString(split));
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "TRANSFER TYPE '%s' NOT HANDLED => %s\n", type, item);
+ add = 0;
+ }
+ } else if(!strncmp(type, "uuid_br", 7)) {
+ cJSON_AddItemToObject(jitem, "Call-ID", cJSON_CreateString(callid));
+ cJSON_AddItemToObject(jitem, "Type", cJSON_CreateString("bridge"));
+ cJSON_AddItemToObject(jitem, "Other-Leg", cJSON_CreateString(argv[3]));
+
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "TRANSFER TYPE '%s' NOT HANDLED => %s\n", type, item);
+ add = 0;
+ }
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "TRANSFER TYPE SPLIT ERROR %i => %s\n", argc, item);
+ }
+ if(add) {
+ cJSON_AddItemToObject(json, epoch, jitem);
+ } else {
+ cJSON_Delete(jitem);
+ }
+ switch_safe_free(item);
+}
+
+SWITCH_STANDARD_API(kz_json_history) {
+ char *mycmd = NULL, *argv[MAX_HISTORY] = { 0 };
+ int n, argc = 0;
+ cJSON *json = cJSON_CreateObject();
+ char* output = NULL;
+ switch_event_header_t *header = NULL;
+ if (!zstr(cmd) && (mycmd = strdup(cmd))) {
+ if (!strncmp(mycmd, "ARRAY::", 7)) {
+ mycmd += 7;
+ argc = switch_separate_string_string(mycmd, HST_ARRAY_DELIM, argv, (sizeof(argv) / sizeof(argv[0])));
+ for(n=0; n < argc; n++) {
+ process_history_item(argv[n], json);
+ }
+ } else if (strchr(mycmd, HST_ITEM_DELIM)) {
+ process_history_item(mycmd, json);
+ } else if (stream->param_event) {
+ header = switch_event_get_header_ptr(stream->param_event, mycmd);
+ if (header != NULL) {
+ if(header->idx) {
+ for(n = 0; n < header->idx; n++) {
+ process_history_item(header->array[n], json);
+ }
+ } else {
+ process_history_item(header->value, json);
+ }
+
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "TRANSFER HISTORY HEADER NOT FOUND => %s\n", mycmd);
+ }
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "TRANSFER HISTORY NOT PARSED => %s\n", mycmd);
+ }
+ }
+ output = cJSON_PrintUnformatted(json);
+ stream->write_function(stream, "%s", output);
+ switch_safe_free(output);
+ cJSON_Delete(json);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+SWITCH_STANDARD_API(kz_first_of) {
+ char delim = '|';
+ char *mycmd = NULL, *argv[MAX_FIRST_OF] = { 0 };
+ int n, argc = 0;
+ switch_event_header_t *header = NULL;
+ if (!zstr(cmd) && (mycmd = strdup(cmd))) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "FIRST-OF %s\n", mycmd);
+ if (!zstr(mycmd) && *mycmd == '^' && *(mycmd+1) == '^') {
+ mycmd += 2;
+ delim = *mycmd++;
+ }
+ argc = switch_separate_string(mycmd, delim, argv, (sizeof(argv) / sizeof(argv[0])));
+ for(n=0; n < argc; n++) {
+ char* item = argv[n];
+ if(*item == '#') {
+ if(*(++item) != '\0') {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "RETURNING default %s\n", item);
+ stream->write_function(stream, item);
+ break;
+ }
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "CHECKING %s\n", item);
+ header = switch_event_get_header_ptr(stream->param_event, item);
+ if(header) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "RETURNING %s : %s\n", item, header->value);
+ stream->write_function(stream, header->value);
+ break;
+ }
+ }
+ }
+ }
+
+ switch_safe_free(mycmd);
+ return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t kz_uuid_setvar(int urldecode, const char *cmd, switch_core_session_t *session, switch_stream_handle_t *stream)
+{
switch_core_session_t *psession = NULL;
char *mycmd = NULL, *argv[3] = { 0 };
int argc = 0;
@@ -67,7 +207,11 @@ SWITCH_STANDARD_API(uuid_setvar_function) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No variable name specified.\n");
stream->write_function(stream, "-ERR No variable specified\n");
} else {
+ if(urldecode) {
+ switch_url_decode(var_value);
+ }
switch_channel_set_variable(channel, var_name, var_value);
+ kz_check_set_profile_var(channel, var_name, var_value);
stream->write_function(stream, "+OK\n");
}
@@ -92,8 +236,20 @@ SWITCH_STANDARD_API(uuid_setvar_function) {
return SWITCH_STATUS_SUCCESS;
}
-SWITCH_STANDARD_API(uuid_setvar_multi_function) {
+SWITCH_STANDARD_API(uuid_setvar_function)
+{
+ return kz_uuid_setvar(0, cmd, session, stream);
+}
+
+SWITCH_STANDARD_API(uuid_setvar_encoded_function)
+{
+ return kz_uuid_setvar(1, cmd, session, stream);
+}
+
+switch_status_t kz_uuid_setvar_multi(int urldecode, const char *cmd, switch_core_session_t *session, switch_stream_handle_t *stream)
+{
switch_core_session_t *psession = NULL;
+ char delim = ';';
char *mycmd = NULL, *vars, *argv[64] = { 0 };
int argc = 0;
char *var_name, *var_value = NULL;
@@ -104,12 +260,15 @@ SWITCH_STANDARD_API(uuid_setvar_multi_function) {
goto done;
}
*vars++ = '\0';
-
+ if (*vars == '^' && *(vars+1) == '^') {
+ vars += 2;
+ delim = *vars++;
+ }
if ((psession = switch_core_session_locate(uuid))) {
switch_channel_t *channel = switch_core_session_get_channel(psession);
switch_event_t *event;
int x, y = 0;
- argc = switch_separate_string(vars, ';', argv, (sizeof(argv) / sizeof(argv[0])));
+ argc = switch_separate_string(vars, delim, argv, (sizeof(argv) / sizeof(argv[0])));
for (x = 0; x < argc; x++) {
var_name = argv[x];
@@ -120,16 +279,11 @@ SWITCH_STANDARD_API(uuid_setvar_multi_function) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No variable name specified.\n");
stream->write_function(stream, "-ERR No variable specified\n");
} else {
+ if(urldecode) {
+ switch_url_decode(var_value);
+ }
switch_channel_set_variable(channel, var_name, var_value);
- if (!strcasecmp(var_name, "effective_callee_id_number")) {
- switch_channel_set_profile_var(channel, "callee_id_number", var_value);
- } else if (!strcasecmp(var_name, "effective_callee_id_name")) {
- switch_channel_set_profile_var(channel, "callee_id_name", var_value);
- } else if (!strcasecmp(var_name, "effective_caller_id_number")) {
- switch_channel_set_profile_var(channel, "caller_id_number", var_value);
- } else if (!strcasecmp(var_name, "effective_caller_id_name")) {
- switch_channel_set_profile_var(channel, "caller_id_name", var_value);
- };
+ kz_check_set_profile_var(channel, var_name, var_value);
y++;
}
@@ -158,6 +312,21 @@ SWITCH_STANDARD_API(uuid_setvar_multi_function) {
return SWITCH_STATUS_SUCCESS;
}
+SWITCH_STANDARD_API(uuid_setvar_multi_function)
+{
+ return kz_uuid_setvar_multi(0, cmd, session, stream);
+}
+
+SWITCH_STANDARD_API(uuid_setvar_multi_encoded_function)
+{
+ return kz_uuid_setvar_multi(1, cmd, session, stream);
+}
+
+static size_t body_callback(char *buffer, size_t size, size_t nitems, void *userdata)
+{
+ return size * nitems;
+}
+
static size_t header_callback(char *buffer, size_t size, size_t nitems, void *userdata)
{
switch_event_t* event = (switch_event_t*)userdata;
@@ -182,6 +351,7 @@ SWITCH_STANDARD_API(kz_http_put)
switch_event_t *params = NULL;
char *url = NULL;
char *filename = NULL;
+ int delete_file = 0;
switch_curl_slist_t *headers = NULL; /* optional linked-list of HTTP headers */
char *ext; /* file extension, used for MIME type identification */
@@ -276,9 +446,12 @@ SWITCH_STANDARD_API(kz_http_put)
switch_curl_easy_setopt(curl_handle, CURLOPT_INFILESIZE_LARGE, (curl_off_t)file_info.st_size);
switch_curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1);
switch_curl_easy_setopt(curl_handle, CURLOPT_MAXREDIRS, 10);
- switch_curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "freeswitch-http-cache/1.0");
+ switch_curl_easy_setopt(curl_handle, CURLOPT_FAILONERROR, 1);
+ switch_curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "freeswitch-kazoo/1.0");
switch_curl_easy_setopt(curl_handle, CURLOPT_HEADERDATA, stream->param_event);
switch_curl_easy_setopt(curl_handle, CURLOPT_HEADERFUNCTION, header_callback);
+ switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, body_callback);
+
switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0L);
switch_curl_easy_perform(curl_handle);
switch_curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &httpRes);
@@ -286,22 +459,24 @@ SWITCH_STANDARD_API(kz_http_put)
if (httpRes == 200 || httpRes == 201 || httpRes == 202 || httpRes == 204) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s saved to %s\n", filename, url);
- switch_event_add_header(stream->param_event, SWITCH_STACK_BOTTOM, "API-Output", "%s saved to %s\n", filename, url);
- stream->write_function(stream, "+OK\n");
+ switch_event_add_header(stream->param_event, SWITCH_STACK_BOTTOM, "API-Output", "%s saved to %s", filename, url);
+ stream->write_function(stream, "+OK %s saved to %s", filename, url);
+ delete_file = 1;
} else {
error = switch_mprintf("Received HTTP error %ld trying to save %s to %s", httpRes, filename, url);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s\n", error);
switch_event_add_header(stream->param_event, SWITCH_STACK_BOTTOM, "API-Error", "%s", error);
switch_event_add_header(stream->param_event, SWITCH_STACK_BOTTOM, "API-HTTP-Error", "%ld", httpRes);
- stream->write_function(stream, "-ERR ");
- stream->write_function(stream, error);
- stream->write_function(stream, "\n");
+ stream->write_function(stream, "-ERR %s", error);
status = SWITCH_STATUS_GENERR;
}
done:
if (file_to_put) {
fclose(file_to_put);
+ if(delete_file) {
+ remove(filename);
+ }
}
if (headers) {
@@ -326,9 +501,15 @@ done:
void add_kz_commands(switch_loadable_module_interface_t **module_interface, switch_api_interface_t *api_interface) {
SWITCH_ADD_API(api_interface, "kz_uuid_setvar_multi", UUID_SET_DESC, uuid_setvar_multi_function, UUID_MULTISET_SYNTAX);
+ SWITCH_ADD_API(api_interface, "kz_uuid_setvar_multi_encoded", UUID_SET_DESC, uuid_setvar_multi_encoded_function, UUID_MULTISET_SYNTAX);
switch_console_set_complete("add kz_uuid_setvar_multi ::console::list_uuid");
+ switch_console_set_complete("add kz_uuid_setvar_multi_encoded ::console::list_uuid");
SWITCH_ADD_API(api_interface, "kz_uuid_setvar", UUID_MULTISET_DESC, uuid_setvar_function, UUID_SET_SYNTAX);
+ SWITCH_ADD_API(api_interface, "kz_uuid_setvar_encoded", UUID_MULTISET_DESC, uuid_setvar_encoded_function, UUID_SET_SYNTAX);
switch_console_set_complete("add kz_uuid_setvar ::console::list_uuid");
+ switch_console_set_complete("add kz_uuid_setvar_encoded ::console::list_uuid");
SWITCH_ADD_API(api_interface, "kz_http_put", KZ_HTTP_PUT_DESC, kz_http_put, KZ_HTTP_PUT_SYNTAX);
+ SWITCH_ADD_API(api_interface, "first-of", KZ_FIRST_OF_DESC, kz_first_of, KZ_FIRST_OF_SYNTAX);
+ SWITCH_ADD_API(api_interface, "kz_json_history", KZ_FIRST_OF_DESC, kz_json_history, KZ_FIRST_OF_SYNTAX);
}
diff --git a/src/mod/event_handlers/mod_kazoo/kazoo_config.c b/src/mod/event_handlers/mod_kazoo/kazoo_config.c
new file mode 100644
index 0000000000..fcda9012ff
--- /dev/null
+++ b/src/mod/event_handlers/mod_kazoo/kazoo_config.c
@@ -0,0 +1,536 @@
+/*
+* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+* Copyright (C) 2005-2012, Anthony Minessale II
+*
+* Version: MPL 1.1
+*
+* The contents of this file are subject to the Mozilla Public License Version
+* 1.1 (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+* http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS IS" basis,
+* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+* for the specific language governing rights and limitations under the
+* License.
+*
+* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+*
+* The Initial Developer of the Original Code is
+* Anthony Minessale II
+* Portions created by the Initial Developer are Copyright (C)
+* the Initial Developer. All Rights Reserved.
+*
+* Based on mod_skel by
+* Anthony Minessale II
+*
+* Contributor(s):
+*
+* Daniel Bryars
+* Tim Brown
+* Anthony Minessale II
+* William King
+* Mike Jerris
+*
+* kazoo.c -- Sends FreeSWITCH events to an AMQP broker
+*
+*/
+
+#include "mod_kazoo.h"
+
+static const char *LOG_LEVEL_NAMES[] = {
+ "SWITCH_LOG_DEBUG10",
+ "SWITCH_LOG_DEBUG9",
+ "SWITCH_LOG_DEBUG8",
+ "SWITCH_LOG_DEBUG7",
+ "SWITCH_LOG_DEBUG6",
+ "SWITCH_LOG_DEBUG5",
+ "SWITCH_LOG_DEBUG4",
+ "SWITCH_LOG_DEBUG3",
+ "SWITCH_LOG_DEBUG2",
+ "SWITCH_LOG_DEBUG1",
+ "SWITCH_LOG_DEBUG",
+ "SWITCH_LOG_INFO",
+ "SWITCH_LOG_NOTICE",
+ "SWITCH_LOG_WARNING",
+ "SWITCH_LOG_ERROR",
+ "SWITCH_LOG_CRIT",
+ "SWITCH_LOG_ALERT",
+ "SWITCH_LOG_CONSOLE",
+ "SWITCH_LOG_INVALID",
+ "SWITCH_LOG_UNINIT",
+ NULL
+};
+
+static const switch_log_level_t LOG_LEVEL_VALUES[] = {
+ SWITCH_LOG_DEBUG10,
+ SWITCH_LOG_DEBUG9,
+ SWITCH_LOG_DEBUG8,
+ SWITCH_LOG_DEBUG7,
+ SWITCH_LOG_DEBUG6,
+ SWITCH_LOG_DEBUG5,
+ SWITCH_LOG_DEBUG4,
+ SWITCH_LOG_DEBUG3,
+ SWITCH_LOG_DEBUG2,
+ SWITCH_LOG_DEBUG1,
+ SWITCH_LOG_DEBUG,
+ SWITCH_LOG_INFO,
+ SWITCH_LOG_NOTICE,
+ SWITCH_LOG_WARNING,
+ SWITCH_LOG_ERROR,
+ SWITCH_LOG_CRIT,
+ SWITCH_LOG_ALERT,
+ SWITCH_LOG_CONSOLE,
+ SWITCH_LOG_INVALID,
+ SWITCH_LOG_UNINIT
+};
+
+switch_log_level_t log_str2level(const char *str)
+{
+ int x = 0;
+ switch_log_level_t level = SWITCH_LOG_INVALID;
+
+ if (switch_is_number(str)) {
+ x = atoi(str);
+
+ if (x > SWITCH_LOG_INVALID) {
+ return SWITCH_LOG_INVALID - 1;
+ } else if (x < 0) {
+ return 0;
+ } else {
+ return x;
+ }
+ }
+
+
+ for (x = 0;; x++) {
+ if (!LOG_LEVEL_NAMES[x]) {
+ break;
+ }
+
+ if (!strcasecmp(LOG_LEVEL_NAMES[x], str)) {
+ level = LOG_LEVEL_VALUES[x]; //(switch_log_level_t) x;
+ break;
+ }
+ }
+
+ return level;
+}
+
+switch_status_t kazoo_config_loglevels(switch_memory_pool_t *pool, switch_xml_t cfg, kazoo_loglevels_ptr *ptr)
+{
+ switch_xml_t xml_level, xml_logging;
+ kazoo_loglevels_ptr loglevels = (kazoo_loglevels_ptr) switch_core_alloc(pool, sizeof(kazoo_loglevels_t));
+
+ loglevels->failed_log_level = SWITCH_LOG_ALERT;
+ loglevels->filtered_event_log_level = SWITCH_LOG_DEBUG1;
+ loglevels->filtered_field_log_level = SWITCH_LOG_DEBUG1;
+ loglevels->info_log_level = SWITCH_LOG_INFO;
+ loglevels->warn_log_level = SWITCH_LOG_WARNING;
+ loglevels->success_log_level = SWITCH_LOG_DEBUG;
+ loglevels->time_log_level = SWITCH_LOG_DEBUG1;
+
+ if ((xml_logging = switch_xml_child(cfg, "logging")) != NULL) {
+ for (xml_level = switch_xml_child(xml_logging, "log"); xml_level; xml_level = xml_level->next) {
+ char *var = (char *) switch_xml_attr_soft(xml_level, "name");
+ char *val = (char *) switch_xml_attr_soft(xml_level, "value");
+
+ if (!var) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "logging param missing 'name' attribute\n");
+ continue;
+ }
+
+ if (!val) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "logging param[%s] missing 'value' attribute\n", var);
+ continue;
+ }
+
+ if (!strncmp(var, "success", 7)) {
+ loglevels->success_log_level = log_str2level(val);
+ } else if (!strncmp(var, "failed", 6)) {
+ loglevels->failed_log_level = log_str2level(val);
+ } else if (!strncmp(var, "info", 4)) {
+ loglevels->info_log_level = log_str2level(val);
+ } else if (!strncmp(var, "warn", 4)) {
+ loglevels->warn_log_level = log_str2level(val);
+ } else if (!strncmp(var, "time", 4)) {
+ loglevels->time_log_level = log_str2level(val);
+ } else if (!strncmp(var, "filtered-event", 14)) {
+ loglevels->filtered_event_log_level = log_str2level(val);
+ } else if (!strncmp(var, "filtered-field", 14)) {
+ loglevels->filtered_field_log_level = log_str2level(val);
+ }
+ } /* xml_level for loop */
+ }
+
+ *ptr = loglevels;
+ return SWITCH_STATUS_SUCCESS;
+
+}
+
+switch_status_t kazoo_config_filters(switch_memory_pool_t *pool, switch_xml_t cfg, kazoo_filter_ptr *ptr)
+{
+ switch_xml_t filters, filter;
+// char *routing_key = NULL;
+ kazoo_filter_ptr root = NULL, prv = NULL, cur = NULL;
+
+
+ if ((filters = switch_xml_child(cfg, "filters")) != NULL) {
+ for (filter = switch_xml_child(filters, "filter"); filter; filter = filter->next) {
+ const char *var = switch_xml_attr(filter, "name");
+ const char *val = switch_xml_attr(filter, "value");
+ const char *type = switch_xml_attr(filter, "type");
+ const char *compare = switch_xml_attr(filter, "compare");
+ cur = (kazoo_filter_ptr) switch_core_alloc(pool, sizeof(kazoo_filter));
+ memset(cur, 0, sizeof(kazoo_filter));
+ if(prv == NULL) {
+ root = prv = cur;
+ } else {
+ prv->next = cur;
+ prv = cur;
+ }
+ cur->type = FILTER_EXCLUDE;
+ cur->compare = FILTER_COMPARE_VALUE;
+
+ if(var)
+ cur->name = switch_core_strdup(pool, var);
+
+ if(val)
+ cur->value = switch_core_strdup(pool, val);
+
+ if(type) {
+ if (!strncmp(type, "exclude", 7)) {
+ cur->type = FILTER_EXCLUDE;
+ } else if (!strncmp(type, "include", 7)) {
+ cur->type = FILTER_INCLUDE;
+ }
+ }
+
+ if(compare) {
+ if (!strncmp(compare, "value", 7)) {
+ cur->compare = FILTER_COMPARE_VALUE;
+ } else if (!strncmp(compare, "prefix", 6)) {
+ cur->compare = FILTER_COMPARE_PREFIX;
+ } else if (!strncmp(compare, "list", 4)) {
+ cur->compare = FILTER_COMPARE_LIST;
+ } else if (!strncmp(compare, "exists", 6)) {
+ cur->compare = FILTER_COMPARE_EXISTS;
+ } else if (!strncmp(compare, "regex", 5)) {
+ cur->compare = FILTER_COMPARE_REGEX;
+ } else if (!strncmp(compare, "field", 5)) {
+ cur->compare = FILTER_COMPARE_FIELD;
+ }
+ }
+
+ if(cur->value == NULL)
+ cur->compare = FILTER_COMPARE_EXISTS;
+
+ if(cur->compare == FILTER_COMPARE_LIST) {
+ cur->list.size = switch_separate_string(cur->value, '|', cur->list.value, MAX_LIST_FIELDS);
+ }
+
+ }
+
+ }
+
+ *ptr = root;
+
+ return SWITCH_STATUS_SUCCESS;
+
+}
+
+switch_status_t kazoo_config_field(kazoo_config_ptr definitions, switch_memory_pool_t *pool, switch_xml_t cfg, kazoo_field_ptr *ptr)
+{
+ const char *var = switch_xml_attr(cfg, "name");
+ const char *val = switch_xml_attr(cfg, "value");
+ const char *as = switch_xml_attr(cfg, "as");
+ const char *type = switch_xml_attr(cfg, "type");
+ const char *exclude_prefix = switch_xml_attr(cfg, "exclude-prefix");
+ const char *serialize_as = switch_xml_attr(cfg, "serialize-as");
+ kazoo_field_ptr cur = (kazoo_field_ptr) switch_core_alloc(pool, sizeof(kazoo_field));
+ cur->in_type = FIELD_NONE;
+ cur->out_type = JSON_NONE;
+
+ if(var)
+ cur->name = switch_core_strdup(pool, var);
+
+ if(val)
+ cur->value = switch_core_strdup(pool, val);
+
+ if(as)
+ cur->as = switch_core_strdup(pool, as);
+
+ if(type) {
+ if (!strncmp(type, "copy", 4)) {
+ cur->in_type = FIELD_COPY;
+ } else if (!strncmp(type, "static", 6)) {
+ cur->in_type = FIELD_STATIC;
+ } else if (!strncmp(type, "first-of", 8)) {
+ cur->in_type = FIELD_FIRST_OF;
+ } else if (!strncmp(type, "expand", 6)) {
+ cur->in_type = FIELD_EXPAND;
+ } else if (!strncmp(type, "prefix", 10)) {
+ cur->in_type = FIELD_PREFIX;
+ } else if (!strncmp(type, "group", 5)) {
+ cur->in_type = FIELD_GROUP;
+ } else if (!strncmp(type, "reference", 9)) {
+ cur->in_type = FIELD_REFERENCE;
+ }
+ }
+
+ if(serialize_as) {
+ if (!strncmp(serialize_as, "string", 5)) {
+ cur->out_type = JSON_STRING;
+ } else if (!strncmp(serialize_as, "number", 6)) {
+ cur->out_type = JSON_NUMBER;
+ } else if (!strncmp(serialize_as, "boolean", 7)) {
+ cur->out_type = JSON_BOOLEAN;
+ } else if (!strncmp(serialize_as, "object", 6)) {
+ cur->out_type = JSON_OBJECT;
+ } else if (!strncmp(serialize_as, "raw", 6)) {
+ cur->out_type = JSON_RAW;
+ }
+ }
+
+ if(exclude_prefix)
+ cur->exclude_prefix = switch_true(exclude_prefix);
+
+ kazoo_config_filters(pool, cfg, &cur->filter);
+ kazoo_config_fields(definitions, pool, cfg, &cur->children);
+
+ if(cur->children != NULL
+ && (cur->in_type == FIELD_STATIC)
+ && (cur->out_type == JSON_NONE)
+ ) {
+ cur->out_type = JSON_OBJECT;
+ }
+ if(cur->in_type == FIELD_NONE) {
+ cur->in_type = FIELD_COPY;
+ }
+
+ if(cur->out_type == JSON_NONE) {
+ cur->out_type = JSON_STRING;
+ }
+
+ if(cur->in_type == FIELD_FIRST_OF) {
+ cur->list.size = switch_separate_string(cur->value, '|', cur->list.value, MAX_LIST_FIELDS);
+ }
+
+ if(cur->in_type == FIELD_REFERENCE) {
+ cur->ref = (kazoo_definition_ptr)switch_core_hash_find(definitions->hash, cur->name);
+ if(cur->ref == NULL) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "referenced field %s not found\n", cur->name);
+ }
+ }
+
+ *ptr = cur;
+
+ return SWITCH_STATUS_SUCCESS;
+
+}
+
+switch_status_t kazoo_config_fields_loop(kazoo_config_ptr definitions, switch_memory_pool_t *pool, switch_xml_t cfg, kazoo_field_ptr *ptr)
+{
+ switch_xml_t field;
+ kazoo_field_ptr root = NULL, prv = NULL;
+
+
+ for (field = switch_xml_child(cfg, "field"); field; field = field->next) {
+ kazoo_field_ptr cur = NULL;
+ kazoo_config_field(definitions, pool, field, &cur);
+ if(root == NULL) {
+ root = prv = cur;
+ } else {
+ prv->next = cur;
+ prv = cur;
+ }
+ }
+
+ *ptr = root;
+
+ return SWITCH_STATUS_SUCCESS;
+
+}
+
+switch_status_t kazoo_config_fields(kazoo_config_ptr definitions, switch_memory_pool_t *pool, switch_xml_t cfg, kazoo_fields_ptr *ptr)
+{
+ switch_xml_t fields;
+ kazoo_fields_ptr root = NULL;
+
+
+ if ((fields = switch_xml_child(cfg, "fields")) != NULL) {
+ const char *verbose = switch_xml_attr(fields, "verbose");
+ root = (kazoo_fields_ptr) switch_core_alloc(pool, sizeof(kazoo_fields));
+ root->verbose = SWITCH_TRUE;
+ if(verbose) {
+ root->verbose = switch_true(verbose);
+ }
+
+ kazoo_config_fields_loop(definitions, pool, fields, &root->head);
+
+ }
+
+ *ptr = root;
+
+ return SWITCH_STATUS_SUCCESS;
+
+}
+
+kazoo_config_ptr kazoo_config_event_handlers(kazoo_config_ptr definitions, switch_xml_t cfg)
+{
+ switch_xml_t xml_profiles = NULL, xml_profile = NULL;
+ kazoo_config_ptr profiles = NULL;
+ switch_memory_pool_t *pool = NULL;
+
+ if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "error creating memory pool for producers\n");
+ return NULL;
+ }
+
+ profiles = switch_core_alloc(pool, sizeof(kazoo_config));
+ profiles->pool = pool;
+ switch_core_hash_init(&profiles->hash);
+
+ if ((xml_profiles = switch_xml_child(cfg, "event-handlers"))) {
+ if ((xml_profile = switch_xml_child(xml_profiles, "profile"))) {
+ for (; xml_profile; xml_profile = xml_profile->next) {
+ const char *name = switch_xml_attr(xml_profile, "name");
+ if(name == NULL) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "missing attr name\n" );
+ continue;
+ }
+ kazoo_config_event_handler(definitions, profiles, xml_profile, NULL);
+ }
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "unable to locate a event-handler profile for kazoo\n" );
+ }
+ } else {
+ destroy_config(&profiles);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "unable to locate event-handlers section for kazoo, using default\n" );
+ }
+
+ return profiles;
+
+}
+
+kazoo_config_ptr kazoo_config_fetch_handlers(kazoo_config_ptr definitions, switch_xml_t cfg)
+{
+ switch_xml_t xml_profiles = NULL, xml_profile = NULL;
+ kazoo_config_ptr profiles = NULL;
+ switch_memory_pool_t *pool = NULL;
+
+ if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "error creating memory pool for producers\n");
+ return NULL;
+ }
+
+ profiles = switch_core_alloc(pool, sizeof(kazoo_config));
+ profiles->pool = pool;
+ switch_core_hash_init(&profiles->hash);
+
+ if ((xml_profiles = switch_xml_child(cfg, "fetch-handlers"))) {
+ if ((xml_profile = switch_xml_child(xml_profiles, "profile"))) {
+ for (; xml_profile; xml_profile = xml_profile->next) {
+ const char *name = switch_xml_attr(xml_profile, "name");
+ if(name == NULL) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "missing attr name\n" );
+ continue;
+ }
+ kazoo_config_fetch_handler(definitions, profiles, xml_profile, NULL);
+ }
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "unable to locate a fetch-handler profile for kazoo\n" );
+ }
+ } else {
+ destroy_config(&profiles);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "unable to locate fetch-handlers section for kazoo, using default\n" );
+ }
+
+ return profiles;
+
+}
+
+
+switch_status_t kazoo_config_definition(kazoo_config_ptr root, switch_xml_t cfg)
+{
+ kazoo_definition_ptr definition = NULL;
+ char *name = (char *) switch_xml_attr_soft(cfg, "name");
+
+ if (zstr(name)) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to load kazoo profile, check definition missing name attr\n");
+ return SWITCH_STATUS_GENERR;
+ }
+
+ definition = switch_core_alloc(root->pool, sizeof(kazoo_definition));
+ definition->name = switch_core_strdup(root->pool, name);
+
+ kazoo_config_filters(root->pool, cfg, &definition->filter);
+ kazoo_config_fields_loop(root, root->pool, cfg, &definition->head);
+
+ if ( switch_core_hash_insert(root->hash, name, (void *) definition) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to insert new definition [%s] into kazoo definitions hash\n", name);
+ return SWITCH_STATUS_GENERR;
+ }
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "definition[%s] successfully configured\n", definition->name);
+ return SWITCH_STATUS_SUCCESS;
+}
+
+kazoo_config_ptr kazoo_config_definitions(switch_xml_t cfg)
+{
+ switch_xml_t xml_definitions = NULL, xml_definition = NULL;
+ kazoo_config_ptr definitions = NULL;
+ switch_memory_pool_t *pool = NULL;
+
+ if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "error creating memory pool for definitions\n");
+ return NULL;
+ }
+
+ definitions = switch_core_alloc(pool, sizeof(kazoo_config));
+ definitions->pool = pool;
+ switch_core_hash_init(&definitions->hash);
+
+ if ((xml_definitions = switch_xml_child(cfg, "definitions"))) {
+ if ((xml_definition = switch_xml_child(xml_definitions, "definition"))) {
+ for (; xml_definition; xml_definition = xml_definition->next) {
+ kazoo_config_definition(definitions, xml_definition);
+ }
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "no definitions for kazoo\n" );
+ }
+ } else {
+ destroy_config(&definitions);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "unable to locate definitions section for kazoo, using default\n" );
+ }
+
+ return definitions;
+}
+
+void destroy_config(kazoo_config_ptr *ptr)
+{
+ kazoo_config_ptr config = NULL;
+ switch_memory_pool_t *pool;
+
+ if (!ptr || !*ptr) {
+ return;
+ }
+ config = *ptr;
+ pool = config->pool;
+
+ switch_core_hash_destroy(&(config->hash));
+ switch_core_destroy_memory_pool(&pool);
+
+ *ptr = NULL;
+}
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4
+ */
diff --git a/src/mod/event_handlers/mod_kazoo/kazoo_config.h b/src/mod/event_handlers/mod_kazoo/kazoo_config.h
new file mode 100644
index 0000000000..d0117fda5f
--- /dev/null
+++ b/src/mod/event_handlers/mod_kazoo/kazoo_config.h
@@ -0,0 +1,63 @@
+/*
+* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+* Copyright (C) 2005-2012, Anthony Minessale II
+*
+* Version: MPL 1.1
+*
+* The contents of this file are subject to the Mozilla Public License Version
+* 1.1 (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+* http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS IS" basis,
+* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+* for the specific language governing rights and limitations under the
+* License.
+*
+* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+*
+* The Initial Developer of the Original Code is
+* Anthony Minessale II
+* Portions created by the Initial Developer are Copyright (C)
+* the Initial Developer. All Rights Reserved.
+*
+* Based on mod_skel by
+* Anthony Minessale II
+*
+* Contributor(s):
+*
+* Daniel Bryars
+* Tim Brown
+* Anthony Minessale II
+* William King
+* Mike Jerris
+*
+* kazoo.c -- Sends FreeSWITCH events to an AMQP broker
+*
+*/
+
+#ifndef KAZOO_CONFIG_H
+#define KAZOO_CONFIG_H
+
+#include
+
+
+struct kazoo_config_t {
+ switch_hash_t *hash;
+ switch_memory_pool_t *pool;
+};
+
+switch_status_t kazoo_config_loglevels(switch_memory_pool_t *pool, switch_xml_t cfg, kazoo_loglevels_ptr *ptr);
+switch_status_t kazoo_config_filters(switch_memory_pool_t *pool, switch_xml_t cfg, kazoo_filter_ptr *ptr);
+switch_status_t kazoo_config_fields(kazoo_config_ptr definitions, switch_memory_pool_t *pool, switch_xml_t cfg, kazoo_fields_ptr *ptr);
+
+switch_status_t kazoo_config_event_handler(kazoo_config_ptr definitions, kazoo_config_ptr root, switch_xml_t cfg, kazoo_event_profile_ptr *ptr);
+switch_status_t kazoo_config_fetch_handler(kazoo_config_ptr definitions, kazoo_config_ptr root, switch_xml_t cfg, kazoo_fetch_profile_ptr *ptr);
+kazoo_config_ptr kazoo_config_event_handlers(kazoo_config_ptr definitions, switch_xml_t cfg);
+kazoo_config_ptr kazoo_config_fetch_handlers(kazoo_config_ptr definitions, switch_xml_t cfg);
+kazoo_config_ptr kazoo_config_definitions(switch_xml_t cfg);
+switch_status_t kazoo_config_field(kazoo_config_ptr definitions, switch_memory_pool_t *pool, switch_xml_t cfg, kazoo_field_ptr *ptr);
+void destroy_config(kazoo_config_ptr *ptr);
+
+#endif /* KAZOO_CONFIG_H */
+
diff --git a/src/mod/event_handlers/mod_kazoo/kazoo_definitions.S b/src/mod/event_handlers/mod_kazoo/kazoo_definitions.S
new file mode 100644
index 0000000000..0bbe0137cb
--- /dev/null
+++ b/src/mod/event_handlers/mod_kazoo/kazoo_definitions.S
@@ -0,0 +1,8 @@
+ .global kz_default_config
+ .global kz_default_config_size
+ .section .rodata
+kz_default_config:
+ .incbin "kazoo.conf.xml"
+1:
+kz_default_config_size:
+ .int 1b - kz_default_config
diff --git a/src/mod/event_handlers/mod_kazoo/kazoo_dptools.c b/src/mod/event_handlers/mod_kazoo/kazoo_dptools.c
index 0ea4cf6f2c..72e2afa18f 100644
--- a/src/mod/event_handlers/mod_kazoo/kazoo_dptools.c
+++ b/src/mod/event_handlers/mod_kazoo/kazoo_dptools.c
@@ -52,7 +52,24 @@
#define EXPORT_LONG_DESC "Export many channel variables for the channel calling the application"
#define EXPORT_SYNTAX "[^^]= ="
-static void base_set (switch_core_session_t *session, const char *data, switch_stack_t stack) {
+#define PREFIX_UNSET_SHORT_DESC "clear variables by prefix"
+#define PREFIX_UNSET_LONG_DESC "clears the channel variables that start with prefix supplied"
+#define PREFIX_UNSET_SYNTAX ""
+
+#define UUID_MULTISET_SHORT_DESC "Set many channel variables"
+#define UUID_MULTISET_LONG_DESC "Set many channel variables for a specific channel"
+#define UUID_MULTISET_SYNTAX " [^^]= ="
+
+#define KZ_ENDLESS_PLAYBACK_SHORT_DESC "Playback File Endlessly until break"
+#define KZ_ENDLESS_PLAYBACK_LONG_DESC "Endlessly Playback a file to the channel until a break occurs"
+#define KZ_ENDLESS_PLAYBACK_SYNTAX ""
+
+#define NOOP_SHORT_DESC "no operation"
+#define NOOP_LONG_DESC "no operation. serves as a control point"
+#define NOOP_SYNTAX "[]"
+
+static void base_set (switch_core_session_t *session, const char *data, int urldecode, switch_stack_t stack)
+{
char *var, *val = NULL;
if (zstr(data)) {
@@ -75,31 +92,40 @@ static void base_set (switch_core_session_t *session, const char *data, switch_s
}
if (val) {
+ if(urldecode) {
+ switch_url_decode(val);
+ }
expanded = switch_channel_expand_variables(channel, val);
}
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s SET [%s]=[%s]\n", switch_channel_get_name(channel), var,
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s SET [%s]=[%s] => [%s]\n", switch_channel_get_name(channel), var, val,
expanded ? expanded : "UNDEF");
switch_channel_add_variable_var_check(channel, var, expanded, SWITCH_FALSE, stack);
-
- if (!strcasecmp(var, "effective_callee_id_number")) {
- switch_channel_set_profile_var(channel, "callee_id_number", expanded);
- } else if (!strcasecmp(var, "effective_callee_id_name")) {
- switch_channel_set_profile_var(channel, "callee_id_name", expanded);
- } else if (!strcasecmp(var, "effective_caller_id_number")) {
- switch_channel_set_profile_var(channel, "caller_id_number", expanded);
- } else if (!strcasecmp(var, "effective_caller_id_name")) {
- switch_channel_set_profile_var(channel, "caller_id_name", expanded);
- };
-
-
+ kz_check_set_profile_var(channel, var, expanded);
if (expanded && expanded != val) {
switch_safe_free(expanded);
}
}
}
-static void base_export (switch_core_session_t *session, const char *data, switch_stack_t stack) {
+static int kz_is_exported(switch_core_session_t *session, char *varname)
+{
+ char *array[256] = {0};
+ int i, argc;
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ const char *exports = switch_channel_get_variable(channel, SWITCH_EXPORT_VARS_VARIABLE);
+ char *arg = switch_core_session_strdup(session, exports);
+ argc = switch_split(arg, ',', array);
+ for(i=0; i < argc; i++) {
+ if(!strcasecmp(array[i], varname))
+ return 1;
+ }
+
+ return 0;
+}
+
+static void base_export (switch_core_session_t *session, const char *data, int urldecode, switch_stack_t stack)
+{
char *var, *val = NULL;
if (zstr(data)) {
@@ -121,21 +147,57 @@ static void base_export (switch_core_session_t *session, const char *data, switc
}
}
- if (val) {
- expanded = switch_channel_expand_variables(channel, val);
- }
+ if (val) {
+ if(urldecode) {
+ switch_url_decode(val);
+ }
+ expanded = switch_channel_expand_variables(channel, val);
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s EXPORT [%s]=[%s]\n", switch_channel_get_name(channel), var,
- expanded ? expanded : "UNDEF");
- switch_channel_export_variable_var_check(channel, var, expanded, SWITCH_EXPORT_VARS_VARIABLE, SWITCH_FALSE);
-
- if (expanded && expanded != val) {
- switch_safe_free(expanded);
- }
+ if(!kz_is_exported(session, var)) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s EXPORT [%s]=[%s]\n", switch_channel_get_name(channel), var, expanded ? expanded : "UNDEF");
+ switch_channel_export_variable_var_check(channel, var, expanded, SWITCH_EXPORT_VARS_VARIABLE, SWITCH_FALSE);
+ } else {
+ if(strcmp(switch_str_nil(switch_channel_get_variable_dup(channel, var, SWITCH_FALSE, -1)), expanded)) {
+ switch_channel_set_variable(channel, var, expanded);
+ }
+ }
+ if (expanded && expanded != val) {
+ switch_safe_free(expanded);
+ }
+ }
}
}
-SWITCH_STANDARD_APP(multiset_function) {
+SWITCH_STANDARD_APP(prefix_unset_function)
+{
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ switch_event_header_t *ei = NULL;
+ switch_event_t *clear;
+ char *arg = (char *) data;
+
+ if(switch_event_create(&clear, SWITCH_EVENT_CLONE) != SWITCH_STATUS_SUCCESS) {
+ return;
+ }
+
+ for (ei = switch_channel_variable_first(channel); ei; ei = ei->next) {
+ const char *name = ei->name;
+ char *value = ei->value;
+ if (!strncasecmp(name, arg, strlen(arg))) {
+ switch_event_add_header_string(clear, SWITCH_STACK_BOTTOM, name, value);
+ }
+ }
+
+ switch_channel_variable_last(channel);
+ for (ei = clear->headers; ei; ei = ei->next) {
+ char *varname = ei->name;
+ switch_channel_set_variable(channel, varname, NULL);
+ }
+
+ switch_event_destroy(&clear);
+}
+
+void kz_multiset(switch_core_session_t *session, const char* data, int urldecode)
+{
char delim = ' ';
char *arg = (char *) data;
switch_event_t *event;
@@ -145,33 +207,107 @@ SWITCH_STANDARD_APP(multiset_function) {
delim = *arg++;
}
- if (arg) {
+ if(delim != '\0') {
switch_channel_t *channel = switch_core_session_get_channel(session);
- char *array[256] = {0};
- int i, argc;
+ if (arg) {
+ char *array[256] = {0};
+ int i, argc;
- arg = switch_core_session_strdup(session, arg);
- argc = switch_split(arg, delim, array);
+ arg = switch_core_session_strdup(session, arg);
+ argc = switch_split(arg, delim, array);
- for(i = 0; i < argc; i++) {
- base_set(session, array[i], SWITCH_STACK_BOTTOM);
+ for(i = 0; i < argc; i++) {
+ base_set(session, array[i], urldecode, SWITCH_STACK_BOTTOM);
+ }
}
-
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_DATA) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data(channel, event);
switch_event_fire(&event);
}
-
} else {
- base_set(session, data, SWITCH_STACK_BOTTOM);
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "multiset with empty args\n");
}
}
-SWITCH_STANDARD_APP(set_function) {
+SWITCH_STANDARD_APP(multiset_function)
+{
+ kz_multiset(session, data, 0);
+}
+
+SWITCH_STANDARD_APP(multiset_encoded_function)
+{
+ kz_multiset(session, data, 1);
+}
+
+void kz_uuid_multiset(switch_core_session_t *session, const char* data, int urldecode)
+{
+ char delim = ' ';
+ char *arg0 = (char *) data;
+ char *arg = strchr(arg0, ' ');
+ switch_event_t *event;
+
+
+ if(arg == NULL) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "uuid_multiset with invalid args\n");
+ return;
+ }
+ *arg = '\0';
+ arg++;
+
+ if(zstr(arg0)) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "uuid_multiset with invalid uuid\n");
+ return;
+ }
+
+
+ if (!zstr(arg) && *arg == '^' && *(arg+1) == '^') {
+ arg += 2;
+ delim = *arg++;
+ }
+
+ if(delim != '\0') {
+ switch_core_session_t *uuid_session = NULL;
+ if ((uuid_session = switch_core_session_force_locate(arg0)) != NULL) {
+ switch_channel_t *uuid_channel = switch_core_session_get_channel(uuid_session);
+ if (arg) {
+ char *array[256] = {0};
+ int i, argc;
+
+ arg = switch_core_session_strdup(session, arg);
+ argc = switch_split(arg, delim, array);
+
+ for(i = 0; i < argc; i++) {
+ base_set(uuid_session, array[i], urldecode, SWITCH_STACK_BOTTOM);
+ }
+ }
+ if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_DATA) == SWITCH_STATUS_SUCCESS) {
+ switch_channel_event_set_data(uuid_channel, event);
+ switch_event_fire(&event);
+ }
+ switch_core_session_rwunlock(uuid_session);
+ } else {
+ base_set(session, data, urldecode, SWITCH_STACK_BOTTOM);
+ }
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "multiset with empty args\n");
+ }
+}
+
+SWITCH_STANDARD_APP(uuid_multiset_function)
+{
+ kz_uuid_multiset(session, data, 0);
+}
+
+SWITCH_STANDARD_APP(uuid_multiset_encoded_function)
+{
+ kz_uuid_multiset(session, data, 1);
+}
+
+void kz_set(switch_core_session_t *session, const char* data, int urldecode) {
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_event_t *event;
- base_set(session, data, SWITCH_STACK_BOTTOM);
+ base_set(session, data, urldecode, SWITCH_STACK_BOTTOM);
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_DATA) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data(channel, event);
@@ -179,6 +315,16 @@ SWITCH_STANDARD_APP(set_function) {
}
}
+SWITCH_STANDARD_APP(set_function)
+{
+ kz_set(session, data, 0);
+}
+
+SWITCH_STANDARD_APP(set_encoded_function)
+{
+ kz_set(session, data, 1);
+}
+
SWITCH_STANDARD_APP(unset_function) {
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_event_t *event;
@@ -205,55 +351,562 @@ SWITCH_STANDARD_APP(multiunset_function) {
delim = *arg++;
}
- if (arg) {
- char *array[256] = {0};
- int i, argc;
+ if(delim != '\0') {
+ if (arg) {
+ char *array[256] = {0};
+ int i, argc;
- arg = switch_core_session_strdup(session, arg);
- argc = switch_split(arg, delim, array);
+ arg = switch_core_session_strdup(session, arg);
+ argc = switch_split(arg, delim, array);
- for(i = 0; i < argc; i++) {
- switch_channel_set_variable(switch_core_session_get_channel(session), array[i], NULL);
+ for(i = 0; i < argc; i++) {
+ switch_channel_set_variable(switch_core_session_get_channel(session), array[i], NULL);
+ }
+
+ } else {
+ switch_channel_set_variable(switch_core_session_get_channel(session), arg, NULL);
}
-
} else {
- switch_channel_set_variable(switch_core_session_get_channel(session), arg, NULL);
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "multiunset with empty args\n");
}
}
-SWITCH_STANDARD_APP(export_function) {
- char delim = ' ';
- char *arg = (char *) data;
- if (!zstr(arg) && *arg == '^' && *(arg+1) == '^') {
- arg += 2;
- delim = *arg++;
- }
+void kz_export(switch_core_session_t *session, const char* data, int urldecode)
+{
+ char delim = ' ';
+ char *arg = (char *) data;
- if (arg) {
- char *array[256] = {0};
- int i, argc;
+ if (!zstr(arg) && *arg == '^' && *(arg+1) == '^') {
+ arg += 2;
+ delim = *arg++;
+ }
- arg = switch_core_session_strdup(session, arg);
- argc = switch_split(arg, delim, array);
+ if(delim != '\0') {
+ if (arg) {
+ char *array[256] = {0};
+ int i, argc;
- for(i = 0; i < argc; i++) {
- base_export(session, array[i], SWITCH_STACK_BOTTOM);
- }
- } else {
- base_export(session, data, SWITCH_STACK_BOTTOM);
- }
+ arg = switch_core_session_strdup(session, arg);
+ argc = switch_split(arg, delim, array);
+
+ for(i = 0; i < argc; i++) {
+ base_export(session, array[i], urldecode, SWITCH_STACK_BOTTOM);
+ }
+ } else {
+ base_export(session, data, urldecode, SWITCH_STACK_BOTTOM);
+ }
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "export with empty args\n");
+ }
+}
+
+SWITCH_STANDARD_APP(export_function)
+{
+ kz_export(session, data, 0);
+}
+
+SWITCH_STANDARD_APP(export_encoded_function)
+{
+ kz_export(session, data, 1);
+}
+
+// copied from mod_dptools with allow SWITCH_STATUS_BREAK
+SWITCH_STANDARD_APP(kz_endless_playback_function)
+{
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ switch_status_t status = SWITCH_STATUS_SUCCESS;
+ const char *file = data;
+
+ while (switch_channel_ready(channel)) {
+ status = switch_ivr_play_file(session, NULL, file, NULL);
+
+ if (status != SWITCH_STATUS_SUCCESS) {
+ break;
+ }
+ }
+
+ switch (status) {
+ case SWITCH_STATUS_SUCCESS:
+ switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "FILE PLAYED");
+ break;
+ case SWITCH_STATUS_BREAK:
+ switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "PLAYBACK_INTERRUPTED");
+ break;
+ case SWITCH_STATUS_NOTFOUND:
+ switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "FILE NOT FOUND");
+ break;
+ default:
+ switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "PLAYBACK ERROR");
+ break;
+ }
+
+}
+
+SWITCH_STANDARD_APP(noop_function)
+{
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
+ const char *response = uuid_str;
+
+ if (zstr(data)) {
+ switch_uuid_str(uuid_str, sizeof(uuid_str));
+ } else {
+ response = data;
+ }
+
+ switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, response);
+}
+
+SWITCH_STANDARD_APP(kz_restore_caller_id_function)
+{
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ switch_caller_profile_t *cp = switch_channel_get_caller_profile(channel);
+ cp->caller_id_name = cp->orig_caller_id_name;
+ cp->caller_id_number = cp->orig_caller_id_number;
+}
+
+SWITCH_STANDARD_APP(kz_audio_bridge_function)
+{
+ switch_channel_t *caller_channel = switch_core_session_get_channel(session);
+ switch_core_session_t *peer_session = NULL;
+ switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING;
+ switch_status_t status = SWITCH_STATUS_FALSE;
+
+ if (zstr(data)) {
+ return;
+ }
+
+ status = switch_ivr_originate(session, &peer_session, &cause, data, 0, NULL, NULL, NULL, NULL, NULL, SOF_NONE, NULL, NULL);
+
+ if (status != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Originate Failed. Cause: %s\n", switch_channel_cause2str(cause));
+
+ switch_channel_set_variable(caller_channel, "originate_failed_cause", switch_channel_cause2str(cause));
+ switch_channel_set_variable(caller_channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, switch_channel_cause2str(cause));
+ switch_channel_handle_cause(caller_channel, cause);
+
+ return;
+ } else {
+ const char* uuid = switch_core_session_get_uuid(session);
+ const char* peer_uuid = switch_core_session_get_uuid(peer_session);
+
+
+ switch_channel_t *peer_channel = switch_core_session_get_channel(peer_session);
+ if (switch_true(switch_channel_get_variable(caller_channel, SWITCH_BYPASS_MEDIA_AFTER_BRIDGE_VARIABLE)) ||
+ switch_true(switch_channel_get_variable(peer_channel, SWITCH_BYPASS_MEDIA_AFTER_BRIDGE_VARIABLE))) {
+ switch_channel_set_flag(caller_channel, CF_BYPASS_MEDIA_AFTER_BRIDGE);
+ }
+
+ while(1) {
+ const char *xfer_uuid;
+ switch_channel_state_t a_state , a_running_state;
+ switch_channel_state_t b_state , b_running_state;
+ status = switch_ivr_multi_threaded_bridge(session, peer_session, NULL, NULL, NULL);
+
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "BRIDGE RESULT %i\n", status);
+ if(status != 0) {
+ break;
+ }
+
+ a_state = switch_channel_get_state(caller_channel);
+ a_running_state = switch_channel_get_running_state(caller_channel);
+
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "A STATE %s %s => %s , %s\n", switch_channel_state_name(a_running_state), switch_channel_state_name(a_state), uuid, peer_uuid);
+
+ if(a_state >= CS_HANGUP) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "A HANGUP = %s , %s\n", uuid, peer_uuid);
+ break;
+ }
+
+ b_state = switch_channel_get_state(peer_channel);
+ b_running_state = switch_channel_get_running_state(peer_channel);
+
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "B STATE %s %s => %s , %s\n", switch_channel_state_name(b_running_state), switch_channel_state_name(b_state), uuid, peer_uuid);
+
+ if(b_state >= CS_HANGUP) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "B HANGUP = %s , %s\n", uuid, peer_uuid);
+ switch_channel_set_variable(caller_channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, switch_channel_cause2str(switch_channel_get_cause(peer_channel)));
+ break;
+ }
+
+ if(!(xfer_uuid=switch_channel_get_variable(caller_channel, "att_xfer_peer_uuid"))) {
+ if(!(xfer_uuid=switch_channel_get_variable(peer_channel, "att_xfer_peer_uuid"))) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "XFER UUID NULL\n");
+ break;
+ }
+ }
+
+ switch_channel_set_variable(caller_channel, "att_xfer_peer_uuid", NULL);
+ switch_channel_set_variable(peer_channel, "att_xfer_peer_uuid", NULL);
+
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "WAIT 1\n");
+
+ switch_channel_clear_flag(peer_channel, CF_UUID_BRIDGE_ORIGINATOR);
+ switch_channel_set_state(peer_channel, CS_RESET);
+ switch_channel_wait_for_state(peer_channel, NULL, CS_RESET);
+ switch_channel_clear_state_handler(peer_channel, NULL);
+
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "WAIT 3\n");
+
+ switch_channel_set_flag(caller_channel, CF_UUID_BRIDGE_ORIGINATOR);
+ switch_channel_clear_flag(caller_channel, CF_TRANSFER);
+ switch_channel_clear_flag(caller_channel, CF_REDIRECT);
+ switch_channel_set_flag(peer_channel, CF_UUID_BRIDGE_ORIGINATOR);
+ switch_channel_clear_flag(peer_channel, CF_TRANSFER);
+ switch_channel_clear_flag(peer_channel, CF_REDIRECT);
+
+ if(!switch_channel_media_up(caller_channel)) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "A MEDIA DOWN HANGUP = %s, %s , %s\n", xfer_uuid, uuid, peer_uuid);
+ }
+ if(!switch_channel_media_up(peer_channel)) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "B MEDIA DOWN HANGUP = %s, %s , %s\n", xfer_uuid, uuid, peer_uuid);
+ }
+ switch_channel_set_state(caller_channel, CS_EXECUTE);
+ switch_channel_set_state(peer_channel, CS_EXECUTE);
+
+
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "XFER LOOP %s %s , %s\n", xfer_uuid, uuid, peer_uuid);
+
+ }
+
+ if (peer_session) {
+ switch_core_session_rwunlock(peer_session);
+ }
+ }
+}
+
+SWITCH_STANDARD_APP(kz_audio_bridge_uuid_function)
+{
+ switch_core_session_t *peer_session = NULL;
+ const char * peer_uuid = NULL;
+
+ if (zstr(data)) {
+ return;
+ }
+
+ peer_uuid = switch_core_session_strdup(session, data);
+ if (peer_uuid && (peer_session = switch_core_session_locate(peer_uuid))) {
+ switch_ivr_multi_threaded_bridge(session, peer_session, NULL, NULL, NULL);
+ }
+
+ if (peer_session) {
+ switch_core_session_rwunlock(peer_session);
+ }
+}
+
+
+struct kz_att_keys {
+ const char *attxfer_cancel_key;
+ const char *attxfer_hangup_key;
+ const char *attxfer_conf_key;
+};
+
+static switch_status_t kz_att_xfer_on_dtmf(switch_core_session_t *session, void *input, switch_input_type_t itype, void *buf, unsigned int buflen)
+{
+ switch_core_session_t *peer_session = (switch_core_session_t *) buf;
+ if (!buf || !peer_session) {
+ return SWITCH_STATUS_SUCCESS;
+ }
+
+ switch (itype) {
+ case SWITCH_INPUT_TYPE_DTMF:
+ {
+ switch_dtmf_t *dtmf = (switch_dtmf_t *) input;
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ switch_channel_t *peer_channel = switch_core_session_get_channel(peer_session);
+ struct kz_att_keys *keys = switch_channel_get_private(channel, "__kz_keys");
+
+ if (dtmf->digit == *keys->attxfer_hangup_key) {
+ switch_channel_hangup(channel, SWITCH_CAUSE_ATTENDED_TRANSFER);
+ return SWITCH_STATUS_FALSE;
+ }
+
+ if (dtmf->digit == *keys->attxfer_cancel_key) {
+ switch_channel_hangup(peer_channel, SWITCH_CAUSE_NORMAL_CLEARING);
+ return SWITCH_STATUS_FALSE;
+ }
+
+ if (dtmf->digit == *keys->attxfer_conf_key) {
+ switch_caller_extension_t *extension = NULL;
+ const char *app = "three_way";
+ const char *app_arg = switch_core_session_get_uuid(session);
+ const char *holding = switch_channel_get_variable(channel, SWITCH_SOFT_HOLDING_UUID_VARIABLE);
+ switch_core_session_t *b_session;
+
+ if (holding && (b_session = switch_core_session_locate(holding))) {
+ switch_channel_t *b_channel = switch_core_session_get_channel(b_session);
+ if (!switch_channel_ready(b_channel)) {
+ app = "intercept";
+ }
+ switch_core_session_rwunlock(b_session);
+ }
+
+ if ((extension = switch_caller_extension_new(peer_session, app, app_arg)) == 0) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Memory Error!\n");
+ abort();
+ }
+
+ switch_caller_extension_add_application(peer_session, extension, app, app_arg);
+ switch_channel_set_caller_extension(peer_channel, extension);
+ switch_channel_set_state(peer_channel, CS_RESET);
+ switch_channel_wait_for_state(peer_channel, channel, CS_RESET);
+ switch_channel_set_state(peer_channel, CS_EXECUTE);
+ switch_channel_set_variable(channel, SWITCH_HANGUP_AFTER_BRIDGE_VARIABLE, NULL);
+ return SWITCH_STATUS_FALSE;
+ }
+
+ }
+ break;
+ default:
+ break;
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t kz_att_xfer_tmp_hanguphook(switch_core_session_t *session)
+{
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ switch_channel_state_t state = switch_channel_get_state(channel);
+
+ if (state == CS_HANGUP || state == CS_ROUTING) {
+ const char *bond = switch_channel_get_variable(channel, SWITCH_SOFT_HOLDING_UUID_VARIABLE);
+
+ if (!zstr(bond)) {
+ switch_core_session_t *b_session;
+
+ if ((b_session = switch_core_session_locate(bond))) {
+ switch_channel_t *b_channel = switch_core_session_get_channel(b_session);
+ if (switch_channel_up(b_channel)) {
+ switch_channel_set_flag(b_channel, CF_REDIRECT);
+ }
+ switch_core_session_rwunlock(b_session);
+ }
+ }
+
+ switch_core_event_hook_remove_state_change(session, kz_att_xfer_tmp_hanguphook);
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t kz_att_xfer_hanguphook(switch_core_session_t *session)
+{
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ switch_channel_state_t state = switch_channel_get_state(channel);
+ const char *id = NULL;
+
+ if (state == CS_HANGUP || state == CS_ROUTING) {
+ if ((id = switch_channel_get_variable(channel, "xfer_uuids"))) {
+ switch_stream_handle_t stream = { 0 };
+ SWITCH_STANDARD_STREAM(stream);
+ switch_api_execute("uuid_bridge", id, NULL, &stream);
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "\nHangup Command uuid_bridge(%s):\n%s\n", id,
+ switch_str_nil((char *) stream.data));
+ switch_safe_free(stream.data);
+ }
+
+ switch_core_event_hook_remove_state_change(session, kz_att_xfer_hanguphook);
+ }
+ return SWITCH_STATUS_SUCCESS;
+}
+
+
+static void kz_att_xfer_set_result(switch_channel_t *channel, switch_status_t status)
+{
+ switch_channel_set_variable(channel, SWITCH_ATT_XFER_RESULT_VARIABLE, status == SWITCH_STATUS_SUCCESS ? "success" : "failure");
+}
+
+struct kz_att_obj {
+ switch_core_session_t *session;
+ const char *data;
+ int running;
+};
+
+void *SWITCH_THREAD_FUNC kz_att_thread_run(switch_thread_t *thread, void *obj)
+{
+ struct kz_att_obj *att = (struct kz_att_obj *) obj;
+ struct kz_att_keys *keys = NULL;
+ switch_core_session_t *session = att->session;
+ switch_core_session_t *peer_session = NULL;
+ const char *data = att->data;
+ switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING;
+ switch_channel_t *channel = switch_core_session_get_channel(session), *peer_channel = NULL;
+ const char *bond = NULL;
+ switch_core_session_t *b_session = NULL;
+ switch_bool_t follow_recording = switch_true(switch_channel_get_variable(channel, "recording_follow_attxfer"));
+ const char *attxfer_cancel_key = NULL, *attxfer_hangup_key = NULL, *attxfer_conf_key = NULL;
+
+ att->running = 1;
+
+ if (switch_core_session_read_lock(session) != SWITCH_STATUS_SUCCESS) {
+ return NULL;
+ }
+
+ bond = switch_channel_get_partner_uuid(channel);
+ if ((b_session = switch_core_session_locate(bond)) == NULL) {
+ switch_core_session_rwunlock(peer_session);
+ return NULL;
+ }
+
+ switch_channel_set_variable(channel, SWITCH_SOFT_HOLDING_UUID_VARIABLE, bond);
+ switch_core_event_hook_add_state_change(session, kz_att_xfer_tmp_hanguphook);
+
+ if (follow_recording && (b_session = switch_core_session_locate(bond))) {
+ switch_ivr_transfer_recordings(b_session, session);
+ switch_core_session_rwunlock(b_session);
+ }
+
+ if (switch_ivr_originate(session, &peer_session, &cause, data, 0, NULL, NULL, NULL, NULL, NULL, SOF_NONE, NULL, NULL)
+ != SWITCH_STATUS_SUCCESS || !peer_session) {
+ switch_channel_set_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE, bond);
+ goto end;
+ }
+
+ peer_channel = switch_core_session_get_channel(peer_session);
+ switch_channel_set_flag(peer_channel, CF_INNER_BRIDGE);
+ switch_channel_set_flag(channel, CF_INNER_BRIDGE);
+
+ if (!(attxfer_cancel_key = switch_channel_get_variable(channel, "attxfer_cancel_key"))) {
+ if (!(attxfer_cancel_key = switch_channel_get_variable(peer_channel, "attxfer_cancel_key"))) {
+ attxfer_cancel_key = "#";
+ }
+ }
+
+ if (!(attxfer_hangup_key = switch_channel_get_variable(channel, "attxfer_hangup_key"))) {
+ if (!(attxfer_hangup_key = switch_channel_get_variable(peer_channel, "attxfer_hangup_key"))) {
+ attxfer_hangup_key = "*";
+ }
+ }
+
+ if (!(attxfer_conf_key = switch_channel_get_variable(channel, "attxfer_conf_key"))) {
+ if (!(attxfer_conf_key = switch_channel_get_variable(peer_channel, "attxfer_conf_key"))) {
+ attxfer_conf_key = "0";
+ }
+ }
+
+ keys = switch_core_session_alloc(session, sizeof(*keys));
+ keys->attxfer_cancel_key = switch_core_session_strdup(session, attxfer_cancel_key);
+ keys->attxfer_hangup_key = switch_core_session_strdup(session, attxfer_hangup_key);
+ keys->attxfer_conf_key = switch_core_session_strdup(session, attxfer_conf_key);
+ switch_channel_set_private(channel, "__kz_keys", keys);
+
+ switch_channel_set_variable(channel, "att_xfer_peer_uuid", switch_core_session_get_uuid(peer_session));
+
+ switch_ivr_multi_threaded_bridge(session, peer_session, kz_att_xfer_on_dtmf, peer_session, NULL);
+
+ switch_channel_clear_flag(peer_channel, CF_INNER_BRIDGE);
+ switch_channel_clear_flag(channel, CF_INNER_BRIDGE);
+
+ if (zstr(bond) && switch_channel_down(peer_channel)) {
+ switch_core_session_rwunlock(peer_session);
+ switch_channel_set_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE, bond);
+ goto end;
+ }
+
+ if (bond) {
+ int br = 0;
+
+ switch_channel_set_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE, bond);
+
+ if (!switch_channel_down(peer_channel)) {
+ /*
+ * we're emiting the transferee event so that callctl can update
+ */
+ switch_event_t *event = NULL;
+ switch_channel_t *b_channel = switch_core_session_get_channel(b_session);
+ if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, "sofia::transferee") == SWITCH_STATUS_SUCCESS) {
+ switch_channel_event_set_data(b_channel, event);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "att_xfer_replaced_call_id", switch_core_session_get_uuid(peer_session));
+ switch_event_fire(&event);
+ }
+ if (!switch_channel_ready(channel)) {
+ switch_status_t status;
+
+ if (follow_recording) {
+ switch_ivr_transfer_recordings(session, peer_session);
+ }
+ status = switch_ivr_uuid_bridge(switch_core_session_get_uuid(peer_session), bond);
+ kz_att_xfer_set_result(peer_channel, status);
+ br++;
+ } else {
+ switch_channel_set_variable_printf(b_channel, "xfer_uuids", "%s %s", switch_core_session_get_uuid(peer_session), switch_core_session_get_uuid(session));
+ switch_channel_set_variable_printf(channel, "xfer_uuids", "%s %s", switch_core_session_get_uuid(peer_session), bond);
+
+ switch_core_event_hook_add_state_change(session, kz_att_xfer_hanguphook);
+ switch_core_event_hook_add_state_change(b_session, kz_att_xfer_hanguphook);
+ }
+ }
+
+/*
+ * this was commented so that the existing bridge
+ * doesn't end
+ *
+ if (!br) {
+ switch_status_t status = switch_ivr_uuid_bridge(switch_core_session_get_uuid(session), bond);
+ att_xfer_set_result(channel, status);
+ }
+*/
+
+ }
+
+ switch_core_session_rwunlock(peer_session);
+
+ end:
+
+ switch_core_event_hook_remove_state_change(session, kz_att_xfer_tmp_hanguphook);
+
+ switch_channel_set_variable(channel, SWITCH_SOFT_HOLDING_UUID_VARIABLE, NULL);
+ switch_channel_clear_flag(channel, CF_XFER_ZOMBIE);
+
+ switch_core_session_rwunlock(b_session);
+ switch_core_session_rwunlock(session);
+ att->running = 0;
+
+ return NULL;
+}
+
+SWITCH_STANDARD_APP(kz_att_xfer_function)
+{
+ switch_thread_t *thread;
+ switch_threadattr_t *thd_attr = NULL;
+ switch_memory_pool_t *pool = switch_core_session_get_pool(session);
+ struct kz_att_obj *att;
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+
+ switch_threadattr_create(&thd_attr, pool);
+ switch_threadattr_detach_set(thd_attr, 1);
+ switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
+ switch_threadattr_detach_set(thd_attr, 1);
+
+ att = switch_core_session_alloc(session, sizeof(*att));
+ att->running = -1;
+ att->session = session;
+ att->data = switch_core_session_strdup(session, data);
+ switch_thread_create(&thread, thd_attr, kz_att_thread_run, att, pool);
+
+ while(att->running && switch_channel_up(channel)) {
+ switch_yield(100000);
+ }
}
void add_kz_dptools(switch_loadable_module_interface_t **module_interface, switch_application_interface_t *app_interface) {
- SWITCH_ADD_APP(app_interface, "kz_set", SET_SHORT_DESC, SET_LONG_DESC, set_function, SET_SYNTAX,
- SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
- SWITCH_ADD_APP(app_interface, "kz_multiset", MULTISET_SHORT_DESC, MULTISET_LONG_DESC, multiset_function, MULTISET_SYNTAX,
- SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
- SWITCH_ADD_APP(app_interface, "kz_unset", UNSET_SHORT_DESC, UNSET_LONG_DESC, unset_function, UNSET_SYNTAX,
- SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
- SWITCH_ADD_APP(app_interface, "kz_multiunset", MULTISET_SHORT_DESC, MULTISET_LONG_DESC, multiunset_function, MULTIUNSET_SYNTAX,
- SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
- SWITCH_ADD_APP(app_interface, "kz_export", EXPORT_SHORT_DESC, EXPORT_LONG_DESC, export_function, EXPORT_SYNTAX,
- SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
+ SWITCH_ADD_APP(app_interface, "kz_set", SET_SHORT_DESC, SET_LONG_DESC, set_function, SET_SYNTAX, SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
+ SWITCH_ADD_APP(app_interface, "kz_set_encoded", SET_SHORT_DESC, SET_LONG_DESC, set_encoded_function, SET_SYNTAX, SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
+ SWITCH_ADD_APP(app_interface, "kz_multiset", MULTISET_SHORT_DESC, MULTISET_LONG_DESC, multiset_function, MULTISET_SYNTAX, SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
+ SWITCH_ADD_APP(app_interface, "kz_multiset_encoded", MULTISET_SHORT_DESC, MULTISET_LONG_DESC, multiset_encoded_function, MULTISET_SYNTAX, SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
+ SWITCH_ADD_APP(app_interface, "kz_unset", UNSET_SHORT_DESC, UNSET_LONG_DESC, unset_function, UNSET_SYNTAX, SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
+ SWITCH_ADD_APP(app_interface, "kz_multiunset", MULTISET_SHORT_DESC, MULTISET_LONG_DESC, multiunset_function, MULTIUNSET_SYNTAX, SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
+ SWITCH_ADD_APP(app_interface, "kz_export", EXPORT_SHORT_DESC, EXPORT_LONG_DESC, export_function, EXPORT_SYNTAX, SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
+ SWITCH_ADD_APP(app_interface, "kz_export_encoded", EXPORT_SHORT_DESC, EXPORT_LONG_DESC, export_encoded_function, EXPORT_SYNTAX, SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
+ SWITCH_ADD_APP(app_interface, "kz_prefix_unset", PREFIX_UNSET_SHORT_DESC, PREFIX_UNSET_LONG_DESC, prefix_unset_function, PREFIX_UNSET_SYNTAX, SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
+ SWITCH_ADD_APP(app_interface, "kz_uuid_multiset", UUID_MULTISET_SHORT_DESC, UUID_MULTISET_LONG_DESC, uuid_multiset_function, UUID_MULTISET_SYNTAX, SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
+ SWITCH_ADD_APP(app_interface, "kz_uuid_multiset_encoded", UUID_MULTISET_SHORT_DESC, UUID_MULTISET_LONG_DESC, uuid_multiset_encoded_function, UUID_MULTISET_SYNTAX, SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
+ SWITCH_ADD_APP(app_interface, "kz_endless_playback", KZ_ENDLESS_PLAYBACK_SHORT_DESC, KZ_ENDLESS_PLAYBACK_LONG_DESC, kz_endless_playback_function, KZ_ENDLESS_PLAYBACK_SYNTAX, SAF_NONE);
+ SWITCH_ADD_APP(app_interface, "kz_restore_caller_id", NOOP_SHORT_DESC, NOOP_LONG_DESC, kz_restore_caller_id_function, NOOP_SYNTAX, SAF_NONE);
+ SWITCH_ADD_APP(app_interface, "noop", NOOP_SHORT_DESC, NOOP_LONG_DESC, noop_function, NOOP_SYNTAX, SAF_NONE);
+ SWITCH_ADD_APP(app_interface, "kz_bridge", "Bridge Audio", "Bridge the audio between two sessions", kz_audio_bridge_function, "", SAF_SUPPORT_NOMEDIA|SAF_SUPPORT_TEXT_ONLY);
+ SWITCH_ADD_APP(app_interface, "kz_bridge_uuid", "Bridge Audio", "Bridge the audio between two sessions", kz_audio_bridge_uuid_function, "", SAF_SUPPORT_NOMEDIA|SAF_SUPPORT_TEXT_ONLY);
+ SWITCH_ADD_APP(app_interface, "kz_att_xfer", "Attended Transfer", "Attended Transfer", kz_att_xfer_function, "", SAF_NONE);
}
diff --git a/src/mod/event_handlers/mod_kazoo/kazoo_ei.h b/src/mod/event_handlers/mod_kazoo/kazoo_ei.h
new file mode 100644
index 0000000000..3d844655b7
--- /dev/null
+++ b/src/mod/event_handlers/mod_kazoo/kazoo_ei.h
@@ -0,0 +1,292 @@
+#ifndef KAZOO_EI_H
+#define KAZOO_EI_H
+
+#include
+#include
+
+#define MODNAME "mod_kazoo"
+#define BUNDLE "community"
+#define RELEASE "v1.5.0-1"
+#define VERSION "mod_kazoo v1.5.0-1 community"
+
+#define KZ_MAX_SEPARATE_STRINGS 10
+
+typedef enum {KAZOO_FETCH_PROFILE, KAZOO_EVENT_PROFILE} kazoo_profile_type;
+
+typedef enum {ERLANG_TUPLE, ERLANG_MAP} kazoo_json_term;
+
+typedef struct ei_xml_agent_s ei_xml_agent_t;
+typedef ei_xml_agent_t *ei_xml_agent_ptr;
+
+typedef struct kazoo_event kazoo_event_t;
+typedef kazoo_event_t *kazoo_event_ptr;
+
+typedef struct kazoo_event_profile kazoo_event_profile_t;
+typedef kazoo_event_profile_t *kazoo_event_profile_ptr;
+
+typedef struct kazoo_fetch_profile kazoo_fetch_profile_t;
+typedef kazoo_fetch_profile_t *kazoo_fetch_profile_ptr;
+
+typedef struct kazoo_config_t kazoo_config;
+typedef kazoo_config *kazoo_config_ptr;
+
+#include "kazoo_fields.h"
+#include "kazoo_config.h"
+
+struct ei_send_msg_s {
+ ei_x_buff buf;
+ erlang_pid pid;
+};
+typedef struct ei_send_msg_s ei_send_msg_t;
+
+struct ei_received_msg_s {
+ ei_x_buff buf;
+ erlang_msg msg;
+};
+typedef struct ei_received_msg_s ei_received_msg_t;
+
+
+typedef struct ei_event_stream_s ei_event_stream_t;
+typedef struct ei_node_s ei_node_t;
+
+struct ei_event_binding_s {
+ char id[SWITCH_UUID_FORMATTED_LENGTH + 1];
+ switch_event_node_t *node;
+ switch_event_types_t type;
+ const char *subclass_name;
+ ei_event_stream_t* stream;
+ kazoo_event_ptr event;
+
+ struct ei_event_binding_s *next;
+};
+typedef struct ei_event_binding_s ei_event_binding_t;
+
+struct ei_event_stream_s {
+ switch_memory_pool_t *pool;
+ ei_event_binding_t *bindings;
+ switch_queue_t *queue;
+ switch_socket_t *acceptor;
+ switch_pollset_t *pollset;
+ switch_pollfd_t *pollfd;
+ switch_socket_t *socket;
+ switch_mutex_t *socket_mutex;
+ switch_bool_t connected;
+ char remote_ip[48];
+ uint16_t remote_port;
+ char local_ip[48];
+ uint16_t local_port;
+ erlang_pid pid;
+ uint32_t flags;
+ ei_node_t *node;
+ short event_stream_framing;
+ struct ei_event_stream_s *next;
+};
+
+struct ei_node_s {
+ int nodefd;
+ switch_atomic_t pending_bgapi;
+ switch_atomic_t receive_handlers;
+ switch_memory_pool_t *pool;
+ ei_event_stream_t *event_streams;
+ switch_mutex_t *event_streams_mutex;
+ switch_queue_t *send_msgs;
+ switch_queue_t *received_msgs;
+ char *peer_nodename;
+ switch_time_t created_time;
+ switch_socket_t *socket;
+ char remote_ip[48];
+ uint16_t remote_port;
+ char local_ip[48];
+ uint16_t local_port;
+ uint32_t flags;
+ int legacy;
+ short event_stream_framing;
+ struct ei_node_s *next;
+};
+
+
+struct xml_fetch_reply_s {
+ char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
+ char *xml_str;
+ struct xml_fetch_reply_s *next;
+};
+typedef struct xml_fetch_reply_s xml_fetch_reply_t;
+
+struct fetch_handler_s {
+ erlang_pid pid;
+ struct fetch_handler_s *next;
+};
+typedef struct fetch_handler_s fetch_handler_t;
+
+struct ei_xml_client_s {
+ ei_node_t *ei_node;
+ fetch_handler_t *fetch_handlers;
+ struct ei_xml_client_s *next;
+};
+typedef struct ei_xml_client_s ei_xml_client_t;
+
+struct ei_xml_agent_s {
+ switch_memory_pool_t *pool;
+ switch_xml_section_t section;
+ switch_thread_rwlock_t *lock;
+ ei_xml_client_t *clients;
+ switch_mutex_t *current_client_mutex;
+ ei_xml_client_t *current_client;
+ switch_mutex_t *replies_mutex;
+ switch_thread_cond_t *new_reply;
+ xml_fetch_reply_t *replies;
+ kazoo_fetch_profile_ptr profile;
+
+};
+
+typedef enum {
+ KZ_TWEAK_INTERACTION_ID,
+ KZ_TWEAK_EXPORT_VARS,
+ KZ_TWEAK_SWITCH_URI,
+ KZ_TWEAK_REPLACES_CALL_ID,
+ KZ_TWEAK_LOOPBACK_VARS,
+ KZ_TWEAK_CALLER_ID,
+ KZ_TWEAK_TRANSFERS,
+ KZ_TWEAK_BRIDGE,
+ KZ_TWEAK_BRIDGE_REPLACES_ALEG,
+ KZ_TWEAK_BRIDGE_REPLACES_CALL_ID,
+ KZ_TWEAK_BRIDGE_VARIABLES,
+ KZ_TWEAK_RESTORE_CALLER_ID_ON_BLIND_XFER,
+
+ /* No new flags below this line */
+ KZ_TWEAK_MAX
+} kz_tweak_t;
+
+struct globals_s {
+ switch_memory_pool_t *pool;
+ switch_atomic_t threads;
+ switch_socket_t *acceptor;
+ struct ei_cnode_s ei_cnode;
+ switch_thread_rwlock_t *ei_nodes_lock;
+ ei_node_t *ei_nodes;
+
+ switch_xml_binding_t *config_fetch_binding;
+ switch_xml_binding_t *directory_fetch_binding;
+ switch_xml_binding_t *dialplan_fetch_binding;
+ switch_xml_binding_t *channels_fetch_binding;
+ switch_xml_binding_t *languages_fetch_binding;
+ switch_xml_binding_t *chatplan_fetch_binding;
+
+ switch_hash_t *event_filter;
+ int epmdfd;
+ int num_worker_threads;
+ switch_bool_t nat_map;
+ switch_bool_t ei_shortname;
+ int ei_compat_rel;
+ char *ip;
+ char *hostname;
+ char *ei_cookie;
+ char *ei_nodename;
+ uint32_t flags;
+ int send_all_headers;
+ int send_all_private_headers;
+ int connection_timeout;
+ int receive_timeout;
+ int receive_msg_preallocate;
+ int event_stream_preallocate;
+ int send_msg_batch;
+ short event_stream_framing;
+ switch_port_t port;
+ int config_fetched;
+ int io_fault_tolerance;
+ kazoo_event_profile_ptr events;
+ kazoo_config_ptr definitions;
+ kazoo_config_ptr event_handlers;
+ kazoo_config_ptr fetch_handlers;
+ kazoo_json_term json_encoding;
+
+ char **profile_vars_prefixes;
+ char **kazoo_var_prefixes;
+
+ int legacy_events;
+ uint8_t tweaks[KZ_TWEAK_MAX];
+
+
+};
+typedef struct globals_s globals_t;
+extern globals_t kazoo_globals;
+
+/* kazoo_event_stream.c */
+ei_event_stream_t *find_event_stream(ei_event_stream_t *event_streams, const erlang_pid *from);
+
+//ei_event_stream_t *new_event_stream(ei_event_stream_t **event_streams, const erlang_pid *from);
+ei_event_stream_t *new_event_stream(ei_node_t *ei_node, const erlang_pid *from);
+
+
+switch_status_t remove_event_stream(ei_event_stream_t **event_streams, const erlang_pid *from);
+switch_status_t remove_event_streams(ei_event_stream_t **event_streams);
+unsigned long get_stream_port(const ei_event_stream_t *event_stream);
+switch_status_t add_event_binding(ei_event_stream_t *event_stream, const char *event_name);
+//switch_status_t add_event_binding(ei_event_stream_t *event_stream, const switch_event_types_t event_type, const char *subclass_name);
+switch_status_t remove_event_binding(ei_event_stream_t *event_stream, const switch_event_types_t event_type, const char *subclass_name);
+switch_status_t remove_event_bindings(ei_event_stream_t *event_stream);
+
+/* kazoo_node.c */
+switch_status_t new_kazoo_node(int nodefd, ErlConnect *conn);
+
+/* kazoo_ei_utils.c */
+void close_socket(switch_socket_t **sock);
+void close_socketfd(int *sockfd);
+switch_socket_t *create_socket_with_port(switch_memory_pool_t *pool, switch_port_t port);
+switch_socket_t *create_socket(switch_memory_pool_t *pool);
+switch_status_t create_ei_cnode(const char *ip_addr, const char *name, struct ei_cnode_s *ei_cnode);
+switch_status_t ei_compare_pids(const erlang_pid *pid1, const erlang_pid *pid2);
+void ei_encode_switch_event_headers(ei_x_buff *ebuf, switch_event_t *event);
+void ei_encode_switch_event_headers_2(ei_x_buff *ebuf, switch_event_t *event, int decode);
+void ei_encode_json(ei_x_buff *ebuf, cJSON *JObj);
+void ei_link(ei_node_t *ei_node, erlang_pid * from, erlang_pid * to);
+void ei_encode_switch_event(ei_x_buff * ebuf, switch_event_t *event);
+int ei_helper_send(ei_node_t *ei_node, erlang_pid* to, ei_x_buff *buf);
+int ei_decode_atom_safe(char *buf, int *index, char *dst);
+int ei_decode_string_or_binary_limited(char *buf, int *index, int maxsize, char *dst);
+int ei_decode_string_or_binary(char *buf, int *index, char **dst);
+switch_status_t create_acceptor();
+switch_hash_t *create_default_filter();
+
+void fetch_config();
+
+switch_status_t kazoo_load_config();
+void kazoo_destroy_config();
+
+
+#define _ei_x_encode_string(buf, string) { ei_x_encode_binary(buf, string, strlen(string)); }
+
+/* kazoo_fetch_agent.c */
+switch_status_t bind_fetch_agents();
+switch_status_t unbind_fetch_agents();
+switch_status_t remove_xml_clients(ei_node_t *ei_node);
+switch_status_t add_fetch_handler(ei_node_t *ei_node, erlang_pid *from, switch_xml_binding_t *binding);
+switch_status_t remove_fetch_handlers(ei_node_t *ei_node, erlang_pid *from);
+switch_status_t fetch_reply(char *uuid_str, char *xml_str, switch_xml_binding_t *binding);
+switch_status_t handle_api_command_streams(ei_node_t *ei_node, switch_stream_handle_t *stream);
+
+void bind_event_profiles(kazoo_event_ptr event);
+void rebind_fetch_profiles(kazoo_config_ptr fetch_handlers);
+switch_status_t kazoo_config_handlers(switch_xml_t cfg);
+
+/* runtime */
+SWITCH_MODULE_RUNTIME_FUNCTION(mod_kazoo_runtime);
+
+
+
+#define kz_test_tweak(flag) (kazoo_globals.tweaks[flag] ? 1 : 0)
+#define kz_set_tweak(flag) kazoo_globals.tweaks[flag] = 1
+#define kz_clear_tweak(flag) kazoo_globals.tweaks[flag] = 0
+
+#endif /* KAZOO_EI_H */
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4:
+ */
diff --git a/src/mod/event_handlers/mod_kazoo/kazoo_ei_config.c b/src/mod/event_handlers/mod_kazoo/kazoo_ei_config.c
new file mode 100644
index 0000000000..9357211afb
--- /dev/null
+++ b/src/mod/event_handlers/mod_kazoo/kazoo_ei_config.c
@@ -0,0 +1,635 @@
+/*
+* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+* Copyright (C) 2005-2012, Anthony Minessale II
+*
+* Version: MPL 1.1
+*
+* The contents of this file are subject to the Mozilla Public License Version
+* 1.1 (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+* http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS IS" basis,
+* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+* for the specific language governing rights and limitations under the
+* License.
+*
+* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+*
+* The Initial Developer of the Original Code is
+* Anthony Minessale II
+* Portions created by the Initial Developer are Copyright (C)
+* the Initial Developer. All Rights Reserved.
+*
+* Based on mod_skel by
+* Anthony Minessale II
+*
+* Contributor(s):
+*
+* Daniel Bryars
+* Tim Brown
+* Anthony Minessale II
+* William King
+* Mike Jerris
+*
+* kazoo.c -- Sends FreeSWITCH events to an AMQP broker
+*
+*/
+
+#include "mod_kazoo.h"
+
+#define KZ_DEFAULT_STREAM_PRE_ALLOCATE 8192
+
+#define KAZOO_DECLARE_GLOBAL_STRING_FUNC(fname, vname) static void __attribute__((__unused__)) fname(const char *string) { if (!string) return;\
+ if (vname) {free(vname); vname = NULL;}vname = strdup(string);} static void fname(const char *string)
+
+KAZOO_DECLARE_GLOBAL_STRING_FUNC(set_pref_ip, kazoo_globals.ip);
+KAZOO_DECLARE_GLOBAL_STRING_FUNC(set_pref_ei_cookie, kazoo_globals.ei_cookie);
+KAZOO_DECLARE_GLOBAL_STRING_FUNC(set_pref_ei_nodename, kazoo_globals.ei_nodename);
+//KAZOO_DECLARE_GLOBAL_STRING_FUNC(set_pref_kazoo_var_prefix, kazoo_globals.kazoo_var_prefix);
+
+static int read_cookie_from_file(char *filename) {
+ int fd;
+ char cookie[MAXATOMLEN + 1];
+ char *end;
+ struct stat buf;
+ ssize_t res;
+
+ if (!stat(filename, &buf)) {
+ if ((buf.st_mode & S_IRWXG) || (buf.st_mode & S_IRWXO)) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s must only be accessible by owner only.\n", filename);
+ return 2;
+ }
+ if (buf.st_size > MAXATOMLEN) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s contains a cookie larger than the maximum atom size of %d.\n", filename, MAXATOMLEN);
+ return 2;
+ }
+ fd = open(filename, O_RDONLY);
+ if (fd < 1) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to open cookie file %s : %d.\n", filename, errno);
+ return 2;
+ }
+
+ if ((res = read(fd, cookie, MAXATOMLEN)) < 1) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to read cookie file %s : %d.\n", filename, errno);
+ }
+
+ cookie[MAXATOMLEN] = '\0';
+
+ /* replace any end of line characters with a null */
+ if ((end = strchr(cookie, '\n'))) {
+ *end = '\0';
+ }
+
+ if ((end = strchr(cookie, '\r'))) {
+ *end = '\0';
+ }
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set cookie from file %s: %s\n", filename, cookie);
+
+ set_pref_ei_cookie(cookie);
+ return 0;
+ } else {
+ /* don't error here, because we might be blindly trying to read $HOME/.erlang.cookie, and that can fail silently */
+ return 1;
+ }
+}
+
+
+switch_status_t kazoo_ei_config(switch_xml_t cfg) {
+ switch_xml_t child, param;
+ char* kazoo_var_prefix = NULL;
+ char* profile_vars_prefix = NULL;
+ char* sep_array[KZ_MAX_SEPARATE_STRINGS];
+ int array_len, i;
+ kazoo_globals.send_all_headers = 0;
+ kazoo_globals.send_all_private_headers = 1;
+ kazoo_globals.connection_timeout = 500;
+ kazoo_globals.receive_timeout = 200;
+ kazoo_globals.receive_msg_preallocate = 2000;
+ kazoo_globals.event_stream_preallocate = KZ_DEFAULT_STREAM_PRE_ALLOCATE;
+ kazoo_globals.send_msg_batch = 10;
+ kazoo_globals.event_stream_framing = 2;
+ kazoo_globals.port = 0;
+ kazoo_globals.io_fault_tolerance = 10;
+ kazoo_globals.json_encoding = ERLANG_TUPLE;
+
+ kazoo_globals.legacy_events = SWITCH_FALSE;
+
+ kz_set_tweak(KZ_TWEAK_INTERACTION_ID);
+ kz_set_tweak(KZ_TWEAK_EXPORT_VARS);
+ kz_set_tweak(KZ_TWEAK_SWITCH_URI);
+ kz_set_tweak(KZ_TWEAK_REPLACES_CALL_ID);
+ kz_set_tweak(KZ_TWEAK_LOOPBACK_VARS);
+ kz_set_tweak(KZ_TWEAK_CALLER_ID);
+ kz_set_tweak(KZ_TWEAK_TRANSFERS);
+ kz_set_tweak(KZ_TWEAK_BRIDGE);
+ kz_set_tweak(KZ_TWEAK_BRIDGE_REPLACES_ALEG);
+ kz_set_tweak(KZ_TWEAK_BRIDGE_REPLACES_CALL_ID);
+ kz_set_tweak(KZ_TWEAK_BRIDGE_VARIABLES);
+ kz_set_tweak(KZ_TWEAK_RESTORE_CALLER_ID_ON_BLIND_XFER);
+
+
+
+ if ((child = switch_xml_child(cfg, "settings"))) {
+ for (param = switch_xml_child(child, "param"); param; param = param->next) {
+ char *var = (char *) switch_xml_attr_soft(param, "name");
+ char *val = (char *) switch_xml_attr_soft(param, "value");
+
+ if (!strcmp(var, "listen-ip")) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set bind ip address: %s\n", val);
+ set_pref_ip(val);
+ } else if (!strcmp(var, "listen-port")) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set bind port: %s\n", val);
+ kazoo_globals.port = atoi(val);
+ } else if (!strcmp(var, "cookie")) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set cookie: %s\n", val);
+ set_pref_ei_cookie(val);
+ } else if (!strcmp(var, "cookie-file")) {
+ if (read_cookie_from_file(val) == 1) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to read cookie from %s\n", val);
+ }
+ } else if (!strcmp(var, "nodename")) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set node name: %s\n", val);
+ set_pref_ei_nodename(val);
+ } else if (!strcmp(var, "shortname")) {
+ kazoo_globals.ei_shortname = switch_true(val);
+ } else if (!strcmp(var, "kazoo-var-prefix")) {
+ kazoo_var_prefix = switch_core_strdup(kazoo_globals.pool, val);
+ } else if (!strcmp(var, "set-profile-vars-prefix")) {
+ profile_vars_prefix = switch_core_strdup(kazoo_globals.pool, val);
+ } else if (!strcmp(var, "compat-rel")) {
+ if (atoi(val) >= 7)
+ kazoo_globals.ei_compat_rel = atoi(val);
+ else
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid compatibility release '%s' specified\n", val);
+ } else if (!strcmp(var, "nat-map")) {
+ kazoo_globals.nat_map = switch_true(val);
+ } else if (!strcmp(var, "send-all-headers")) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set send-all-headers: %s\n", val);
+ kazoo_globals.send_all_headers = switch_true(val);
+ } else if (!strcmp(var, "send-all-private-headers")) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set send-all-private-headers: %s\n", val);
+ kazoo_globals.send_all_private_headers = switch_true(val);
+ } else if (!strcmp(var, "connection-timeout")) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set connection-timeout: %s\n", val);
+ kazoo_globals.connection_timeout = atoi(val);
+ } else if (!strcmp(var, "receive-timeout")) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set receive-timeout: %s\n", val);
+ kazoo_globals.receive_timeout = atoi(val);
+ } else if (!strcmp(var, "receive-msg-preallocate")) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set receive-msg-preallocate: %s\n", val);
+ kazoo_globals.receive_msg_preallocate = atoi(val);
+ } else if (!strcmp(var, "event-stream-preallocate")) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set event-stream-preallocate: %s\n", val);
+ kazoo_globals.event_stream_preallocate = atoi(val);
+ } else if (!strcmp(var, "send-msg-batch-size")) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set send-msg-batch-size: %s\n", val);
+ kazoo_globals.send_msg_batch = atoi(val);
+ } else if (!strcmp(var, "event-stream-framing")) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set event-stream-framing: %s\n", val);
+ kazoo_globals.event_stream_framing = atoi(val);
+ } else if (!strcmp(var, "io-fault-tolerance")) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set io-fault-tolerance: %s\n", val);
+ kazoo_globals.io_fault_tolerance = atoi(val);
+ } else if (!strcmp(var, "num-worker-threads")) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set num-worker-threads: %s\n", val);
+ kazoo_globals.num_worker_threads = atoi(val);
+ } else if (!strcmp(var, "json-term-encoding")) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set json-term-encoding: %s\n", val);
+ if(!strcmp(val, "map")) {
+ kazoo_globals.json_encoding = ERLANG_MAP;
+ }
+ } else if (!strcmp(var, "legacy-events")) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set legacy-events: %s\n", val);
+ kazoo_globals.legacy_events = switch_true(val);
+ }
+ }
+ }
+
+ if ((child = switch_xml_child(cfg, "tweaks"))) {
+ for (param = switch_xml_child(child, "tweak"); param; param = param->next) {
+ kz_tweak_t tweak = KZ_TWEAK_MAX;
+ char *var = (char *) switch_xml_attr_soft(param, "name");
+ char *val = (char *) switch_xml_attr_soft(param, "value");
+ if(var && val && kz_name_tweak(var, &tweak) == SWITCH_STATUS_SUCCESS) {
+ if(switch_true(val)) {
+ kz_set_tweak(tweak);
+ } else {
+ kz_clear_tweak(tweak);
+ }
+ }
+ }
+ }
+
+ if ((child = switch_xml_child(cfg, "variables"))) {
+ for (param = switch_xml_child(child, "variable"); param; param = param->next) {
+ char *var = (char *) switch_xml_attr_soft(param, "name");
+ char *val = (char *) switch_xml_attr_soft(param, "value");
+ if(var && val) {
+ switch_core_set_variable(var, val);
+ }
+ }
+ }
+
+ if ((child = switch_xml_child(cfg, "event-filter"))) {
+ switch_hash_t *filter;
+
+ switch_core_hash_init(&filter);
+ for (param = switch_xml_child(child, "header"); param; param = param->next) {
+ char *var = (char *) switch_xml_attr_soft(param, "name");
+ switch_core_hash_insert(filter, var, "1");
+ }
+ kazoo_globals.event_filter = filter;
+ }
+
+ if (kazoo_globals.receive_msg_preallocate < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid receive message preallocate value, disabled\n");
+ kazoo_globals.receive_msg_preallocate = 0;
+ }
+
+ if (kazoo_globals.event_stream_preallocate < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid event stream preallocate value, disabled\n");
+ kazoo_globals.event_stream_preallocate = 0;
+ }
+
+ if (kazoo_globals.send_msg_batch < 1) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid send message batch size, reverting to default\n");
+ kazoo_globals.send_msg_batch = 10;
+ }
+
+ if (kazoo_globals.io_fault_tolerance < 1) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid I/O fault tolerance, reverting to default\n");
+ kazoo_globals.io_fault_tolerance = 10;
+ }
+
+ if (!kazoo_globals.event_filter) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Event filter not found in configuration, using default\n");
+ kazoo_globals.event_filter = create_default_filter();
+ }
+
+ if (kazoo_globals.event_stream_framing < 1 || kazoo_globals.event_stream_framing > 4) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid event stream framing value, using default\n");
+ kazoo_globals.event_stream_framing = 2;
+ }
+
+ if (zstr(kazoo_var_prefix)) {
+ kazoo_var_prefix = switch_core_strdup(kazoo_globals.pool, "ecallmgr_;cav_");
+ }
+
+ if (zstr(profile_vars_prefix)) {
+ profile_vars_prefix = switch_core_strdup(kazoo_globals.pool, "effective_;origination_");
+ }
+
+ kazoo_globals.kazoo_var_prefixes = switch_core_alloc(kazoo_globals.pool, sizeof(char*) * KZ_MAX_SEPARATE_STRINGS);
+ array_len = switch_separate_string(kazoo_var_prefix, ';', sep_array, KZ_MAX_SEPARATE_STRINGS - 1);
+ for(i=0; i < array_len; i++) {
+ char var[100];
+ sprintf(var, "variable_%s", sep_array[i]);
+ kazoo_globals.kazoo_var_prefixes[i] = switch_core_strdup(kazoo_globals.pool, var);
+ }
+
+ kazoo_globals.profile_vars_prefixes = switch_core_alloc(kazoo_globals.pool, sizeof(char*) * KZ_MAX_SEPARATE_STRINGS);
+ array_len = switch_separate_string(profile_vars_prefix, ';', sep_array, KZ_MAX_SEPARATE_STRINGS - 1);
+ for(i=0; i < array_len; i++) {
+ kazoo_globals.profile_vars_prefixes[i] = switch_core_strdup(kazoo_globals.pool, sep_array[i]);
+ }
+
+ if (!kazoo_globals.num_worker_threads) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Number of worker threads not found in configuration, using default\n");
+ kazoo_globals.num_worker_threads = 10;
+ }
+
+ if (zstr(kazoo_globals.ip)) {
+ set_pref_ip("0.0.0.0");
+ }
+
+ if (zstr(kazoo_globals.ei_cookie)) {
+ int res;
+ char *home_dir = getenv("HOME");
+ char path_buf[1024];
+
+ if (!zstr(home_dir)) {
+ /* $HOME/.erlang.cookie */
+ switch_snprintf(path_buf, sizeof (path_buf), "%s%s%s", home_dir, SWITCH_PATH_SEPARATOR, ".erlang.cookie");
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Checking for cookie at path: %s\n", path_buf);
+
+ res = read_cookie_from_file(path_buf);
+ if (res) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "No cookie or valid cookie file specified, using default cookie\n");
+ set_pref_ei_cookie("ClueCon");
+ }
+ }
+ }
+
+ if (!kazoo_globals.ei_nodename) {
+ set_pref_ei_nodename("freeswitch");
+ }
+
+ if (!kazoo_globals.nat_map) {
+ kazoo_globals.nat_map = 0;
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t kazoo_config_handlers(switch_xml_t cfg)
+{
+ switch_xml_t def = NULL;
+ switch_xml_t child, param;
+ char* xml = NULL;
+ kazoo_config_ptr definitions = NULL, fetch_handlers = NULL, event_handlers = NULL;
+ kazoo_event_profile_ptr events = NULL;
+
+ xml = strndup(kz_default_config, kz_default_config_size);
+ def = switch_xml_parse_str_dup(xml);
+
+ kz_xml_process(def);
+ kz_xml_process(cfg);
+
+ if ((child = switch_xml_child(cfg, "variables"))) {
+ for (param = switch_xml_child(child, "variable"); param; param = param->next) {
+ char *var = (char *) switch_xml_attr_soft(param, "name");
+ char *val = (char *) switch_xml_attr_soft(param, "value");
+ if(var && val) {
+ switch_core_set_variable(var, val);
+ }
+ }
+ } else if ((child = switch_xml_child(def, "variables"))) {
+ for (param = switch_xml_child(child, "variable"); param; param = param->next) {
+ char *var = (char *) switch_xml_attr_soft(param, "name");
+ char *val = (char *) switch_xml_attr_soft(param, "value");
+ if(var && val) {
+ switch_core_set_variable(var, val);
+ }
+ }
+ }
+
+ definitions = kazoo_config_definitions(cfg);
+ if(definitions == NULL) {
+ if(kazoo_globals.definitions == NULL) {
+ definitions = kazoo_config_definitions(def);
+ } else {
+ definitions = kazoo_globals.definitions;
+ }
+ }
+
+ fetch_handlers = kazoo_config_fetch_handlers(definitions, cfg);
+ if(fetch_handlers == NULL) {
+ if(kazoo_globals.fetch_handlers == NULL) {
+ fetch_handlers = kazoo_config_fetch_handlers(definitions, def);
+ } else {
+ fetch_handlers = kazoo_globals.fetch_handlers;
+ }
+ }
+
+ event_handlers = kazoo_config_event_handlers(definitions, cfg);
+ if(event_handlers == NULL) {
+ if(kazoo_globals.event_handlers == NULL) {
+ event_handlers = kazoo_config_event_handlers(definitions, def);
+ } else {
+ event_handlers = kazoo_globals.event_handlers;
+ }
+ }
+
+ if(event_handlers != NULL) {
+ events = (kazoo_event_profile_ptr) switch_core_hash_find(event_handlers->hash, "default");
+ }
+
+ if(events == NULL) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to get default handler for events\n");
+ if(kazoo_globals.event_handlers != event_handlers) destroy_config(&event_handlers);
+ if(kazoo_globals.fetch_handlers != fetch_handlers) destroy_config(&fetch_handlers);
+ if(kazoo_globals.definitions != definitions) destroy_config(&definitions);
+ switch_xml_free(def);
+ switch_safe_free(xml);
+ return SWITCH_STATUS_GENERR;
+ }
+
+ if(kazoo_globals.events != events) {
+ bind_event_profiles(events->events);
+ kazoo_globals.events = events;
+ }
+
+ if(kazoo_globals.event_handlers != event_handlers) {
+ kazoo_config_ptr tmp = kazoo_globals.event_handlers;
+ kazoo_globals.event_handlers = event_handlers;
+ destroy_config(&tmp);
+ }
+
+ if(kazoo_globals.fetch_handlers != fetch_handlers) {
+ kazoo_config_ptr tmp = kazoo_globals.fetch_handlers;
+ kazoo_globals.fetch_handlers = fetch_handlers;
+ rebind_fetch_profiles(fetch_handlers);
+ destroy_config(&tmp);
+ }
+
+ if(kazoo_globals.definitions != definitions) {
+ kazoo_config_ptr tmp = kazoo_globals.definitions;
+ kazoo_globals.definitions = definitions;
+ destroy_config(&tmp);
+ }
+
+
+ switch_xml_free(def);
+ switch_safe_free(xml);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t kazoo_load_config()
+{
+ char *cf = "kazoo.conf";
+ switch_xml_t cfg, xml;
+ if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to open configuration file %s\n", cf);
+ return SWITCH_STATUS_FALSE;
+ } else {
+ kazoo_ei_config(cfg);
+ kazoo_config_handlers(cfg);
+ switch_xml_free(xml);
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+void kazoo_destroy_config()
+{
+ destroy_config(&kazoo_globals.event_handlers);
+ destroy_config(&kazoo_globals.fetch_handlers);
+ destroy_config(&kazoo_globals.definitions);
+}
+
+switch_status_t kazoo_config_events(kazoo_config_ptr definitions, switch_memory_pool_t *pool, switch_xml_t cfg, kazoo_event_profile_ptr profile)
+{
+ switch_xml_t events, event;
+ kazoo_event_ptr prv = NULL, cur = NULL;
+
+
+ if ((events = switch_xml_child(cfg, "events")) != NULL) {
+ for (event = switch_xml_child(events, "event"); event; event = event->next) {
+ const char *var = switch_xml_attr(event, "name");
+ cur = (kazoo_event_ptr) switch_core_alloc(pool, sizeof(kazoo_event_t));
+ memset(cur, 0, sizeof(kazoo_event_t));
+ if(prv == NULL) {
+ profile->events = prv = cur;
+ } else {
+ prv->next = cur;
+ prv = cur;
+ }
+ cur->profile = profile;
+ cur->name = switch_core_strdup(pool, var);
+ kazoo_config_filters(pool, event, &cur->filter);
+ kazoo_config_fields(definitions, pool, event, &cur->fields);
+
+ }
+
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+
+}
+
+
+switch_status_t kazoo_config_fetch_handler(kazoo_config_ptr definitions, kazoo_config_ptr root, switch_xml_t cfg, kazoo_fetch_profile_ptr *ptr)
+{
+ kazoo_fetch_profile_ptr profile = NULL;
+ switch_xml_t params, param;
+ switch_xml_section_t fetch_section;
+ int fetch_timeout = 2000000;
+ switch_memory_pool_t *pool = NULL;
+
+ char *name = (char *) switch_xml_attr_soft(cfg, "name");
+ if (zstr(name)) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "missing name in profile\n");
+ return SWITCH_STATUS_GENERR;
+ }
+
+ if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "error allocation pool for new profile : %s\n", name);
+ return SWITCH_STATUS_GENERR;
+ }
+
+ profile = switch_core_alloc(pool, sizeof(kazoo_fetch_profile_t));
+ profile->pool = pool;
+ profile->root = root;
+ profile->name = switch_core_strdup(profile->pool, name);
+
+ fetch_section = switch_xml_parse_section_string(name);
+
+ if ((params = switch_xml_child(cfg, "params")) != NULL) {
+ for (param = switch_xml_child(params, "param"); param; param = param->next) {
+ char *var = (char *) switch_xml_attr_soft(param, "name");
+ char *val = (char *) switch_xml_attr_soft(param, "value");
+
+ if (!var) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Profile[%s] param missing 'name' attribute\n", name);
+ continue;
+ }
+
+ if (!val) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Profile[%s] param[%s] missing 'value' attribute\n", name, var);
+ continue;
+ }
+
+ if (!strncmp(var, "fetch-timeout", 13)) {
+ fetch_timeout = atoi(val);
+ } else if (!strncmp(var, "fetch-section", 13)) {
+ fetch_section = switch_xml_parse_section_string(val);
+ }
+ }
+ }
+
+ if (fetch_section == SWITCH_XML_SECTION_RESULT) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Fetch Profile[%s] invalid fetch-section: %s\n", name, switch_xml_toxml(cfg, SWITCH_FALSE));
+ goto err;
+ }
+
+
+ profile->fetch_timeout = fetch_timeout;
+ profile->section = fetch_section;
+ kazoo_config_fields(definitions, pool, cfg, &profile->fields);
+ kazoo_config_loglevels(pool, cfg, &profile->logging);
+
+ if(root) {
+ if ( switch_core_hash_insert(root->hash, name, (void *) profile) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to insert new fetch profile [%s] into kazoo profile hash\n", name);
+ goto err;
+ }
+ }
+
+ if(ptr)
+ *ptr = profile;
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "fetch handler profile %s successfully configured\n", name);
+ return SWITCH_STATUS_SUCCESS;
+
+ err:
+ /* Cleanup */
+ if(pool) {
+ switch_core_destroy_memory_pool(&pool);
+ }
+ return SWITCH_STATUS_GENERR;
+
+}
+
+switch_status_t kazoo_config_event_handler(kazoo_config_ptr definitions, kazoo_config_ptr root, switch_xml_t cfg, kazoo_event_profile_ptr *ptr)
+{
+ kazoo_event_profile_ptr profile = NULL;
+ switch_memory_pool_t *pool = NULL;
+
+ char *name = (char *) switch_xml_attr_soft(cfg, "name");
+ if (zstr(name)) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "missing name in profile\n");
+ return SWITCH_STATUS_GENERR;
+ }
+
+ if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "error allocation pool for new profile : %s\n", name);
+ return SWITCH_STATUS_GENERR;
+ }
+
+ profile = switch_core_alloc(pool, sizeof(kazoo_event_profile_t));
+ profile->pool = pool;
+ profile->root = root;
+ profile->name = switch_core_strdup(profile->pool, name);
+
+ kazoo_config_filters(pool, cfg, &profile->filter);
+ kazoo_config_fields(definitions, pool, cfg, &profile->fields);
+ kazoo_config_events(definitions, pool, cfg, profile);
+ kazoo_config_loglevels(pool, cfg, &profile->logging);
+
+ if(root) {
+ if ( switch_core_hash_insert(root->hash, name, (void *) profile) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to insert new profile [%s] into kazoo profile hash\n", name);
+ goto err;
+ }
+ }
+
+ if(ptr)
+ *ptr = profile;
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "event handler profile %s successfully configured\n", name);
+ return SWITCH_STATUS_SUCCESS;
+
+ err:
+ /* Cleanup */
+ if(pool) {
+ switch_core_destroy_memory_pool(&pool);
+ }
+ return SWITCH_STATUS_GENERR;
+
+}
+
+
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4
+ */
diff --git a/src/mod/event_handlers/mod_kazoo/kazoo_ei_utils.c b/src/mod/event_handlers/mod_kazoo/kazoo_ei_utils.c
new file mode 100644
index 0000000000..7a2e62c925
--- /dev/null
+++ b/src/mod/event_handlers/mod_kazoo/kazoo_ei_utils.c
@@ -0,0 +1,1001 @@
+/*
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005-2012, Anthony Minessale II
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ *
+ * The Initial Developer of the Original Code is
+ * Anthony Minessale II
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Anthony Minessale II
+ * Andrew Thompson
+ * Rob Charlton
+ * Karl Anderson
+ *
+ * Original from mod_erlang_event.
+ * ei_helpers.c -- helper functions for ei
+ *
+ */
+#include "mod_kazoo.h"
+
+/* Stolen from code added to ei in R12B-5.
+ * Since not everyone has this version yet;
+ * provide our own version.
+ * */
+
+#define put8(s,n) do { \
+ (s)[0] = (char)((n) & 0xff); \
+ (s) += 1; \
+ } while (0)
+
+#define put32be(s,n) do { \
+ (s)[0] = ((n) >> 24) & 0xff; \
+ (s)[1] = ((n) >> 16) & 0xff; \
+ (s)[2] = ((n) >> 8) & 0xff; \
+ (s)[3] = (n) & 0xff; \
+ (s) += 4; \
+ } while (0)
+
+#ifdef EI_DEBUG
+static void ei_x_print_reg_msg(ei_x_buff *buf, char *dest, int send) {
+ char *mbuf = NULL;
+ int i = 1;
+
+ ei_s_print_term(&mbuf, buf->buff, &i);
+
+ if (send) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Encoded term %s to '%s'\n", mbuf, dest);
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Decoded term %s for '%s'\n", mbuf, dest);
+ }
+
+ free(mbuf);
+}
+
+static void ei_x_print_msg(ei_x_buff *buf, erlang_pid *pid, int send) {
+ char *pbuf = NULL;
+ int i = 0;
+ ei_x_buff pidbuf;
+
+ ei_x_new(&pidbuf);
+ ei_x_encode_pid(&pidbuf, pid);
+
+ ei_s_print_term(&pbuf, pidbuf.buff, &i);
+
+ ei_x_print_reg_msg(buf, pbuf, send);
+ free(pbuf);
+}
+#endif
+
+void ei_encode_switch_event_headers(ei_x_buff *ebuf, switch_event_t *event) {
+ ei_encode_switch_event_headers_2(ebuf, event, 1);
+}
+
+void ei_encode_switch_event_headers_2(ei_x_buff *ebuf, switch_event_t *event, int encode) {
+ switch_event_header_t *hp;
+ char *uuid = switch_event_get_header(event, "unique-id");
+ int i;
+
+ for (i = 0, hp = event->headers; hp; hp = hp->next, i++);
+
+ if (event->body)
+ i++;
+
+ ei_x_encode_list_header(ebuf, i + 1);
+
+ if (uuid) {
+ char *unique_id = switch_event_get_header(event, "unique-id");
+ ei_x_encode_binary(ebuf, unique_id, strlen(unique_id));
+ } else {
+ ei_x_encode_atom(ebuf, "undefined");
+ }
+
+ for (hp = event->headers; hp; hp = hp->next) {
+ ei_x_encode_tuple_header(ebuf, 2);
+ ei_x_encode_binary(ebuf, hp->name, strlen(hp->name));
+ if(encode) {
+ switch_url_decode(hp->value);
+ }
+ ei_x_encode_binary(ebuf, hp->value, strlen(hp->value));
+ }
+
+ if (event->body) {
+ ei_x_encode_tuple_header(ebuf, 2);
+ ei_x_encode_binary(ebuf, "body", strlen("body"));
+ ei_x_encode_binary(ebuf, event->body, strlen(event->body));
+ }
+
+ ei_x_encode_empty_list(ebuf);
+}
+
+int ei_json_child_count(cJSON *JObj)
+{
+ int mask = cJSON_False
+ | cJSON_True
+ | cJSON_NULL
+ | cJSON_Number
+ | cJSON_String
+ | cJSON_Array
+ | cJSON_Object
+ | cJSON_Raw;
+
+ cJSON *item = JObj->child;
+ int i = 0;
+ while(item) {
+ if(item->type & mask)
+ i++;
+ item = item->next;
+ }
+ return i;
+
+}
+
+void ei_encode_json_array(ei_x_buff *ebuf, cJSON *JObj) {
+ cJSON *item;
+ int count = ei_json_child_count(JObj);
+
+ ei_x_encode_list_header(ebuf, count);
+ if(count == 0)
+ return;
+
+ item = JObj->child;
+ while(item) {
+ switch(item->type) {
+ case cJSON_String:
+ ei_x_encode_binary(ebuf, item->valuestring, strlen(item->valuestring));
+ break;
+
+ case cJSON_Number:
+ ei_x_encode_double(ebuf, item->valuedouble);
+ break;
+
+ case cJSON_True:
+ ei_x_encode_boolean(ebuf, 1);
+ break;
+
+ case cJSON_False:
+ ei_x_encode_boolean(ebuf, 0);
+ break;
+
+ case cJSON_Object:
+ ei_encode_json(ebuf, item);
+ break;
+
+ case cJSON_Array:
+ ei_encode_json_array(ebuf, item);
+ break;
+
+ case cJSON_Raw:
+ {
+ cJSON *Decoded = cJSON_Parse(item->valuestring);
+ if(!Decoded) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ERROR DECODING RAW JSON %s\n", item->valuestring);
+ ei_x_encode_tuple_header(ebuf, 0);
+ } else {
+ ei_encode_json(ebuf, Decoded);
+ cJSON_Delete(Decoded);
+ }
+ break;
+ }
+
+ case cJSON_NULL:
+ ei_x_encode_atom(ebuf, "null");
+ break;
+
+ default:
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "NOT ENCODED %i\n", item->type);
+ break;
+
+ }
+ item = item->next;
+ }
+
+ ei_x_encode_empty_list(ebuf);
+
+}
+
+void ei_encode_json(ei_x_buff *ebuf, cJSON *JObj) {
+ cJSON *item;
+ int count = ei_json_child_count(JObj);
+
+ if(kazoo_globals.json_encoding == ERLANG_TUPLE) {
+ ei_x_encode_tuple_header(ebuf, 1);
+ ei_x_encode_list_header(ebuf, count);
+ } else {
+ ei_x_encode_map_header(ebuf, count);
+ }
+
+ if(count == 0)
+ return;
+
+ item = JObj->child;
+ while(item) {
+ if(kazoo_globals.json_encoding == ERLANG_TUPLE) {
+ ei_x_encode_tuple_header(ebuf, 2);
+ }
+ ei_x_encode_binary(ebuf, item->string, strlen(item->string));
+
+ switch(item->type) {
+ case cJSON_String:
+ ei_x_encode_binary(ebuf, item->valuestring, strlen(item->valuestring));
+ break;
+
+ case cJSON_Number:
+ if ((fabs(((double)item->valueint) - item->valuedouble) <= DBL_EPSILON)
+ && (item->valuedouble <= INT_MAX)
+ && (item->valuedouble >= INT_MIN)) {
+ ei_x_encode_longlong(ebuf, item->valueint);
+ } else {
+ ei_x_encode_double(ebuf, item->valuedouble);
+ }
+ break;
+
+ case cJSON_True:
+ ei_x_encode_boolean(ebuf, 1);
+ break;
+
+ case cJSON_False:
+ ei_x_encode_boolean(ebuf, 0);
+ break;
+
+ case cJSON_Object:
+ ei_encode_json(ebuf, item);
+ break;
+
+ case cJSON_Array:
+ ei_encode_json_array(ebuf, item);
+ break;
+
+ case cJSON_Raw:
+ {
+ cJSON *Decoded = cJSON_Parse(item->valuestring);
+ if(!Decoded) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ERROR DECODING RAW JSON %s\n", item->valuestring);
+ ei_x_encode_tuple_header(ebuf, 0);
+ } else {
+ ei_encode_json(ebuf, Decoded);
+ cJSON_Delete(Decoded);
+ }
+ break;
+ }
+
+ case cJSON_NULL:
+ ei_x_encode_atom(ebuf, "null");
+ break;
+
+ default:
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "NOT ENCODED %i\n", item->type);
+ break;
+
+ }
+ item = item->next;
+ }
+
+ if(kazoo_globals.json_encoding == ERLANG_TUPLE) {
+ ei_x_encode_empty_list(ebuf);
+ }
+
+}
+
+void close_socket(switch_socket_t ** sock) {
+ if (*sock) {
+ switch_socket_shutdown(*sock, SWITCH_SHUTDOWN_READWRITE);
+ switch_socket_close(*sock);
+ *sock = NULL;
+ }
+}
+
+void close_socketfd(int *sockfd) {
+ if (*sockfd) {
+ shutdown(*sockfd, SHUT_RDWR);
+ close(*sockfd);
+ }
+}
+
+switch_socket_t *create_socket_with_port(switch_memory_pool_t *pool, switch_port_t port) {
+ switch_sockaddr_t *sa;
+ switch_socket_t *socket;
+
+ if(switch_sockaddr_info_get(&sa, kazoo_globals.ip, SWITCH_UNSPEC, port, 0, pool)) {
+ return NULL;
+ }
+
+ if (switch_socket_create(&socket, switch_sockaddr_get_family(sa), SOCK_STREAM, SWITCH_PROTO_TCP, pool)) {
+ return NULL;
+ }
+
+ if (switch_socket_opt_set(socket, SWITCH_SO_REUSEADDR, 1)) {
+ return NULL;
+ }
+
+ if (switch_socket_bind(socket, sa)) {
+ return NULL;
+ }
+
+ if (switch_socket_listen(socket, 5)){
+ return NULL;
+ }
+
+ switch_getnameinfo(&kazoo_globals.hostname, sa, 0);
+
+ if (kazoo_globals.nat_map && switch_nat_get_type()) {
+ switch_nat_add_mapping(port, SWITCH_NAT_TCP, NULL, SWITCH_FALSE);
+ }
+
+ return socket;
+}
+
+switch_socket_t *create_socket(switch_memory_pool_t *pool) {
+ return create_socket_with_port(pool, 0);
+
+}
+
+switch_status_t create_ei_cnode(const char *ip_addr, const char *name, struct ei_cnode_s *ei_cnode) {
+ char hostname[EI_MAXHOSTNAMELEN + 1] = "";
+ char nodename[MAXNODELEN + 1];
+ char cnodename[EI_MAXALIVELEN + 1];
+ //EI_MAX_COOKIE_SIZE+1
+ char *atsign;
+
+ /* copy the erlang interface nodename into something we can modify */
+ strncpy(cnodename, name, EI_MAXALIVELEN);
+
+ if ((atsign = strchr(cnodename, '@'))) {
+ /* we got a qualified node name, don't guess the host/domain */
+ snprintf(nodename, MAXNODELEN + 1, "%s", kazoo_globals.ei_nodename);
+ /* truncate the alivename at the @ */
+ *atsign = '\0';
+ } else {
+ if (zstr(kazoo_globals.hostname) || !strncasecmp(kazoo_globals.ip, "0.0.0.0", 7) || !strncasecmp(kazoo_globals.ip, "::", 2)) {
+ memcpy(hostname, switch_core_get_hostname(), EI_MAXHOSTNAMELEN);
+ } else {
+ memcpy(hostname, kazoo_globals.hostname, EI_MAXHOSTNAMELEN);
+ }
+
+ snprintf(nodename, MAXNODELEN + 1, "%s@%s", kazoo_globals.ei_nodename, hostname);
+ }
+
+ if (kazoo_globals.ei_shortname) {
+ char *off;
+ if ((off = strchr(nodename, '.'))) {
+ *off = '\0';
+ }
+ }
+
+ /* init the ec stuff */
+ if (ei_connect_xinit(ei_cnode, hostname, cnodename, nodename, (Erl_IpAddr) ip_addr, kazoo_globals.ei_cookie, 0) < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to initialize the erlang interface connection structure\n");
+ return SWITCH_STATUS_FALSE;
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t ei_compare_pids(const erlang_pid *pid1, const erlang_pid *pid2) {
+ if ((!strcmp(pid1->node, pid2->node))
+ && pid1->creation == pid2->creation
+ && pid1->num == pid2->num
+ && pid1->serial == pid2->serial) {
+ return SWITCH_STATUS_SUCCESS;
+ } else {
+ return SWITCH_STATUS_FALSE;
+ }
+}
+
+void ei_link(ei_node_t *ei_node, erlang_pid * from, erlang_pid * to) {
+ char msgbuf[2048];
+ char *s;
+ int index = 0;
+
+ index = 5; /* max sizes: */
+ ei_encode_version(msgbuf, &index); /* 1 */
+ ei_encode_tuple_header(msgbuf, &index, 3);
+ ei_encode_long(msgbuf, &index, ERL_LINK);
+ ei_encode_pid(msgbuf, &index, from); /* 268 */
+ ei_encode_pid(msgbuf, &index, to); /* 268 */
+
+ /* 5 byte header missing */
+ s = msgbuf;
+ put32be(s, index - 4); /* 4 */
+ put8(s, ERL_PASS_THROUGH); /* 1 */
+ /* sum: 542 */
+
+ if (write(ei_node->nodefd, msgbuf, index) == -1) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Failed to link to process on %s\n", ei_node->peer_nodename);
+ }
+}
+
+void ei_encode_switch_event(ei_x_buff *ebuf, switch_event_t *event) {
+ ei_x_encode_tuple_header(ebuf, 2);
+ ei_x_encode_atom(ebuf, "event");
+ ei_encode_switch_event_headers(ebuf, event);
+}
+
+int ei_helper_send(ei_node_t *ei_node, erlang_pid *to, ei_x_buff *buf) {
+ int ret = 0;
+
+ if (ei_node->nodefd) {
+#ifdef EI_DEBUG
+ ei_x_print_msg(buf, to, 1);
+#endif
+ ret = ei_send(ei_node->nodefd, to, buf->buff, buf->index);
+ }
+
+ return ret;
+}
+
+int ei_decode_atom_safe(char *buf, int *index, char *dst) {
+ int type, size;
+
+ ei_get_type(buf, index, &type, &size);
+
+ if (type != ERL_ATOM_EXT) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unexpected erlang term type %d (size %d), needed atom\n", type, size);
+ return -1;
+ } else if (size > MAXATOMLEN) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Requested decoding of atom with size %d into a buffer of size %d\n", size, MAXATOMLEN);
+ return -1;
+ } else {
+ return ei_decode_atom(buf, index, dst);
+ }
+}
+
+int ei_decode_string_or_binary(char *buf, int *index, char **dst) {
+ int type, size, res;
+ long len;
+
+ ei_get_type(buf, index, &type, &size);
+
+ if (type != ERL_STRING_EXT && type != ERL_BINARY_EXT && type != ERL_LIST_EXT && type != ERL_NIL_EXT) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unexpected erlang term type %d (size %d), needed binary or string\n", type, size);
+ return -1;
+ }
+
+ *dst = malloc(size + 1);
+
+ if (type == ERL_NIL_EXT) {
+ res = 0;
+ **dst = '\0';
+ } else if (type == ERL_BINARY_EXT) {
+ res = ei_decode_binary(buf, index, *dst, &len);
+ (*dst)[len] = '\0';
+ } else {
+ res = ei_decode_string(buf, index, *dst);
+ }
+
+ return res;
+}
+
+int ei_decode_string_or_binary_limited(char *buf, int *index, int maxsize, char *dst) {
+ int type, size, res;
+ long len;
+
+ ei_get_type(buf, index, &type, &size);
+
+ if (type != ERL_STRING_EXT && type != ERL_BINARY_EXT && type != ERL_LIST_EXT && type != ERL_NIL_EXT) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unexpected erlang term type %d (size %d), needed binary or string\n", type, size);
+ return -1;
+ }
+
+ if (size > maxsize) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Requested decoding of %s with size %d into a buffer of size %d\n",
+ type == ERL_BINARY_EXT ? "binary" : "string", size, maxsize);
+ return -1;
+ }
+
+ if (type == ERL_NIL_EXT) {
+ res = 0;
+ *dst = '\0';
+ } else if (type == ERL_BINARY_EXT) {
+ res = ei_decode_binary(buf, index, dst, &len);
+ dst[len] = '\0'; /* binaries aren't null terminated */
+ } else {
+ res = ei_decode_string(buf, index, dst);
+ }
+
+ return res;
+}
+
+
+switch_status_t create_acceptor() {
+ switch_sockaddr_t *sa;
+ uint16_t port;
+ char ipbuf[48];
+ const char *ip_addr;
+
+#if ERLANG_MAJOR >= 10
+ ei_init();
+#endif
+
+ /* if the config has specified an erlang release compatibility then pass that along to the erlang interface */
+ if (kazoo_globals.ei_compat_rel) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Compatability with OTP R%d requested\n", kazoo_globals.ei_compat_rel);
+ ei_set_compat_rel(kazoo_globals.ei_compat_rel);
+ }
+
+ if (!(kazoo_globals.acceptor = create_socket_with_port(kazoo_globals.pool, kazoo_globals.port))) {
+ return SWITCH_STATUS_SOCKERR;
+ }
+
+ switch_socket_addr_get(&sa, SWITCH_FALSE, kazoo_globals.acceptor);
+
+ port = switch_sockaddr_get_port(sa);
+ ip_addr = switch_get_addr(ipbuf, sizeof (ipbuf), sa);
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Erlang connection acceptor listening on %s:%u\n", ip_addr, port);
+
+ /* try to initialize the erlang interface */
+ if (create_ei_cnode(ip_addr, kazoo_globals.ei_nodename, &kazoo_globals.ei_cnode) != SWITCH_STATUS_SUCCESS) {
+ return SWITCH_STATUS_SOCKERR;
+ }
+
+ /* tell the erlang port manager where we can be reached. this returns a file descriptor pointing to epmd or -1 */
+ if ((kazoo_globals.epmdfd = ei_publish(&kazoo_globals.ei_cnode, port)) == -1) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Failed to publish port to epmd, trying to start epmd via system()\n");
+ if (system("fs_epmd -daemon")) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
+ "Failed to start epmd manually! Is epmd in $PATH? If not, start it yourself or run an erl shell with -sname or -name\n");
+ return SWITCH_STATUS_SOCKERR;
+ }
+ switch_yield(100000);
+ if ((kazoo_globals.epmdfd = ei_publish(&kazoo_globals.ei_cnode, port)) == -1) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to publish port to epmd AGAIN\n");
+ return SWITCH_STATUS_SOCKERR;
+ }
+ }
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Connected to epmd and published erlang cnode name %s at port %d\n", kazoo_globals.ei_cnode.thisnodename, port);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+switch_hash_t *create_default_filter() {
+ switch_hash_t *filter;
+
+ switch_core_hash_init(&filter);
+
+ switch_core_hash_insert(filter, "Acquired-UUID", "1");
+ switch_core_hash_insert(filter, "action", "1");
+ switch_core_hash_insert(filter, "Action", "1");
+ switch_core_hash_insert(filter, "alt_event_type", "1");
+ switch_core_hash_insert(filter, "Answer-State", "1");
+ switch_core_hash_insert(filter, "Application", "1");
+ switch_core_hash_insert(filter, "Application-Data", "1");
+ switch_core_hash_insert(filter, "Application-Name", "1");
+ switch_core_hash_insert(filter, "Application-Response", "1");
+ switch_core_hash_insert(filter, "att_xfer_replaced_by", "1");
+ switch_core_hash_insert(filter, "Auth-Method", "1");
+ switch_core_hash_insert(filter, "Auth-Realm", "1");
+ switch_core_hash_insert(filter, "Auth-User", "1");
+ switch_core_hash_insert(filter, "Bridge-A-Unique-ID", "1");
+ switch_core_hash_insert(filter, "Bridge-B-Unique-ID", "1");
+ switch_core_hash_insert(filter, "Call-Direction", "1");
+ switch_core_hash_insert(filter, "Caller-Callee-ID-Name", "1");
+ switch_core_hash_insert(filter, "Caller-Callee-ID-Number", "1");
+ switch_core_hash_insert(filter, "Caller-Caller-ID-Name", "1");
+ switch_core_hash_insert(filter, "Caller-Caller-ID-Number", "1");
+ switch_core_hash_insert(filter, "Caller-Screen-Bit", "1");
+ switch_core_hash_insert(filter, "Caller-Privacy-Hide-Name", "1");
+ switch_core_hash_insert(filter, "Caller-Privacy-Hide-Number", "1");
+ switch_core_hash_insert(filter, "Caller-Context", "1");
+ switch_core_hash_insert(filter, "Caller-Controls", "1");
+ switch_core_hash_insert(filter, "Caller-Destination-Number", "1");
+ switch_core_hash_insert(filter, "Caller-Dialplan", "1");
+ switch_core_hash_insert(filter, "Caller-Network-Addr", "1");
+ switch_core_hash_insert(filter, "Caller-Unique-ID", "1");
+ switch_core_hash_insert(filter, "Call-ID", "1");
+ switch_core_hash_insert(filter, "Channel-Call-State", "1");
+ switch_core_hash_insert(filter, "Channel-Call-UUID", "1");
+ switch_core_hash_insert(filter, "Channel-Presence-ID", "1");
+ switch_core_hash_insert(filter, "Channel-State", "1");
+ switch_core_hash_insert(filter, "Chat-Permissions", "1");
+ switch_core_hash_insert(filter, "Conference-Name", "1");
+ switch_core_hash_insert(filter, "Conference-Profile-Name", "1");
+ switch_core_hash_insert(filter, "Conference-Unique-ID", "1");
+ switch_core_hash_insert(filter, "contact", "1");
+ switch_core_hash_insert(filter, "Detected-Tone", "1");
+ switch_core_hash_insert(filter, "dialog_state", "1");
+ switch_core_hash_insert(filter, "direction", "1");
+ switch_core_hash_insert(filter, "Distributed-From", "1");
+ switch_core_hash_insert(filter, "DTMF-Digit", "1");
+ switch_core_hash_insert(filter, "DTMF-Duration", "1");
+ switch_core_hash_insert(filter, "Event-Date-Timestamp", "1");
+ switch_core_hash_insert(filter, "Event-Name", "1");
+ switch_core_hash_insert(filter, "Event-Subclass", "1");
+ switch_core_hash_insert(filter, "expires", "1");
+ switch_core_hash_insert(filter, "Expires", "1");
+ switch_core_hash_insert(filter, "Ext-SIP-IP", "1");
+ switch_core_hash_insert(filter, "File", "1");
+ switch_core_hash_insert(filter, "FreeSWITCH-Hostname", "1");
+ switch_core_hash_insert(filter, "from", "1");
+ switch_core_hash_insert(filter, "Hunt-Destination-Number", "1");
+ switch_core_hash_insert(filter, "ip", "1");
+ switch_core_hash_insert(filter, "Message-Account", "1");
+ switch_core_hash_insert(filter, "metadata", "1");
+ switch_core_hash_insert(filter, "old_node_channel_uuid", "1");
+ switch_core_hash_insert(filter, "Other-Leg-Callee-ID-Name", "1");
+ switch_core_hash_insert(filter, "Other-Leg-Callee-ID-Number", "1");
+ switch_core_hash_insert(filter, "Other-Leg-Caller-ID-Name", "1");
+ switch_core_hash_insert(filter, "Other-Leg-Caller-ID-Number", "1");
+ switch_core_hash_insert(filter, "Other-Leg-Destination-Number", "1");
+ switch_core_hash_insert(filter, "Other-Leg-Direction", "1");
+ switch_core_hash_insert(filter, "Other-Leg-Unique-ID", "1");
+ switch_core_hash_insert(filter, "Other-Leg-Channel-Name", "1");
+ switch_core_hash_insert(filter, "Participant-Type", "1");
+ switch_core_hash_insert(filter, "Path", "1");
+ switch_core_hash_insert(filter, "profile_name", "1");
+ switch_core_hash_insert(filter, "Profiles", "1");
+ switch_core_hash_insert(filter, "proto-specific-event-name", "1");
+ switch_core_hash_insert(filter, "Raw-Application-Data", "1");
+ switch_core_hash_insert(filter, "realm", "1");
+ switch_core_hash_insert(filter, "Resigning-UUID", "1");
+ switch_core_hash_insert(filter, "set", "1");
+ switch_core_hash_insert(filter, "sip_auto_answer", "1");
+ switch_core_hash_insert(filter, "sip_auth_method", "1");
+ switch_core_hash_insert(filter, "sip_from_host", "1");
+ switch_core_hash_insert(filter, "sip_from_user", "1");
+ switch_core_hash_insert(filter, "sip_to_host", "1");
+ switch_core_hash_insert(filter, "sip_to_user", "1");
+ switch_core_hash_insert(filter, "sub-call-id", "1");
+ switch_core_hash_insert(filter, "technology", "1");
+ switch_core_hash_insert(filter, "to", "1");
+ switch_core_hash_insert(filter, "Unique-ID", "1");
+ switch_core_hash_insert(filter, "URL", "1");
+ switch_core_hash_insert(filter, "username", "1");
+ switch_core_hash_insert(filter, "variable_channel_is_moving", "1");
+ switch_core_hash_insert(filter, "variable_collected_digits", "1");
+ switch_core_hash_insert(filter, "variable_current_application", "1");
+ switch_core_hash_insert(filter, "variable_current_application_data", "1");
+ switch_core_hash_insert(filter, "variable_domain_name", "1");
+ switch_core_hash_insert(filter, "variable_effective_caller_id_name", "1");
+ switch_core_hash_insert(filter, "variable_effective_caller_id_number", "1");
+ switch_core_hash_insert(filter, "variable_holding_uuid", "1");
+ switch_core_hash_insert(filter, "variable_hold_music", "1");
+ switch_core_hash_insert(filter, "variable_media_group_id", "1");
+ switch_core_hash_insert(filter, "variable_originate_disposition", "1");
+ switch_core_hash_insert(filter, "variable_origination_uuid", "1");
+ switch_core_hash_insert(filter, "variable_playback_terminator_used", "1");
+ switch_core_hash_insert(filter, "variable_presence_id", "1");
+ switch_core_hash_insert(filter, "variable_record_ms", "1");
+ switch_core_hash_insert(filter, "variable_recovered", "1");
+ switch_core_hash_insert(filter, "variable_silence_hits_exhausted", "1");
+ switch_core_hash_insert(filter, "variable_sip_auth_realm", "1");
+ switch_core_hash_insert(filter, "variable_sip_from_host", "1");
+ switch_core_hash_insert(filter, "variable_sip_from_user", "1");
+ switch_core_hash_insert(filter, "variable_sip_from_tag", "1");
+ switch_core_hash_insert(filter, "variable_sip_h_X-AUTH-IP", "1");
+ switch_core_hash_insert(filter, "variable_sip_received_ip", "1");
+ switch_core_hash_insert(filter, "variable_sip_to_host", "1");
+ switch_core_hash_insert(filter, "variable_sip_to_user", "1");
+ switch_core_hash_insert(filter, "variable_sip_to_tag", "1");
+ switch_core_hash_insert(filter, "variable_sofia_profile_name", "1");
+ switch_core_hash_insert(filter, "variable_transfer_history", "1");
+ switch_core_hash_insert(filter, "variable_user_name", "1");
+ switch_core_hash_insert(filter, "variable_endpoint_disposition", "1");
+ switch_core_hash_insert(filter, "variable_originate_disposition", "1");
+ switch_core_hash_insert(filter, "variable_bridge_hangup_cause", "1");
+ switch_core_hash_insert(filter, "variable_hangup_cause", "1");
+ switch_core_hash_insert(filter, "variable_last_bridge_proto_specific_hangup_cause", "1");
+ switch_core_hash_insert(filter, "variable_proto_specific_hangup_cause", "1");
+ switch_core_hash_insert(filter, "VM-Call-ID", "1");
+ switch_core_hash_insert(filter, "VM-sub-call-id", "1");
+ switch_core_hash_insert(filter, "whistle_application_name", "1");
+ switch_core_hash_insert(filter, "whistle_application_response", "1");
+ switch_core_hash_insert(filter, "whistle_event_name", "1");
+ switch_core_hash_insert(filter, "kazoo_application_name", "1");
+ switch_core_hash_insert(filter, "kazoo_application_response", "1");
+ switch_core_hash_insert(filter, "kazoo_event_name", "1");
+ switch_core_hash_insert(filter, "sip_auto_answer_notify", "1");
+ switch_core_hash_insert(filter, "eavesdrop_group", "1");
+ switch_core_hash_insert(filter, "origination_caller_id_name", "1");
+ switch_core_hash_insert(filter, "origination_caller_id_number", "1");
+ switch_core_hash_insert(filter, "origination_callee_id_name", "1");
+ switch_core_hash_insert(filter, "origination_callee_id_number", "1");
+ switch_core_hash_insert(filter, "sip_auth_username", "1");
+ switch_core_hash_insert(filter, "sip_auth_password", "1");
+ switch_core_hash_insert(filter, "effective_caller_id_name", "1");
+ switch_core_hash_insert(filter, "effective_caller_id_number", "1");
+ switch_core_hash_insert(filter, "effective_callee_id_name", "1");
+ switch_core_hash_insert(filter, "effective_callee_id_number", "1");
+ switch_core_hash_insert(filter, "variable_destination_number", "1");
+ switch_core_hash_insert(filter, "variable_effective_callee_id_name", "1");
+ switch_core_hash_insert(filter, "variable_effective_callee_id_number", "1");
+ switch_core_hash_insert(filter, "variable_record_silence_hits", "1");
+ switch_core_hash_insert(filter, "variable_refer_uuid", "1");
+ switch_core_hash_insert(filter, "variable_sip_call_id", "1");
+ switch_core_hash_insert(filter, "variable_sip_h_Referred-By", "1");
+ switch_core_hash_insert(filter, "variable_sip_h_X-AUTH-PORT", "1");
+ switch_core_hash_insert(filter, "variable_sip_loopback_req_uri", "1");
+ switch_core_hash_insert(filter, "variable_sip_received_port", "1");
+ switch_core_hash_insert(filter, "variable_sip_refer_to", "1");
+ switch_core_hash_insert(filter, "variable_sip_req_host", "1");
+ switch_core_hash_insert(filter, "variable_sip_req_uri", "1");
+ switch_core_hash_insert(filter, "variable_transfer_source", "1");
+ switch_core_hash_insert(filter, "variable_uuid", "1");
+
+ /* Registration headers */
+ switch_core_hash_insert(filter, "call-id", "1");
+ switch_core_hash_insert(filter, "profile-name", "1");
+ switch_core_hash_insert(filter, "from-user", "1");
+ switch_core_hash_insert(filter, "from-host", "1");
+ switch_core_hash_insert(filter, "presence-hosts", "1");
+ switch_core_hash_insert(filter, "contact", "1");
+ switch_core_hash_insert(filter, "rpid", "1");
+ switch_core_hash_insert(filter, "status", "1");
+ switch_core_hash_insert(filter, "expires", "1");
+ switch_core_hash_insert(filter, "to-user", "1");
+ switch_core_hash_insert(filter, "to-host", "1");
+ switch_core_hash_insert(filter, "network-ip", "1");
+ switch_core_hash_insert(filter, "network-port", "1");
+ switch_core_hash_insert(filter, "username", "1");
+ switch_core_hash_insert(filter, "realm", "1");
+ switch_core_hash_insert(filter, "user-agent", "1");
+
+ switch_core_hash_insert(filter, "Hangup-Cause", "1");
+ switch_core_hash_insert(filter, "Unique-ID", "1");
+ switch_core_hash_insert(filter, "variable_switch_r_sdp", "1");
+ switch_core_hash_insert(filter, "variable_rtp_local_sdp_str", "1");
+ switch_core_hash_insert(filter, "variable_sip_to_uri", "1");
+ switch_core_hash_insert(filter, "variable_sip_from_uri", "1");
+ switch_core_hash_insert(filter, "variable_sip_user_agent", "1");
+ switch_core_hash_insert(filter, "variable_duration", "1");
+ switch_core_hash_insert(filter, "variable_billsec", "1");
+ switch_core_hash_insert(filter, "variable_billmsec", "1");
+ switch_core_hash_insert(filter, "variable_progresssec", "1");
+ switch_core_hash_insert(filter, "variable_progress_uepoch", "1");
+ switch_core_hash_insert(filter, "variable_progress_media_uepoch", "1");
+ switch_core_hash_insert(filter, "variable_start_uepoch", "1");
+ switch_core_hash_insert(filter, "variable_digits_dialed", "1");
+ switch_core_hash_insert(filter, "Member-ID", "1");
+ switch_core_hash_insert(filter, "Floor", "1");
+ switch_core_hash_insert(filter, "Video", "1");
+ switch_core_hash_insert(filter, "Hear", "1");
+ switch_core_hash_insert(filter, "Speak", "1");
+ switch_core_hash_insert(filter, "Talking", "1");
+ switch_core_hash_insert(filter, "Current-Energy", "1");
+ switch_core_hash_insert(filter, "Energy-Level", "1");
+ switch_core_hash_insert(filter, "Mute-Detect", "1");
+
+ /* RTMP headers */
+ switch_core_hash_insert(filter, "RTMP-Session-ID", "1");
+ switch_core_hash_insert(filter, "RTMP-Profile", "1");
+ switch_core_hash_insert(filter, "RTMP-Flash-Version", "1");
+ switch_core_hash_insert(filter, "RTMP-SWF-URL", "1");
+ switch_core_hash_insert(filter, "RTMP-TC-URL", "1");
+ switch_core_hash_insert(filter, "RTMP-Page-URL", "1");
+ switch_core_hash_insert(filter, "User", "1");
+ switch_core_hash_insert(filter, "Domain", "1");
+
+ /* Fax headers */
+ switch_core_hash_insert(filter, "variable_fax_bad_rows", "1");
+ switch_core_hash_insert(filter, "variable_fax_document_total_pages", "1");
+ switch_core_hash_insert(filter, "variable_fax_document_transferred_pages", "1");
+ switch_core_hash_insert(filter, "variable_fax_ecm_used", "1");
+ switch_core_hash_insert(filter, "variable_fax_result_code", "1");
+ switch_core_hash_insert(filter, "variable_fax_result_text", "1");
+ switch_core_hash_insert(filter, "variable_fax_success", "1");
+ switch_core_hash_insert(filter, "variable_fax_transfer_rate", "1");
+ switch_core_hash_insert(filter, "variable_fax_local_station_id", "1");
+ switch_core_hash_insert(filter, "variable_fax_remote_station_id", "1");
+ switch_core_hash_insert(filter, "variable_fax_remote_country", "1");
+ switch_core_hash_insert(filter, "variable_fax_remote_vendor", "1");
+ switch_core_hash_insert(filter, "variable_fax_remote_model", "1");
+ switch_core_hash_insert(filter, "variable_fax_image_resolution", "1");
+ switch_core_hash_insert(filter, "variable_fax_file_image_resolution", "1");
+ switch_core_hash_insert(filter, "variable_fax_image_size", "1");
+ switch_core_hash_insert(filter, "variable_fax_image_pixel_size", "1");
+ switch_core_hash_insert(filter, "variable_fax_file_image_pixel_size", "1");
+ switch_core_hash_insert(filter, "variable_fax_longest_bad_row_run", "1");
+ switch_core_hash_insert(filter, "variable_fax_encoding", "1");
+ switch_core_hash_insert(filter, "variable_fax_encoding_name", "1");
+ switch_core_hash_insert(filter, "variable_fax_header", "1");
+ switch_core_hash_insert(filter, "variable_fax_ident", "1");
+ switch_core_hash_insert(filter, "variable_fax_timezone", "1");
+ switch_core_hash_insert(filter, "variable_fax_doc_id", "1");
+ switch_core_hash_insert(filter, "variable_fax_doc_database", "1");
+ switch_core_hash_insert(filter, "variable_has_t38", "1");
+
+ /* Secure headers */
+ switch_core_hash_insert(filter, "variable_sdp_secure_savp_only", "1");
+ switch_core_hash_insert(filter, "variable_rtp_has_crypto", "1");
+ switch_core_hash_insert(filter, "variable_rtp_secure_media", "1");
+ switch_core_hash_insert(filter, "variable_rtp_secure_media_confirmed", "1");
+ switch_core_hash_insert(filter, "variable_rtp_secure_media_confirmed_audio", "1");
+ switch_core_hash_insert(filter, "variable_rtp_secure_media_confirmed_video", "1");
+ switch_core_hash_insert(filter, "variable_zrtp_secure_media", "1");
+ switch_core_hash_insert(filter, "variable_zrtp_secure_media_confirmed", "1");
+ switch_core_hash_insert(filter, "variable_zrtp_secure_media_confirmed_audio", "1");
+ switch_core_hash_insert(filter, "variable_zrtp_secure_media_confirmed_video", "1");
+ switch_core_hash_insert(filter, "sdp_secure_savp_only", "1");
+ switch_core_hash_insert(filter, "rtp_has_crypto", "1");
+ switch_core_hash_insert(filter, "rtp_secure_media", "1");
+ switch_core_hash_insert(filter, "rtp_secure_media_confirmed", "1");
+ switch_core_hash_insert(filter, "rtp_secure_media_confirmed_audio", "1");
+ switch_core_hash_insert(filter, "rtp_secure_media_confirmed_video", "1");
+ switch_core_hash_insert(filter, "zrtp_secure_media", "1");
+ switch_core_hash_insert(filter, "zrtp_secure_media_confirmed", "1");
+ switch_core_hash_insert(filter, "zrtp_secure_media_confirmed_audio", "1");
+ switch_core_hash_insert(filter, "zrtp_secure_media_confirmed_video", "1");
+
+ /* Device Redirect headers */
+ switch_core_hash_insert(filter, "variable_last_bridge_hangup_cause", "1");
+ switch_core_hash_insert(filter, "variable_sip_redirected_by", "1");
+ switch_core_hash_insert(filter, "intercepted_by", "1");
+ switch_core_hash_insert(filter, "variable_bridge_uuid", "1");
+ switch_core_hash_insert(filter, "Record-File-Path", "1");
+
+ /* Loopback headers */
+ switch_core_hash_insert(filter, "variable_loopback_bowout_on_execute", "1");
+ switch_core_hash_insert(filter, "variable_loopback_bowout", "1");
+ switch_core_hash_insert(filter, "variable_other_loopback_leg_uuid", "1");
+ switch_core_hash_insert(filter, "variable_loopback_leg", "1");
+ switch_core_hash_insert(filter, "variable_is_loopback", "1");
+
+ // SMS
+ switch_core_hash_insert(filter, "Message-ID", "1");
+ switch_core_hash_insert(filter, "Delivery-Failure", "1");
+ switch_core_hash_insert(filter, "Delivery-Result-Code", "1");
+
+ return filter;
+}
+
+static void fetch_config_filters(switch_memory_pool_t *pool)
+{
+ char *cf = "kazoo.conf";
+ switch_xml_t cfg, xml, child, param;
+ switch_event_t *params;
+
+ switch_event_create(¶ms, SWITCH_EVENT_REQUEST_PARAMS);
+ switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "Action", "request-filter");
+
+ if (!(xml = switch_xml_open_cfg(cf, &cfg, params))) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to open configuration file %s\n", cf);
+ } else if ((child = switch_xml_child(cfg, "event-filter"))) {
+ switch_hash_t *filter;
+ switch_hash_t *old_filter;
+
+ switch_core_hash_init(&filter);
+ for (param = switch_xml_child(child, "header"); param; param = param->next) {
+ char *var = (char *) switch_xml_attr_soft(param, "name");
+ switch_core_hash_insert(filter, var, "1");
+ }
+
+ old_filter = kazoo_globals.event_filter;
+ kazoo_globals.event_filter = filter;
+ if (old_filter) {
+ switch_core_hash_destroy(&old_filter);
+ }
+
+ kazoo_globals.config_fetched = 1;
+ switch_xml_free(xml);
+ }
+
+}
+
+static void fetch_config_handlers(switch_memory_pool_t *pool)
+{
+ char *cf = "kazoo.conf";
+ switch_xml_t cfg, xml;
+ switch_event_t *params;
+
+ switch_event_create(¶ms, SWITCH_EVENT_REQUEST_PARAMS);
+ switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "Action", "request-handlers");
+
+ if (!(xml = switch_xml_open_cfg(cf, &cfg, params))) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to open configuration file %s\n", cf);
+ } else {
+ kazoo_config_handlers(cfg);
+ kazoo_globals.config_fetched = 1;
+ switch_xml_free(xml);
+ }
+
+}
+
+static void *SWITCH_THREAD_FUNC fetch_config_exec(switch_thread_t *thread, void *obj)
+{
+ switch_memory_pool_t *pool = (switch_memory_pool_t *)obj;
+ fetch_config_filters(pool);
+ fetch_config_handlers(pool);
+
+ kazoo_globals.config_fetched = 1;
+
+ return NULL;
+}
+
+void fetch_config() {
+ switch_memory_pool_t *pool;
+ switch_thread_t *thread;
+ switch_threadattr_t *thd_attr = NULL;
+ switch_uuid_t uuid;
+
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "fetching kazoo config\n");
+
+ switch_core_new_memory_pool(&pool);
+
+ switch_threadattr_create(&thd_attr, pool);
+ switch_threadattr_detach_set(thd_attr, 1);
+ switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
+
+ switch_uuid_get(&uuid);
+ switch_thread_create(&thread, thd_attr, fetch_config_exec, pool, pool);
+
+}
+
+
+SWITCH_MODULE_RUNTIME_FUNCTION(mod_kazoo_runtime) {
+ switch_os_socket_t os_socket;
+
+ if(create_acceptor() != SWITCH_STATUS_SUCCESS) {
+ // TODO: what would we need to clean up here
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to create erlang connection acceptor!\n");
+ close_socket(&kazoo_globals.acceptor);
+ return SWITCH_STATUS_TERM;
+ }
+
+ switch_atomic_inc(&kazoo_globals.threads);
+ switch_os_sock_get(&os_socket, kazoo_globals.acceptor);
+
+ while (switch_test_flag(&kazoo_globals, LFLAG_RUNNING)) {
+ int nodefd;
+ ErlConnect conn;
+
+ /* zero out errno because ei_accept doesn't differentiate between a */
+ /* failed authentication or a socket failure, or a client version */
+ /* mismatch or a godzilla attack (and a godzilla attack is highly likely) */
+ errno = 0;
+
+ /* wait here for an erlang node to connect, timming out to check if our module is still running every now-and-again */
+ if ((nodefd = ei_accept_tmo(&kazoo_globals.ei_cnode, (int) os_socket, &conn, kazoo_globals.connection_timeout)) == ERL_ERROR) {
+ if (erl_errno == ETIMEDOUT) {
+ continue;
+ } else if (errno) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Erlang connection acceptor socket error %d %d\n", erl_errno, errno);
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
+ "Erlang node connection failed - ensure your cookie matches '%s' and you are using a good nodename\n", kazoo_globals.ei_cookie);
+ }
+ continue;
+ }
+
+ if (!switch_test_flag(&kazoo_globals, LFLAG_RUNNING)) {
+ break;
+ }
+
+ /* NEW ERLANG NODE CONNECTION! Hello friend! */
+ new_kazoo_node(nodefd, &conn);
+ }
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Erlang connection acceptor shut down\n");
+
+ switch_atomic_dec(&kazoo_globals.threads);
+
+ return SWITCH_STATUS_TERM;
+}
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4:
+ */
diff --git a/src/mod/event_handlers/mod_kazoo/kazoo_endpoints.c b/src/mod/event_handlers/mod_kazoo/kazoo_endpoints.c
new file mode 100644
index 0000000000..fba1adddb1
--- /dev/null
+++ b/src/mod/event_handlers/mod_kazoo/kazoo_endpoints.c
@@ -0,0 +1,284 @@
+/*
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005-2012, Anthony Minessale II
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ *
+ * The Initial Developer of the Original Code is
+ * Anthony Minessale II
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Karl Anderson
+ * Darren Schreiber
+ *
+ *
+ * kazoo_dptools.c -- clones of mod_dptools commands slightly modified for kazoo
+ *
+ */
+#include "mod_kazoo.h"
+
+/* kazoo endpoint */
+switch_endpoint_interface_t *kz_endpoint_interface;
+static switch_call_cause_t kz_endpoint_outgoing_channel(switch_core_session_t *session,
+ switch_event_t *var_event,
+ switch_caller_profile_t *outbound_profile,
+ switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags,
+ switch_call_cause_t *cancel_cause);
+switch_io_routines_t kz_endpoint_io_routines = {
+ /*.outgoing_channel */ kz_endpoint_outgoing_channel
+};
+
+static switch_call_cause_t kz_endpoint_outgoing_channel(switch_core_session_t *session,
+ switch_event_t *var_event,
+ switch_caller_profile_t *outbound_profile,
+ switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags,
+ switch_call_cause_t *cancel_cause)
+{
+ switch_xml_t x_user = NULL, x_param, x_params;
+ char *user = NULL, *domain = NULL, *dup_domain = NULL, *dialed_user = NULL;
+ const char *dest = NULL;
+ switch_call_cause_t cause = SWITCH_CAUSE_NONE;
+ unsigned int timelimit = SWITCH_DEFAULT_TIMEOUT;
+ switch_channel_t *new_channel = NULL;
+ switch_event_t *params = NULL, *var_event_orig = var_event;
+ char stupid[128] = "";
+ const char *skip = NULL, *var = NULL;
+
+ if (zstr(outbound_profile->destination_number)) {
+ goto done;
+ }
+
+ user = strdup(outbound_profile->destination_number);
+
+ if (!user)
+ goto done;
+
+ if ((domain = strchr(user, '@'))) {
+ *domain++ = '\0';
+ } else {
+ domain = switch_core_get_domain(SWITCH_TRUE);
+ dup_domain = domain;
+ }
+
+ if (!domain) {
+ goto done;
+ }
+
+
+ switch_event_create(¶ms, SWITCH_EVENT_REQUEST_PARAMS);
+ switch_assert(params);
+ switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "as_channel", "true");
+ switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "action", "user_call");
+
+ if (var_event) {
+ switch_event_merge(params, var_event);
+ }
+
+ if (var_event && (skip = switch_event_get_header(var_event, "user_recurse_variables")) && switch_false(skip)) {
+ if ((var = switch_event_get_header(var_event, SWITCH_CALL_TIMEOUT_VARIABLE)) || (var = switch_event_get_header(var_event, "leg_timeout"))) {
+ timelimit = atoi(var);
+ }
+ var_event = NULL;
+ }
+
+ if (switch_xml_locate_user_merged("id", user, domain, NULL, &x_user, params) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Can't find user [%s@%s]\n", user, domain);
+ cause = SWITCH_CAUSE_SUBSCRIBER_ABSENT;
+ goto done;
+ }
+
+ if ((x_params = switch_xml_child(x_user, "params"))) {
+ for (x_param = switch_xml_child(x_params, "param"); x_param; x_param = x_param->next) {
+ const char *pvar = switch_xml_attr_soft(x_param, "name");
+ const char *val = switch_xml_attr(x_param, "value");
+
+ if (!strcasecmp(pvar, "dial-string")) {
+ dest = val;
+ } else if (!strncasecmp(pvar, "dial-var-", 9)) {
+ if (!var_event) {
+ switch_event_create(&var_event, SWITCH_EVENT_GENERAL);
+ } else {
+ switch_event_del_header(var_event, pvar + 9);
+ }
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "adding variable to var_event => %s = %s\n", pvar + 9, val);
+ switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, pvar + 9, val);
+ }
+ }
+ }
+
+ dialed_user = (char *)switch_xml_attr(x_user, "id");
+
+ if (var_event) {
+ switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "dialed_user", dialed_user);
+ switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "dialed_domain", domain);
+ if (!zstr(dest) && !strstr(dest, "presence_id=")) {
+ switch_event_add_header(var_event, SWITCH_STACK_BOTTOM, "presence_id", "%s@%s", dialed_user, domain);
+ }
+ }
+
+ if (!dest) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No dial-string available, please check your user directory.\n");
+ cause = SWITCH_CAUSE_MANDATORY_IE_MISSING;
+ } else {
+ const char *varval;
+ char *d_dest = NULL;
+ switch_channel_t *channel;
+ switch_originate_flag_t myflags = SOF_NONE;
+ char *cid_name_override = NULL;
+ char *cid_num_override = NULL;
+
+ if (var_event) {
+ cid_name_override = switch_event_get_header(var_event, "origination_caller_id_name");
+ cid_num_override = switch_event_get_header(var_event, "origination_caller_id_number");
+ }
+
+ if (session) {
+ switch_event_t *event = NULL;
+ switch_event_create(&event, SWITCH_EVENT_GENERAL);
+ channel = switch_core_session_get_channel(session);
+ if ((varval = switch_channel_get_variable(channel, SWITCH_CALL_TIMEOUT_VARIABLE))
+ || (var_event && (varval = switch_event_get_header(var_event, "leg_timeout")))) {
+ timelimit = atoi(varval);
+ }
+ switch_channel_event_set_data(channel, event);
+ if(var_event) {
+ switch_event_merge(event, var_event);
+ }
+
+ switch_channel_set_variable(channel, "dialed_user", dialed_user);
+ switch_channel_set_variable(channel, "dialed_domain", domain);
+
+ d_dest = switch_event_expand_headers(event, dest);
+
+ switch_event_destroy(&event);
+
+ } else {
+ switch_event_t *event = NULL;
+
+ if (var_event) {
+ switch_event_dup(&event, var_event);
+ switch_event_del_header(event, "dialed_user");
+ switch_event_del_header(event, "dialed_domain");
+ if ((varval = switch_event_get_header(var_event, SWITCH_CALL_TIMEOUT_VARIABLE)) ||
+ (varval = switch_event_get_header(var_event, "leg_timeout"))) {
+ timelimit = atoi(varval);
+ }
+ } else {
+ switch_event_create(&event, SWITCH_EVENT_REQUEST_PARAMS);
+ switch_assert(event);
+ }
+
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "dialed_user", dialed_user);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "dialed_domain", domain);
+ d_dest = switch_event_expand_headers(event, dest);
+ switch_event_destroy(&event);
+ }
+
+ if ((flags & SOF_NO_LIMITS)) {
+ myflags |= SOF_NO_LIMITS;
+ }
+
+ if ((flags & SOF_FORKED_DIAL)) {
+ myflags |= SOF_NOBLOCK;
+ }
+
+ switch_snprintf(stupid, sizeof(stupid), "kz/%s", dialed_user);
+ if (switch_stristr(stupid, d_dest)) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Waddya Daft? You almost called '%s' in an infinate loop!\n",
+ stupid);
+ cause = SWITCH_CAUSE_INVALID_IE_CONTENTS;
+ } else if (switch_ivr_originate(session, new_session, &cause, d_dest, timelimit, NULL,
+ cid_name_override, cid_num_override, outbound_profile, var_event, myflags,
+ cancel_cause, NULL) == SWITCH_STATUS_SUCCESS) {
+ const char *context;
+ switch_caller_profile_t *cp;
+
+ if (var_event) {
+ switch_event_del_header(var_event, "origination_uuid");
+ }
+
+ new_channel = switch_core_session_get_channel(*new_session);
+
+ if ((context = switch_channel_get_variable(new_channel, "user_context"))) {
+ if ((cp = switch_channel_get_caller_profile(new_channel))) {
+ cp->context = switch_core_strdup(cp->pool, context);
+ }
+ }
+
+ if ((x_params = switch_xml_child(x_user, "variables"))) {
+ for (x_param = switch_xml_child(x_params, "variable"); x_param; x_param = x_param->next) {
+ const char *pvar = switch_xml_attr(x_param, "name");
+ const char *val = switch_xml_attr(x_param, "value");
+ switch_channel_set_variable(new_channel, pvar, val);
+ }
+ }
+
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(*new_session), SWITCH_LOG_DEBUG1, "CHECKING CALLER-ID\n");
+ if ((x_params = switch_xml_child(x_user, "profile-variables"))) {
+ switch_caller_profile_t *cp = NULL;
+ const char* val = NULL;
+ for (x_param = switch_xml_child(x_params, "variable"); x_param; x_param = x_param->next) {
+ const char *pvar = switch_xml_attr(x_param, "name");
+ const char *val = switch_xml_attr(x_param, "value");
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(*new_session), SWITCH_LOG_DEBUG1, "setting profile var %s = %s\n", pvar, val);
+ switch_channel_set_profile_var(new_channel, pvar, val);
+ }
+ cp = switch_channel_get_caller_profile(new_channel);
+ if((val=switch_caller_get_field_by_name(cp, "Endpoint-Caller-ID-Name"))) {
+ cp->callee_id_name = val;
+ cp->orig_caller_id_name = val;
+ }
+ if((val=switch_caller_get_field_by_name(cp, "Endpoint-Caller-ID-Number"))) {
+ cp->callee_id_number = val;
+ cp->orig_caller_id_number = val;
+ }
+ }
+ switch_core_session_rwunlock(*new_session);
+ }
+
+ if (d_dest != dest) {
+ switch_safe_free(d_dest);
+ }
+ }
+
+ done:
+
+ if (x_user) {
+ switch_xml_free(x_user);
+ }
+
+ if (params) {
+ switch_event_destroy(¶ms);
+ }
+
+ if (var_event && var_event_orig != var_event) {
+ switch_event_destroy(&var_event);
+ }
+
+ switch_safe_free(user);
+ switch_safe_free(dup_domain);
+
+ return cause;
+}
+
+
+void add_kz_endpoints(switch_loadable_module_interface_t **module_interface) {
+ kz_endpoint_interface = (switch_endpoint_interface_t *) switch_loadable_module_create_interface(*module_interface, SWITCH_ENDPOINT_INTERFACE);
+ kz_endpoint_interface->interface_name = "kz";
+ kz_endpoint_interface->io_routines = &kz_endpoint_io_routines;
+}
diff --git a/src/mod/event_handlers/mod_kazoo/kazoo_event_stream.c b/src/mod/event_handlers/mod_kazoo/kazoo_event_stream.c
index 3ca0e3acc7..5e5fb8dff4 100644
--- a/src/mod/event_handlers/mod_kazoo/kazoo_event_stream.c
+++ b/src/mod/event_handlers/mod_kazoo/kazoo_event_stream.c
@@ -32,6 +32,8 @@
*/
#include "mod_kazoo.h"
+#define MAX_FRAMING 4
+
/* Blatantly repurposed from switch_eventc */
static char *my_dup(const char *s) {
size_t len = strlen(s) + 1;
@@ -48,7 +50,8 @@ static char *my_dup(const char *s) {
static const char* private_headers[] = {"variable_sip_h_", "sip_h_", "P-", "X-"};
static int is_private_header(const char *name) {
- for(int i=0; i < 4; i++) {
+ int i;
+ for(i=0; i < 4; i++) {
if(!strncmp(name, private_headers[i], strlen(private_headers[i]))) {
return 1;
}
@@ -56,6 +59,20 @@ static int is_private_header(const char *name) {
return 0;
}
+static int is_kazoo_var(char* header)
+{
+ int idx = 0;
+ while(kazoo_globals.kazoo_var_prefixes[idx] != NULL) {
+ char *prefix = kazoo_globals.kazoo_var_prefixes[idx];
+ if(!strncasecmp(header, prefix, strlen(prefix))) {
+ return 1;
+ }
+ idx++;
+ }
+
+ return 0;
+}
+
static switch_status_t kazoo_event_dup(switch_event_t **clone, switch_event_t *event, switch_hash_t *filter) {
switch_event_header_t *header;
@@ -73,7 +90,7 @@ static switch_status_t kazoo_event_dup(switch_event_t **clone, switch_event_t *e
continue;
}
- if (strncmp(header->name, kazoo_globals.kazoo_var_prefix, kazoo_globals.var_prefix_length)
+ if (!is_kazoo_var(header->name)
&& filter
&& !switch_core_hash_find(filter, header->name)
&& (!kazoo_globals.send_all_headers)
@@ -102,51 +119,115 @@ static switch_status_t kazoo_event_dup(switch_event_t **clone, switch_event_t *e
return SWITCH_STATUS_SUCCESS;
}
-static void event_handler(switch_event_t *event) {
+static int encode_event_old(switch_event_t *event, ei_x_buff *ebuf) {
switch_event_t *clone = NULL;
- ei_event_stream_t *event_stream = (ei_event_stream_t *) event->bind_user_data;
+
+ if (kazoo_event_dup(&clone, event, kazoo_globals.event_filter) != SWITCH_STATUS_SUCCESS) {
+ return 0;
+ }
+
+ ei_encode_switch_event(ebuf, clone);
+
+ switch_event_destroy(&clone);
+
+ return 1;
+}
+
+static int encode_event_new(switch_event_t *event, ei_x_buff *ebuf) {
+ kazoo_message_ptr msg = NULL;
+ ei_event_binding_t *event_binding = (ei_event_binding_t *) event->bind_user_data;
+
+ msg = kazoo_message_create_event(event, event_binding->event, kazoo_globals.events);
+
+ if(msg == NULL) {
+ return 0;
+ }
+
+ ei_x_encode_tuple_header(ebuf, 3);
+ ei_x_encode_atom(ebuf, "event");
+ if(kazoo_globals.json_encoding == ERLANG_TUPLE) {
+ ei_x_encode_atom(ebuf, "json");
+ } else {
+ ei_x_encode_atom(ebuf, "map");
+ }
+ ei_encode_json(ebuf, msg->JObj);
+
+ kazoo_message_destroy(&msg);
+
+ return 1;
+}
+
+/*
+ * event_handler is duplicated when there are 2+ nodes connected
+ * with the same bindings
+ * we should maintain a list of event_streams in event_binding struct
+ * and build a ref count in the message
+ *
+ */
+static void event_handler(switch_event_t *event) {
+ ei_event_binding_t *event_binding = (ei_event_binding_t *) event->bind_user_data;
+ ei_event_stream_t *event_stream = event_binding->stream;
+ ei_x_buff *ebuf = NULL;
+ int res = 0;
/* if mod_kazoo or the event stream isn't running dont push a new event */
if (!switch_test_flag(event_stream, LFLAG_RUNNING) || !switch_test_flag(&kazoo_globals, LFLAG_RUNNING)) {
return;
}
- if (event->event_id == SWITCH_EVENT_CUSTOM) {
- ei_event_binding_t *event_binding = event_stream->bindings;
- unsigned short int found = 0;
+ kz_event_decode(event);
- if (!event->subclass_name) {
- return;
- }
-
- while(event_binding != NULL) {
- if (event_binding->type == SWITCH_EVENT_CUSTOM) {
- if(event_binding->subclass_name
- && !strcmp(event->subclass_name, event_binding->subclass_name)) {
- found = 1;
- break;
- }
- }
- event_binding = event_binding->next;
- }
-
- if (!found) {
- return;
- }
+ switch_malloc(ebuf, sizeof(*ebuf));
+ if(ebuf == NULL) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not allocate erlang buffer for mod_kazoo message\n");
+ return;
}
+ memset(ebuf, 0, sizeof(*ebuf));
- /* try to clone the event and push it to the event stream thread */
- /* TODO: someday maybe the filter comes from the event_stream (set during init only)
- * and is per-binding so we only send headers that a process requests */
- if (kazoo_event_dup(&clone, event, kazoo_globals.event_filter) == SWITCH_STATUS_SUCCESS) {
- if (switch_queue_trypush(event_stream->queue, clone) != SWITCH_STATUS_SUCCESS) {
- /* if we couldn't place the cloned event into the listeners */
- /* event queue make sure we destroy it, real good like */
- switch_event_destroy(&clone);
+ if(kazoo_globals.event_stream_preallocate > 0) {
+ ebuf->buff = malloc(kazoo_globals.event_stream_preallocate);
+ ebuf->buffsz = kazoo_globals.event_stream_preallocate;
+ ebuf->index = 0;
+ if(ebuf->buff == NULL) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not pre-allocate memory for mod_kazoo message\n");
+ switch_safe_free(ebuf);
+ return;
}
} else {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Memory error: Have a good trip? See you next fall!\n");
+ ei_x_new(ebuf);
}
+
+ ebuf->index = MAX_FRAMING;
+
+ ei_x_encode_version(ebuf);
+
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Target-Node", event_binding->stream->node->peer_nodename);
+
+ if(event_stream->node->legacy) {
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Switch-Nodename", kazoo_globals.ei_cnode.thisnodename);
+ res = encode_event_old(event, ebuf);
+ } else {
+ res = encode_event_new(event, ebuf);
+ }
+
+ if(!res) {
+ ei_x_free(ebuf);
+ switch_safe_free(ebuf);
+ return;
+ }
+
+ if (kazoo_globals.event_stream_preallocate > 0 && ebuf->buffsz > kazoo_globals.event_stream_preallocate) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "increased event stream buffer size to %d\n", ebuf->buffsz);
+ }
+
+ if (switch_queue_trypush(event_stream->queue, ebuf) != SWITCH_STATUS_SUCCESS) {
+ /* if we couldn't place the cloned event into the listeners */
+ /* event queue make sure we destroy it, real good like */
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "error placing the event in the listeners queue\n");
+ ei_x_free(ebuf);
+ switch_safe_free(ebuf);
+ }
+
}
static void *SWITCH_THREAD_FUNC event_stream_loop(switch_thread_t *thread, void *obj) {
@@ -157,12 +238,15 @@ static void *SWITCH_THREAD_FUNC event_stream_loop(switch_thread_t *thread, void
char ipbuf[48];
const char *ip_addr;
void *pop;
- short event_stream_framing = kazoo_globals.event_stream_framing;
+ short event_stream_framing;
+ short ok = 1;
switch_atomic_inc(&kazoo_globals.threads);
switch_assert(event_stream != NULL);
+ event_stream_framing = event_stream->event_stream_framing;
+
/* figure out what socket we just opened */
switch_socket_addr_get(&sa, SWITCH_FALSE, event_stream->acceptor);
port = switch_sockaddr_get_port(sa);
@@ -172,13 +256,14 @@ static void *SWITCH_THREAD_FUNC event_stream_loop(switch_thread_t *thread, void
,(void *)event_stream, ip_addr, port, event_stream->pid.node, event_stream->pid.creation
,event_stream->pid.num, event_stream->pid.serial);
- while (switch_test_flag(event_stream, LFLAG_RUNNING) && switch_test_flag(&kazoo_globals, LFLAG_RUNNING)) {
+ while (switch_test_flag(event_stream, LFLAG_RUNNING) && switch_test_flag(&kazoo_globals, LFLAG_RUNNING) && ok) {
const switch_pollfd_t *fds;
int32_t numfds;
/* check if a new connection is pending */
if (switch_pollset_poll(event_stream->pollset, 0, &numfds, &fds) == SWITCH_STATUS_SUCCESS) {
- for (int32_t i = 0; i < numfds; i++) {
+ int32_t i;
+ for (i = 0; i < numfds; i++) {
switch_socket_t *newsocket;
/* accept the new client connection */
@@ -201,11 +286,11 @@ static void *SWITCH_THREAD_FUNC event_stream_loop(switch_thread_t *thread, void
event_stream->socket = newsocket;
switch_socket_addr_get(&sa, SWITCH_TRUE, newsocket);
- event_stream->local_port = switch_sockaddr_get_port(sa);
+ event_stream->remote_port = switch_sockaddr_get_port(sa);
switch_get_addr(event_stream->remote_ip, sizeof (event_stream->remote_ip), sa);
switch_socket_addr_get(&sa, SWITCH_FALSE, newsocket);
- event_stream->remote_port = switch_sockaddr_get_port(sa);
+ event_stream->local_port = switch_sockaddr_get_port(sa);
switch_get_addr(event_stream->local_ip, sizeof (event_stream->local_ip), sa);
event_stream->connected = SWITCH_TRUE;
@@ -217,46 +302,38 @@ static void *SWITCH_THREAD_FUNC event_stream_loop(switch_thread_t *thread, void
}
/* if there was an event waiting in our queue send it to the client */
- if (switch_queue_pop_timeout(event_stream->queue, &pop, 500000) == SWITCH_STATUS_SUCCESS) {
- switch_event_t *event = (switch_event_t *) pop;
+ if (switch_queue_pop_timeout(event_stream->queue, &pop, 200000) == SWITCH_STATUS_SUCCESS) {
+ ei_x_buff *ebuf = (ei_x_buff *) pop;
if (event_stream->socket) {
- ei_x_buff ebuf;
- char byte;
- short i = event_stream_framing;
- switch_size_t size = 1;
+ switch_size_t size = 1, expected = 0;
+ switch_status_t status = SWITCH_STATUS_SUCCESS;
- if(kazoo_globals.event_stream_preallocate > 0) {
- ebuf.buff = malloc(kazoo_globals.event_stream_preallocate);
- ebuf.buffsz = kazoo_globals.event_stream_preallocate;
- ebuf.index = 0;
- if(ebuf.buff == NULL) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not pre-allocate memory for mod_kazoo message\n");
- break;
- }
- ei_x_encode_version(&ebuf);
+ if(ebuf->index >= pow(2, 8 * event_stream_framing)) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "sending frame size %d with insufficient frame capacity, change event_stream_framing here and tcp_packet_type in ecallmgr\n", ebuf->index);
} else {
- ei_x_new_with_version(&ebuf);
+ if(event_stream_framing) {
+ int index = ebuf->index - MAX_FRAMING;
+ char byte;
+ short i = event_stream_framing;
+ while (i) {
+ byte = index >> (8 * --i);
+ ebuf->buff[MAX_FRAMING - i - 1] = byte;
+ }
+ }
+ expected = size = (switch_size_t)ebuf->index - MAX_FRAMING + event_stream_framing;
+ if((status = switch_socket_send(event_stream->socket, ebuf->buff + (MAX_FRAMING - event_stream_framing), &size)) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "error %d sending event stream\n", status);
+ ok = 0;
+ } else if(expected != size) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "error sending event stream, sent bytes is different of expected\n");
+ ok = 0;
+ }
}
-
- ei_encode_switch_event(&ebuf, event);
-
- if (kazoo_globals.event_stream_preallocate > 0 && ebuf.buffsz > kazoo_globals.event_stream_preallocate) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "increased event stream buffer size to %d\n", ebuf.buffsz);
- }
-
- while (i) {
- byte = ebuf.index >> (8 * --i);
- switch_socket_send(event_stream->socket, &byte, &size);
- }
-
- size = (switch_size_t)ebuf.index;
- switch_socket_send(event_stream->socket, ebuf.buff, &size);
-
- ei_x_free(&ebuf);
}
- switch_event_destroy(&event);
+ ei_x_free(ebuf);
+ switch_safe_free(ebuf);
}
}
@@ -272,8 +349,9 @@ static void *SWITCH_THREAD_FUNC event_stream_loop(switch_thread_t *thread, void
/* clear and destroy any remaining queued events */
while (switch_queue_trypop(event_stream->queue, &pop) == SWITCH_STATUS_SUCCESS) {
- switch_event_t *event = (switch_event_t *) pop;
- switch_event_destroy(&event);
+ ei_x_buff *ebuf = (ei_x_buff *) pop;
+ ei_x_free(ebuf);
+ switch_safe_free(ebuf);
}
/* remove the acceptor pollset */
@@ -297,11 +375,12 @@ static void *SWITCH_THREAD_FUNC event_stream_loop(switch_thread_t *thread, void
return NULL;
}
-ei_event_stream_t *new_event_stream(ei_event_stream_t **event_streams, const erlang_pid *from) {
+ei_event_stream_t *new_event_stream(ei_node_t *ei_node, const erlang_pid *from) {
switch_thread_t *thread;
switch_threadattr_t *thd_attr = NULL;
switch_memory_pool_t *pool = NULL;
ei_event_stream_t *event_stream;
+ ei_event_stream_t **event_streams = &ei_node->event_streams;
/* create memory pool for this event stream */
if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {
@@ -320,6 +399,8 @@ ei_event_stream_t *new_event_stream(ei_event_stream_t **event_streams, const erl
event_stream->bindings = NULL;
event_stream->pool = pool;
event_stream->connected = SWITCH_FALSE;
+ event_stream->node = ei_node;
+ event_stream->event_stream_framing = ei_node->event_stream_framing;
memcpy(&event_stream->pid, from, sizeof(erlang_pid));
switch_queue_create(&event_stream->queue, MAX_QUEUE_LEN, pool);
@@ -443,17 +524,68 @@ switch_status_t remove_event_streams(ei_event_stream_t **event_streams) {
return SWITCH_STATUS_SUCCESS;
}
-switch_status_t add_event_binding(ei_event_stream_t *event_stream, const switch_event_types_t event_type, const char *subclass_name) {
+void bind_event_profile(ei_event_binding_t *event_binding, kazoo_event_ptr event)
+{
+ switch_event_types_t event_type;
+ while(event != NULL) {
+ if (switch_name_event(event->name, &event_type) != SWITCH_STATUS_SUCCESS) {
+ event_type = SWITCH_EVENT_CUSTOM;
+ }
+ if(event_binding->type != SWITCH_EVENT_CUSTOM
+ && event_binding->type == event_type) {
+ break;
+ }
+ if (event_binding->type == SWITCH_EVENT_CUSTOM
+ && event_binding->type == event_type
+ && !strcasecmp(event_binding->subclass_name, event->name)) {
+ break;
+ }
+ event = event->next;
+ }
+ event_binding->event = event;
+ if(event == NULL && (!event_binding->stream->node->legacy)) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "event binding to an event without profile in non legacy mode => %s - %s\n",switch_event_name(event_binding->type), event_binding->subclass_name);
+ }
+}
+
+void bind_event_profiles(kazoo_event_ptr event)
+{
+ ei_node_t *ei_node = kazoo_globals.ei_nodes;
+ while(ei_node) {
+ ei_event_stream_t *event_streams = ei_node->event_streams;
+ while(event_streams) {
+ ei_event_binding_t *bindings = event_streams->bindings;
+ while(bindings) {
+ bind_event_profile(bindings, event);
+ bindings = bindings->next;
+ }
+ event_streams = event_streams->next;
+ }
+ ei_node = ei_node->next;
+ }
+}
+
+switch_status_t add_event_binding(ei_event_stream_t *event_stream, const char *event_name) {
ei_event_binding_t *event_binding = event_stream->bindings;
+ switch_event_types_t event_type;
+
+ if(!strcasecmp(event_name, "CUSTOM")) {
+ return SWITCH_STATUS_SUCCESS;
+ }
+
+ if (switch_name_event(event_name, &event_type) != SWITCH_STATUS_SUCCESS) {
+ event_type = SWITCH_EVENT_CUSTOM;
+ }
/* check if the event binding already exists, ignore if so */
while(event_binding != NULL) {
if (event_binding->type == SWITCH_EVENT_CUSTOM) {
- if(subclass_name
- && event_binding->subclass_name
- && !strcmp(subclass_name, event_binding->subclass_name)) {
- return SWITCH_STATUS_SUCCESS;
- }
+ if(event_type == SWITCH_EVENT_CUSTOM
+ && event_name
+ && event_binding->subclass_name
+ && !strcasecmp(event_name, event_binding->subclass_name)) {
+ return SWITCH_STATUS_SUCCESS;
+ }
} else if (event_binding->type == event_type) {
return SWITCH_STATUS_SUCCESS;
}
@@ -467,18 +599,21 @@ switch_status_t add_event_binding(ei_event_stream_t *event_stream, const switch_
}
/* prepare the event binding struct */
+ event_binding->stream = event_stream;
event_binding->type = event_type;
- if (!subclass_name || zstr(subclass_name)) {
- event_binding->subclass_name = NULL;
+ if(event_binding->type == SWITCH_EVENT_CUSTOM) {
+ event_binding->subclass_name = switch_core_strdup(event_stream->pool, event_name);
} else {
- /* TODO: free strdup? */
- event_binding->subclass_name = strdup(subclass_name);
+ event_binding->subclass_name = SWITCH_EVENT_SUBCLASS_ANY;
}
event_binding->next = NULL;
+ bind_event_profile(event_binding, kazoo_globals.events->events);
+
+
/* bind to the event with a unique ID and capture the event_node pointer */
switch_uuid_str(event_binding->id, sizeof(event_binding->id));
- if (switch_event_bind_removable(event_binding->id, event_type, subclass_name, event_handler, event_stream, &event_binding->node) != SWITCH_STATUS_SUCCESS) {
+ if (switch_event_bind_removable(event_binding->id, event_type, event_binding->subclass_name, event_handler, event_binding, &event_binding->node) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to bind to event %s %s!\n"
,switch_event_name(event_binding->type), event_binding->subclass_name ? event_binding->subclass_name : "");
return SWITCH_STATUS_GENERR;
diff --git a/src/mod/event_handlers/mod_kazoo/kazoo_fetch_agent.c b/src/mod/event_handlers/mod_kazoo/kazoo_fetch_agent.c
index 006ffe32f0..24d4358b7e 100644
--- a/src/mod/event_handlers/mod_kazoo/kazoo_fetch_agent.c
+++ b/src/mod/event_handlers/mod_kazoo/kazoo_fetch_agent.c
@@ -32,38 +32,12 @@
*/
#include "mod_kazoo.h"
-struct xml_fetch_reply_s {
- char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
- char *xml_str;
- struct xml_fetch_reply_s *next;
+static const char *fetch_uuid_sources[] = {
+ "Fetch-Call-UUID",
+ "refer-from-channel-id",
+ "sip_call_id",
+ NULL
};
-typedef struct xml_fetch_reply_s xml_fetch_reply_t;
-
-struct fetch_handler_s {
- erlang_pid pid;
- struct fetch_handler_s *next;
-};
-typedef struct fetch_handler_s fetch_handler_t;
-
-struct ei_xml_client_s {
- ei_node_t *ei_node;
- fetch_handler_t *fetch_handlers;
- struct ei_xml_client_s *next;
-};
-typedef struct ei_xml_client_s ei_xml_client_t;
-
-struct ei_xml_agent_s {
- switch_memory_pool_t *pool;
- switch_xml_section_t section;
- switch_thread_rwlock_t *lock;
- ei_xml_client_t *clients;
- switch_mutex_t *current_client_mutex;
- ei_xml_client_t *current_client;
- switch_mutex_t *replies_mutex;
- switch_thread_cond_t *new_reply;
- xml_fetch_reply_t *replies;
-};
-typedef struct ei_xml_agent_s ei_xml_agent_t;
static char *xml_section_to_string(switch_xml_section_t section) {
switch(section) {
@@ -77,6 +51,8 @@ static char *xml_section_to_string(switch_xml_section_t section) {
return "chatplan";
case SWITCH_XML_SECTION_CHANNELS:
return "channels";
+ case SWITCH_XML_SECTION_LANGUAGES:
+ return "languages";
default:
return "unknown";
}
@@ -105,8 +81,10 @@ static char *expand_vars(char *xml_str) {
*e++ = '\0';
rp = e;
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "trying to expand %s \n", var);
if ((val = switch_core_get_variable_dup(var))) {
char *p;
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "expanded %s to %s\n", var, val);
for (p = val; p && *p && wp <= ep; p++) {
*wp++ = *p;
}
@@ -133,6 +111,11 @@ static switch_xml_t fetch_handler(const char *section, const char *tag_name, con
ei_xml_client_t *client;
fetch_handler_t *fetch_handler;
xml_fetch_reply_t reply, *pending, *prev = NULL;
+ switch_event_t *event = params;
+ kazoo_fetch_profile_ptr profile = agent->profile;
+ const char *fetch_call_id;
+ ei_send_msg_t *send_msg = NULL;
+ int sent = 0;
now = switch_micro_time_now();
@@ -164,12 +147,71 @@ static switch_xml_t fetch_handler(const char *section, const char *tag_name, con
return xml;
}
+ if(event == NULL) {
+ if (switch_event_create(&event, SWITCH_EVENT_GENERAL) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "error creating event for fetch handler\n");
+ return xml;
+ }
+ }
+
/* prepare the reply collector */
switch_uuid_get(&uuid);
switch_uuid_format(reply.uuid_str, &uuid);
reply.next = NULL;
reply.xml_str = NULL;
+ if(switch_event_get_header(event, "Unique-ID") == NULL) {
+ int i;
+ for(i = 0; fetch_uuid_sources[i] != NULL; i++) {
+ if((fetch_call_id = switch_event_get_header(event, fetch_uuid_sources[i])) != NULL) {
+ switch_core_session_t *session = NULL;
+ if((session = switch_core_session_force_locate(fetch_call_id)) != NULL) {
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ uint32_t verbose = switch_channel_test_flag(channel, CF_VERBOSE_EVENTS);
+ switch_channel_set_flag(channel, CF_VERBOSE_EVENTS);
+ switch_channel_event_set_data(channel, event);
+ switch_channel_set_flag_value(channel, CF_VERBOSE_EVENTS, verbose);
+ switch_core_session_rwunlock(session);
+ break;
+ }
+ }
+ }
+ }
+
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Fetch-UUID", reply.uuid_str);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Fetch-Section", section);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Fetch-Tag", tag_name);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Fetch-Key-Name", key_name);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Fetch-Key-Value", key_value);
+ switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Fetch-Timeout", "%u", profile->fetch_timeout);
+ switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Fetch-Timestamp-Micro", "%" SWITCH_UINT64_T_FMT, (uint64_t)now);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Kazoo-Version", VERSION);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Kazoo-Bundle", BUNDLE);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Kazoo-Release", RELEASE);
+
+ kz_event_decode(event);
+
+ switch_malloc(send_msg, sizeof(*send_msg));
+
+ if(client->ei_node->legacy) {
+ ei_x_new_with_version(&send_msg->buf);
+ ei_x_encode_tuple_header(&send_msg->buf, 7);
+ ei_x_encode_atom(&send_msg->buf, "fetch");
+ ei_x_encode_atom(&send_msg->buf, section);
+ _ei_x_encode_string(&send_msg->buf, tag_name ? tag_name : "undefined");
+ _ei_x_encode_string(&send_msg->buf, key_name ? key_name : "undefined");
+ _ei_x_encode_string(&send_msg->buf, key_value ? key_value : "undefined");
+ _ei_x_encode_string(&send_msg->buf, reply.uuid_str);
+ ei_encode_switch_event_headers(&send_msg->buf, event);
+ } else {
+ kazoo_message_ptr msg = kazoo_message_create_fetch(event, profile);
+ ei_x_new_with_version(&send_msg->buf);
+ ei_x_encode_tuple_header(&send_msg->buf, 2);
+ ei_x_encode_atom(&send_msg->buf, "fetch");
+ ei_encode_json(&send_msg->buf, msg->JObj);
+ kazoo_message_destroy(&msg);
+ }
+
/* add our reply placeholder to the replies list */
switch_mutex_lock(agent->replies_mutex);
if (!agent->replies) {
@@ -181,28 +223,8 @@ static switch_xml_t fetch_handler(const char *section, const char *tag_name, con
switch_mutex_unlock(agent->replies_mutex);
fetch_handler = client->fetch_handlers;
- while (fetch_handler != NULL) {
- ei_send_msg_t *send_msg;
-
- switch_malloc(send_msg, sizeof(*send_msg));
+ while (fetch_handler != NULL && sent == 0) {
memcpy(&send_msg->pid, &fetch_handler->pid, sizeof(erlang_pid));
-
- ei_x_new_with_version(&send_msg->buf);
-
- ei_x_encode_tuple_header(&send_msg->buf, 7);
- ei_x_encode_atom(&send_msg->buf, "fetch");
- ei_x_encode_atom(&send_msg->buf, section);
- _ei_x_encode_string(&send_msg->buf, tag_name ? tag_name : "undefined");
- _ei_x_encode_string(&send_msg->buf, key_name ? key_name : "undefined");
- _ei_x_encode_string(&send_msg->buf, key_value ? key_value : "undefined");
- _ei_x_encode_string(&send_msg->buf, reply.uuid_str);
-
- if (params) {
- ei_encode_switch_event_headers(&send_msg->buf, params);
- } else {
- ei_x_encode_empty_list(&send_msg->buf);
- }
-
if (switch_queue_trypush(client->ei_node->send_msgs, send_msg) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to send %s XML request to %s <%d.%d.%d>\n"
,section
@@ -210,8 +232,6 @@ static switch_xml_t fetch_handler(const char *section, const char *tag_name, con
,fetch_handler->pid.creation
,fetch_handler->pid.num
,fetch_handler->pid.serial);
- ei_x_free(&send_msg->buf);
- switch_safe_free(send_msg);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Sending %s XML request (%s) to %s <%d.%d.%d>\n"
,section
@@ -220,11 +240,19 @@ static switch_xml_t fetch_handler(const char *section, const char *tag_name, con
,fetch_handler->pid.creation
,fetch_handler->pid.num
,fetch_handler->pid.serial);
+ sent = 1;
}
-
fetch_handler = fetch_handler->next;
}
+ if(!sent) {
+ ei_x_free(&send_msg->buf);
+ switch_safe_free(send_msg);
+ }
+
+ if(params == NULL)
+ switch_event_destroy(&event);
+
/* wait for a reply (if there isnt already one...amazingly improbable but lets not take shortcuts */
switch_mutex_lock(agent->replies_mutex);
@@ -292,6 +320,42 @@ static switch_xml_t fetch_handler(const char *section, const char *tag_name, con
return xml;
}
+void bind_fetch_profile(ei_xml_agent_t *agent, kazoo_config_ptr fetch_handlers)
+{
+ switch_hash_index_t *hi;
+ kazoo_fetch_profile_ptr val = NULL, ptr = NULL;
+
+ for (hi = switch_core_hash_first(fetch_handlers->hash); hi; hi = switch_core_hash_next(&hi)) {
+ switch_core_hash_this(hi, NULL, NULL, (void**) &val);
+ if (val && val->section == agent->section) {
+ ptr = val;
+ break;
+ }
+ }
+ agent->profile = ptr;
+}
+
+void rebind_fetch_profiles(kazoo_config_ptr fetch_handlers)
+{
+ if(kazoo_globals.config_fetch_binding != NULL)
+ bind_fetch_profile((ei_xml_agent_t *) switch_xml_get_binding_user_data(kazoo_globals.config_fetch_binding), fetch_handlers);
+
+ if(kazoo_globals.directory_fetch_binding != NULL)
+ bind_fetch_profile((ei_xml_agent_t *) switch_xml_get_binding_user_data(kazoo_globals.directory_fetch_binding), fetch_handlers);
+
+ if(kazoo_globals.dialplan_fetch_binding != NULL)
+ bind_fetch_profile((ei_xml_agent_t *) switch_xml_get_binding_user_data(kazoo_globals.dialplan_fetch_binding), fetch_handlers);
+
+ if(kazoo_globals.channels_fetch_binding != NULL)
+ bind_fetch_profile((ei_xml_agent_t *) switch_xml_get_binding_user_data(kazoo_globals.channels_fetch_binding), fetch_handlers);
+
+ if(kazoo_globals.languages_fetch_binding != NULL)
+ bind_fetch_profile((ei_xml_agent_t *) switch_xml_get_binding_user_data(kazoo_globals.languages_fetch_binding), fetch_handlers);
+
+ if(kazoo_globals.chatplan_fetch_binding != NULL)
+ bind_fetch_profile((ei_xml_agent_t *) switch_xml_get_binding_user_data(kazoo_globals.chatplan_fetch_binding), fetch_handlers);
+}
+
static switch_status_t bind_fetch_agent(switch_xml_section_t section, switch_xml_binding_t **binding) {
switch_memory_pool_t *pool = NULL;
ei_xml_agent_t *agent;
@@ -326,6 +390,8 @@ static switch_status_t bind_fetch_agent(switch_xml_section_t section, switch_xml
switch_thread_cond_create(&agent->new_reply, pool);
agent->replies = NULL;
+ bind_fetch_profile(agent, kazoo_globals.fetch_handlers);
+
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Bound to %s XML requests\n"
,xml_section_to_string(section));
@@ -336,6 +402,9 @@ static switch_status_t unbind_fetch_agent(switch_xml_binding_t **binding) {
ei_xml_agent_t *agent;
ei_xml_client_t *client;
+ if(*binding == NULL)
+ return SWITCH_STATUS_GENERR;
+
/* get a pointer to our user_data */
agent = (ei_xml_agent_t *)switch_xml_get_binding_user_data(*binding);
@@ -399,6 +468,9 @@ static switch_status_t remove_xml_client(ei_node_t *ei_node, switch_xml_binding_
ei_xml_client_t *client, *prev = NULL;
int found = 0;
+ if(binding == NULL)
+ return SWITCH_STATUS_GENERR;
+
agent = (ei_xml_agent_t *)switch_xml_get_binding_user_data(binding);
/* write-lock the agent */
@@ -575,8 +647,9 @@ switch_status_t bind_fetch_agents() {
bind_fetch_agent(SWITCH_XML_SECTION_CONFIG, &kazoo_globals.config_fetch_binding);
bind_fetch_agent(SWITCH_XML_SECTION_DIRECTORY, &kazoo_globals.directory_fetch_binding);
bind_fetch_agent(SWITCH_XML_SECTION_DIALPLAN, &kazoo_globals.dialplan_fetch_binding);
- bind_fetch_agent(SWITCH_XML_SECTION_CHATPLAN, &kazoo_globals.chatplan_fetch_binding);
bind_fetch_agent(SWITCH_XML_SECTION_CHANNELS, &kazoo_globals.channels_fetch_binding);
+ bind_fetch_agent(SWITCH_XML_SECTION_LANGUAGES, &kazoo_globals.languages_fetch_binding);
+ bind_fetch_agent(SWITCH_XML_SECTION_CHATPLAN, &kazoo_globals.chatplan_fetch_binding);
return SWITCH_STATUS_SUCCESS;
}
@@ -585,8 +658,9 @@ switch_status_t unbind_fetch_agents() {
unbind_fetch_agent(&kazoo_globals.config_fetch_binding);
unbind_fetch_agent(&kazoo_globals.directory_fetch_binding);
unbind_fetch_agent(&kazoo_globals.dialplan_fetch_binding);
- unbind_fetch_agent(&kazoo_globals.chatplan_fetch_binding);
unbind_fetch_agent(&kazoo_globals.channels_fetch_binding);
+ unbind_fetch_agent(&kazoo_globals.languages_fetch_binding);
+ unbind_fetch_agent(&kazoo_globals.chatplan_fetch_binding);
return SWITCH_STATUS_SUCCESS;
}
@@ -595,8 +669,9 @@ switch_status_t remove_xml_clients(ei_node_t *ei_node) {
remove_xml_client(ei_node, kazoo_globals.config_fetch_binding);
remove_xml_client(ei_node, kazoo_globals.directory_fetch_binding);
remove_xml_client(ei_node, kazoo_globals.dialplan_fetch_binding);
- remove_xml_client(ei_node, kazoo_globals.chatplan_fetch_binding);
remove_xml_client(ei_node, kazoo_globals.channels_fetch_binding);
+ remove_xml_client(ei_node, kazoo_globals.languages_fetch_binding);
+ remove_xml_client(ei_node, kazoo_globals.chatplan_fetch_binding);
return SWITCH_STATUS_SUCCESS;
}
@@ -606,6 +681,9 @@ switch_status_t add_fetch_handler(ei_node_t *ei_node, erlang_pid *from, switch_x
ei_xml_client_t *client;
fetch_handler_t *fetch_handler;
+ if(binding == NULL)
+ return SWITCH_STATUS_GENERR;
+
agent = (ei_xml_agent_t *)switch_xml_get_binding_user_data(binding);
/* write-lock the agent */
@@ -653,8 +731,9 @@ switch_status_t remove_fetch_handlers(ei_node_t *ei_node, erlang_pid *from) {
remove_fetch_handler(ei_node, from, kazoo_globals.config_fetch_binding);
remove_fetch_handler(ei_node, from, kazoo_globals.directory_fetch_binding);
remove_fetch_handler(ei_node, from, kazoo_globals.dialplan_fetch_binding);
- remove_fetch_handler(ei_node, from, kazoo_globals.chatplan_fetch_binding);
remove_fetch_handler(ei_node, from, kazoo_globals.channels_fetch_binding);
+ remove_fetch_handler(ei_node, from, kazoo_globals.languages_fetch_binding);
+ remove_fetch_handler(ei_node, from, kazoo_globals.chatplan_fetch_binding);
return SWITCH_STATUS_SUCCESS;
}
@@ -689,8 +768,9 @@ switch_status_t handle_api_command_streams(ei_node_t *ei_node, switch_stream_han
handle_api_command_stream(ei_node, stream, kazoo_globals.config_fetch_binding);
handle_api_command_stream(ei_node, stream, kazoo_globals.directory_fetch_binding);
handle_api_command_stream(ei_node, stream, kazoo_globals.dialplan_fetch_binding);
- handle_api_command_stream(ei_node, stream, kazoo_globals.chatplan_fetch_binding);
handle_api_command_stream(ei_node, stream, kazoo_globals.channels_fetch_binding);
+ handle_api_command_stream(ei_node, stream, kazoo_globals.languages_fetch_binding);
+ handle_api_command_stream(ei_node, stream, kazoo_globals.chatplan_fetch_binding);
return SWITCH_STATUS_SUCCESS;
}
diff --git a/src/mod/event_handlers/mod_kazoo/kazoo_fields.h b/src/mod/event_handlers/mod_kazoo/kazoo_fields.h
new file mode 100644
index 0000000000..6c8111bfe4
--- /dev/null
+++ b/src/mod/event_handlers/mod_kazoo/kazoo_fields.h
@@ -0,0 +1,197 @@
+/*
+* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+* Copyright (C) 2005-2012, Anthony Minessale II
+*
+* Version: MPL 1.1
+*
+* The contents of this file are subject to the Mozilla Public License Version
+* 1.1 (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+* http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS IS" basis,
+* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+* for the specific language governing rights and limitations under the
+* License.
+*
+* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+*
+* The Initial Developer of the Original Code is
+* Anthony Minessale II
+* Portions created by the Initial Developer are Copyright (C)
+* the Initial Developer. All Rights Reserved.
+*
+* Based on mod_skel by
+* Anthony Minessale II
+*
+* Contributor(s):
+*
+* Daniel Bryars
+* Tim Brown
+* Anthony Minessale II
+* William King
+* Mike Jerris
+*
+* kazoo.c -- Sends FreeSWITCH events to an AMQP broker
+*
+*/
+
+#ifndef KAZOO_FIELDS_H
+#define KAZOO_FIELDS_H
+
+#include
+
+#define MAX_LIST_FIELDS 25
+
+typedef struct kazoo_log_levels kazoo_loglevels_t;
+typedef kazoo_loglevels_t *kazoo_loglevels_ptr;
+
+struct kazoo_log_levels
+{
+ switch_log_level_t success_log_level;
+ switch_log_level_t failed_log_level;
+ switch_log_level_t warn_log_level;
+ switch_log_level_t info_log_level;
+ switch_log_level_t time_log_level;
+ switch_log_level_t filtered_event_log_level;
+ switch_log_level_t filtered_field_log_level;
+
+};
+
+typedef struct kazoo_logging kazoo_logging_t;
+typedef kazoo_logging_t *kazoo_logging_ptr;
+
+struct kazoo_logging
+{
+ kazoo_loglevels_ptr levels;
+ const char *profile_name;
+ const char *event_name;
+};
+
+typedef struct kazoo_list_s {
+ char *value[MAX_LIST_FIELDS];
+ int size;
+} kazoo_list_t;
+
+typedef enum {
+ FILTER_COMPARE_REGEX,
+ FILTER_COMPARE_LIST,
+ FILTER_COMPARE_VALUE,
+ FILTER_COMPARE_PREFIX,
+ FILTER_COMPARE_EXISTS,
+ FILTER_COMPARE_FIELD
+
+} kazoo_filter_compare_type;
+
+typedef enum {
+ FILTER_EXCLUDE,
+ FILTER_INCLUDE,
+ FILTER_ENSURE
+} kazoo_filter_type;
+
+typedef struct kazoo_filter_t {
+ kazoo_filter_type type;
+ kazoo_filter_compare_type compare;
+ char* name;
+ char* value;
+ kazoo_list_t list;
+ struct kazoo_filter_t* next;
+} kazoo_filter, *kazoo_filter_ptr;
+
+
+typedef enum {
+ JSON_NONE,
+ JSON_STRING,
+ JSON_NUMBER,
+ JSON_BOOLEAN,
+ JSON_OBJECT,
+ JSON_RAW
+} kazoo_json_field_type;
+
+typedef enum {
+ FIELD_NONE,
+ FIELD_COPY,
+ FIELD_STATIC,
+ FIELD_FIRST_OF,
+ FIELD_EXPAND,
+ FIELD_PREFIX,
+ FIELD_OBJECT,
+ FIELD_GROUP,
+ FIELD_REFERENCE
+
+} kazoo_field_type;
+
+typedef struct kazoo_field_t kazoo_field;
+typedef kazoo_field *kazoo_field_ptr;
+
+typedef struct kazoo_fields_t kazoo_fields;
+typedef kazoo_fields *kazoo_fields_ptr;
+
+typedef struct kazoo_definition_t kazoo_definition;
+typedef kazoo_definition *kazoo_definition_ptr;
+
+struct kazoo_field_t {
+ char* name;
+ char* value;
+ char* as;
+ kazoo_list_t list;
+ switch_bool_t exclude_prefix;
+ kazoo_field_type in_type;
+ kazoo_json_field_type out_type;
+ kazoo_filter_ptr filter;
+
+ kazoo_definition_ptr ref;
+ kazoo_field_ptr next;
+ kazoo_fields_ptr children;
+};
+
+struct kazoo_fields_t {
+ kazoo_field_ptr head;
+ int verbose;
+};
+
+
+struct kazoo_definition_t {
+ char* name;
+ kazoo_field_ptr head;
+ kazoo_filter_ptr filter;
+};
+
+struct kazoo_event {
+ kazoo_event_profile_ptr profile;
+ char *name;
+ kazoo_fields_ptr fields;
+ kazoo_filter_ptr filter;
+
+ kazoo_event_t* next;
+};
+
+struct kazoo_event_profile {
+ char *name;
+ kazoo_config_ptr root;
+ switch_bool_t running;
+ switch_memory_pool_t *pool;
+ kazoo_filter_ptr filter;
+ kazoo_fields_ptr fields;
+ kazoo_event_ptr events;
+
+ kazoo_loglevels_ptr logging;
+};
+
+struct kazoo_fetch_profile {
+ char *name;
+ kazoo_config_ptr root;
+ switch_bool_t running;
+ switch_memory_pool_t *pool;
+ kazoo_fields_ptr fields;
+ int fetch_timeout;
+ switch_mutex_t *fetch_reply_mutex;
+ switch_hash_t *fetch_reply_hash;
+ switch_xml_binding_t *fetch_binding;
+ switch_xml_section_t section;
+
+ kazoo_loglevels_ptr logging;
+};
+
+#endif /* KAZOO_FIELDS_H */
+
diff --git a/src/mod/event_handlers/mod_kazoo/kazoo_message.c b/src/mod/event_handlers/mod_kazoo/kazoo_message.c
new file mode 100644
index 0000000000..74ddff6647
--- /dev/null
+++ b/src/mod/event_handlers/mod_kazoo/kazoo_message.c
@@ -0,0 +1,436 @@
+/*
+* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+* Copyright (C) 2005-2012, Anthony Minessale II
+*
+* Version: MPL 1.1
+*
+* The contents of this file are subject to the Mozilla Public License Version
+* 1.1 (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+* http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS IS" basis,
+* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+* for the specific language governing rights and limitations under the
+* License.
+*
+* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+*
+* The Initial Developer of the Original Code is
+* Anthony Minessale II
+* Portions created by the Initial Developer are Copyright (C)
+* the Initial Developer. All Rights Reserved.
+*
+* Based on mod_skel by
+* Anthony Minessale II
+*
+* Contributor(s):
+*
+* Daniel Bryars
+* Tim Brown
+* Anthony Minessale II
+* William King
+* Mike Jerris
+*
+* kazoo.c -- Sends FreeSWITCH events to an AMQP broker
+*
+*/
+
+#include "mod_kazoo.h"
+
+/* deletes then add */
+void kazoo_cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
+{
+ cJSON_DeleteItemFromObject(object, string);
+ cJSON_AddItemToObject(object, string, item);
+}
+
+static int inline filter_compare(switch_event_t* evt, kazoo_filter_ptr filter)
+{
+ switch_event_header_t *header;
+ int hasValue = 0, n;
+ char *value = NULL, *expr = NULL;
+
+ switch(filter->compare) {
+
+ case FILTER_COMPARE_EXISTS:
+ hasValue = switch_event_get_header(evt, filter->name) != NULL ? 1 : 0;
+ break;
+
+ case FILTER_COMPARE_VALUE:
+ if (*filter->name == '$') {
+ value = expr = kz_event_expand_headers(evt, filter->name);
+ } else {
+ value = switch_event_get_header(evt, filter->name);
+ }
+ hasValue = value ? !strcmp(value, filter->value) : 0;
+ break;
+
+ case FILTER_COMPARE_FIELD:
+ if (*filter->name == '$') {
+ value = expr = kz_event_expand_headers(evt, filter->name);
+ } else {
+ value = switch_event_get_header(evt, filter->name);
+ }
+ hasValue = value ? !strcmp(value, switch_event_get_header_nil(evt, filter->value)) : 0;
+ break;
+
+ case FILTER_COMPARE_PREFIX:
+ for (header = evt->headers; header; header = header->next) {
+ if(!strncmp(header->name, filter->value, strlen(filter->value))) {
+ hasValue = 1;
+ break;
+ }
+ }
+ break;
+
+ case FILTER_COMPARE_LIST:
+ if (*filter->name == '$') {
+ value = expr = kz_event_expand_headers(evt, filter->name);
+ } else {
+ value = switch_event_get_header(evt, filter->name);
+ }
+ if(value) {
+ for(n = 0; n < filter->list.size; n++) {
+ if(!strncmp(value, filter->list.value[n], strlen(filter->list.value[n]))) {
+ hasValue = 1;
+ break;
+ }
+ }
+ }
+ break;
+
+ case FILTER_COMPARE_REGEX:
+ break;
+
+ default:
+ break;
+ }
+
+ switch_safe_free(expr);
+
+ return hasValue;
+}
+
+static kazoo_filter_ptr inline filter_event(switch_event_t* evt, kazoo_filter_ptr filter)
+{
+ while(filter) {
+ int hasValue = filter_compare(evt, filter);
+ if(filter->type == FILTER_EXCLUDE) {
+ if(hasValue)
+ break;
+ } else if(filter->type == FILTER_INCLUDE) {
+ if(!hasValue)
+ break;
+ }
+ filter = filter->next;
+ }
+ return filter;
+}
+
+static void kazoo_event_init_json_fields(switch_event_t *event, cJSON *json)
+{
+ switch_event_header_t *hp;
+ for (hp = event->headers; hp; hp = hp->next) {
+ if (hp->idx) {
+ cJSON *a = cJSON_CreateArray();
+ int i;
+
+ for(i = 0; i < hp->idx; i++) {
+ cJSON_AddItemToArray(a, cJSON_CreateString(hp->array[i]));
+ }
+
+ cJSON_AddItemToObject(json, hp->name, a);
+
+ } else {
+ cJSON_AddItemToObject(json, hp->name, cJSON_CreateString(hp->value));
+ }
+ }
+}
+
+static switch_status_t kazoo_event_init_json(kazoo_fields_ptr fields1, kazoo_fields_ptr fields2, switch_event_t* evt, cJSON** clone)
+{
+ switch_status_t status;
+ if( (fields2 && fields2->verbose)
+ || (fields1 && fields1->verbose)
+ || ( (!fields2) && (!fields1)) ) {
+ status = switch_event_serialize_json_obj(evt, clone);
+ } else {
+ status = SWITCH_STATUS_SUCCESS;
+ *clone = cJSON_CreateObject();
+ if((*clone) == NULL) {
+ status = SWITCH_STATUS_GENERR;
+ }
+ }
+ return status;
+}
+
+static cJSON * kazoo_event_json_value(kazoo_json_field_type type, const char *value) {
+ cJSON *item = NULL;
+ switch(type) {
+ case JSON_STRING:
+ item = cJSON_CreateString(value);
+ break;
+
+ case JSON_NUMBER:
+ item = cJSON_CreateNumber(strtod(value, NULL));
+ break;
+
+ case JSON_BOOLEAN:
+ item = cJSON_CreateBool(switch_true(value));
+ break;
+
+ case JSON_OBJECT:
+ item = cJSON_CreateObject();
+ break;
+
+ case JSON_RAW:
+ item = cJSON_CreateRaw(value);
+ break;
+
+ default:
+ break;
+ };
+
+ return item;
+}
+
+static cJSON * kazoo_event_add_json_value(cJSON *dst, kazoo_field_ptr field, const char *as, const char *value) {
+ cJSON *item = NULL;
+ if(value || field->out_type == JSON_OBJECT) {
+ if((item = kazoo_event_json_value(field->out_type, value)) != NULL) {
+ kazoo_cJSON_AddItemToObject(dst, as, item);
+ }
+ }
+ return item;
+}
+
+
+cJSON * kazoo_event_add_field_to_json(cJSON *dst, switch_event_t *src, kazoo_field_ptr field)
+{
+ switch_event_header_t *header;
+ char *expanded;
+ uint i, n;
+ cJSON *item = NULL;
+
+ switch(field->in_type) {
+ case FIELD_COPY:
+ if((header = switch_event_get_header_ptr(src, field->name)) != NULL) {
+ if (header->idx) {
+ item = cJSON_CreateArray();
+ for(i = 0; i < header->idx; i++) {
+ cJSON_AddItemToArray(item, kazoo_event_json_value(field->out_type, header->array[i]));
+ }
+ kazoo_cJSON_AddItemToObject(dst, field->as ? field->as : field->name, item);
+ } else {
+ item = kazoo_event_add_json_value(dst, field, field->as ? field->as : field->name, header->value);
+ }
+ }
+ break;
+
+ case FIELD_EXPAND:
+ expanded = kz_event_expand_headers(src, field->value);
+ if(expanded != NULL && !zstr(expanded)) {
+ item = kazoo_event_add_json_value(dst, field, field->as ? field->as : field->name, expanded);
+ free(expanded);
+ }
+ break;
+
+ case FIELD_FIRST_OF:
+ for(n = 0; n < field->list.size; n++) {
+ if(*field->list.value[n] == '#') {
+ item = kazoo_event_add_json_value(dst, field, field->as ? field->as : field->name, ++field->list.value[n]);
+ break;
+ } else {
+ header = switch_event_get_header_ptr(src, field->list.value[n]);
+ if(header) {
+ if (header->idx) {
+ item = cJSON_CreateArray();
+ for(i = 0; i < header->idx; i++) {
+ cJSON_AddItemToArray(item, kazoo_event_json_value(field->out_type, header->array[i]));
+ }
+ kazoo_cJSON_AddItemToObject(dst, field->as ? field->as : field->name, item);
+ } else {
+ item = kazoo_event_add_json_value(dst, field, field->as ? field->as : field->name, header->value);
+ }
+ break;
+ }
+ }
+ }
+ break;
+
+ case FIELD_PREFIX:
+ for (header = src->headers; header; header = header->next) {
+ if(!strncmp(header->name, field->name, strlen(field->name))) {
+ if (header->idx) {
+ cJSON *array = cJSON_CreateArray();
+ for(i = 0; i < header->idx; i++) {
+ cJSON_AddItemToArray(array, kazoo_event_json_value(field->out_type, header->array[i]));
+ }
+ kazoo_cJSON_AddItemToObject(dst, field->exclude_prefix ? header->name+strlen(field->name) : header->name, array);
+ } else {
+ kazoo_event_add_json_value(dst, field, field->exclude_prefix ? header->name+strlen(field->name) : header->name, header->value);
+ }
+ }
+ }
+ break;
+
+ case FIELD_STATIC:
+ item = kazoo_event_add_json_value(dst, field, field->name, field->value);
+ break;
+
+ case FIELD_GROUP:
+ item = dst;
+ break;
+
+ default:
+ break;
+ }
+
+ return item;
+}
+
+static switch_status_t kazoo_event_add_fields_to_json(kazoo_logging_ptr logging, cJSON *dst, switch_event_t *src, kazoo_field_ptr field) {
+
+ kazoo_filter_ptr filter;
+ cJSON *item = NULL;
+ while(field) {
+ if(field->in_type == FIELD_REFERENCE) {
+ if(field->ref) {
+ if((filter = filter_event(src, field->ref->filter)) != NULL) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, logging->levels->filtered_field_log_level, "profile[%s] event %s, referenced field %s filtered by settings %s : %s\n", logging->profile_name, logging->event_name, field->ref->name, filter->name, filter->value);
+ } else {
+ kazoo_event_add_fields_to_json(logging, dst, src, field->ref->head);
+ }
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "profile[%s] event %s, referenced field %s not found\n", logging->profile_name, logging->event_name, field->name);
+ }
+ } else {
+ if((filter = filter_event(src, field->filter)) != NULL) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, logging->levels->filtered_field_log_level, "profile[%s] event %s, field %s filtered by settings %s : %s\n", logging->profile_name, logging->event_name, field->name, filter->name, filter->value);
+ } else {
+ item = kazoo_event_add_field_to_json(dst, src, field);
+ if(field->children && item != NULL) {
+ if(field->children->verbose && field->out_type == JSON_OBJECT) {
+ kazoo_event_init_json_fields(src, item);
+ }
+ kazoo_event_add_fields_to_json(logging, field->out_type == JSON_OBJECT ? item : dst, src, field->children->head);
+ }
+ }
+ }
+
+ field = field->next;
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+
+kazoo_message_ptr kazoo_message_create_event(switch_event_t* evt, kazoo_event_ptr event, kazoo_event_profile_ptr profile)
+{
+ kazoo_message_ptr message;
+ cJSON *JObj = NULL;
+ kazoo_filter_ptr filtered;
+ kazoo_logging_t logging;
+
+ logging.levels = profile->logging;
+ logging.event_name = switch_event_get_header_nil(evt, "Event-Name");
+ logging.profile_name = profile->name;
+
+ switch_event_add_header_string(evt, SWITCH_STACK_BOTTOM, "Switch-Nodename", kazoo_globals.ei_cnode.thisnodename);
+
+
+ message = malloc(sizeof(kazoo_message_t));
+ if(message == NULL) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "error allocating memory for serializing event to json\n");
+ return NULL;
+ }
+ memset(message, 0, sizeof(kazoo_message_t));
+
+ if(profile->filter) {
+ // filtering
+ if((filtered = filter_event(evt, profile->filter)) != NULL) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, logging.levels->filtered_event_log_level, "profile[%s] event %s filtered by profile settings %s : %s\n", logging.profile_name, logging.event_name, filtered->name, filtered->value);
+ kazoo_message_destroy(&message);
+ return NULL;
+ }
+ }
+
+ if(event && event->filter) {
+ if((filtered = filter_event(evt, event->filter)) != NULL) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, logging.levels->filtered_event_log_level, "profile[%s] event %s filtered by event settings %s : %s\n", logging.profile_name, logging.event_name, filtered->name, filtered->value);
+ kazoo_message_destroy(&message);
+ return NULL;
+ }
+ }
+
+ kazoo_event_init_json(profile->fields, event ? event->fields : NULL, evt, &JObj);
+
+ if(profile->fields)
+ kazoo_event_add_fields_to_json(&logging, JObj, evt, profile->fields->head);
+
+ if(event && event->fields)
+ kazoo_event_add_fields_to_json(&logging, JObj, evt, event->fields->head);
+
+ message->JObj = JObj;
+
+
+ return message;
+
+
+}
+
+kazoo_message_ptr kazoo_message_create_fetch(switch_event_t* evt, kazoo_fetch_profile_ptr profile)
+{
+ kazoo_message_ptr message;
+ cJSON *JObj = NULL;
+ kazoo_logging_t logging;
+
+ logging.levels = profile->logging;
+ logging.event_name = switch_event_get_header_nil(evt, "Event-Name");
+ logging.profile_name = profile->name;
+
+ switch_event_add_header_string(evt, SWITCH_STACK_BOTTOM, "Switch-Nodename", kazoo_globals.ei_cnode.thisnodename);
+
+ message = malloc(sizeof(kazoo_message_t));
+ if(message == NULL) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "error allocating memory for serializing event to json\n");
+ return NULL;
+ }
+ memset(message, 0, sizeof(kazoo_message_t));
+
+
+ kazoo_event_init_json(profile->fields, NULL, evt, &JObj);
+
+ if(profile->fields)
+ kazoo_event_add_fields_to_json(&logging, JObj, evt, profile->fields->head);
+
+ message->JObj = JObj;
+
+
+ return message;
+
+
+}
+
+
+void kazoo_message_destroy(kazoo_message_ptr *msg)
+{
+ if (!msg || !*msg) return;
+ if((*msg)->JObj != NULL)
+ cJSON_Delete((*msg)->JObj);
+ switch_safe_free(*msg);
+
+}
+
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4
+ */
diff --git a/src/mod/event_handlers/mod_kazoo/kazoo_message.h b/src/mod/event_handlers/mod_kazoo/kazoo_message.h
new file mode 100644
index 0000000000..eade6c4e7b
--- /dev/null
+++ b/src/mod/event_handlers/mod_kazoo/kazoo_message.h
@@ -0,0 +1,66 @@
+/*
+* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+* Copyright (C) 2005-2012, Anthony Minessale II
+*
+* Version: MPL 1.1
+*
+* The contents of this file are subject to the Mozilla Public License Version
+* 1.1 (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+* http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS IS" basis,
+* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+* for the specific language governing rights and limitations under the
+* License.
+*
+* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+*
+* The Initial Developer of the Original Code is
+* Anthony Minessale II
+* Portions created by the Initial Developer are Copyright (C)
+* the Initial Developer. All Rights Reserved.
+*
+* Based on mod_skel by
+* Anthony Minessale II
+*
+* Contributor(s):
+*
+* Daniel Bryars
+* Tim Brown
+* Anthony Minessale II
+* William King
+* Mike Jerris
+*
+* kazoo.c -- Sends FreeSWITCH events to an AMQP broker
+*
+*/
+
+#ifndef KAZOO_MESSAGE_H
+#define KAZOO_MESSAGE_H
+
+#include
+
+typedef struct {
+ uint64_t timestamp;
+ uint64_t start;
+ uint64_t filter;
+ uint64_t serialize;
+ uint64_t print;
+ uint64_t rk;
+} kazoo_message_times_t, *kazoo_message_times_ptr;
+
+typedef struct {
+ cJSON *JObj;
+} kazoo_message_t, *kazoo_message_ptr;
+
+void kazoo_cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
+cJSON * kazoo_event_add_field_to_json(cJSON *dst, switch_event_t *src, kazoo_field_ptr field);
+kazoo_message_ptr kazoo_message_create_event(switch_event_t* evt, kazoo_event_ptr event, kazoo_event_profile_ptr profile);
+kazoo_message_ptr kazoo_message_create_fetch(switch_event_t* evt, kazoo_fetch_profile_ptr profile);
+
+void kazoo_message_destroy(kazoo_message_ptr *msg);
+
+
+#endif /* KAZOO_MESSAGE_H */
+
diff --git a/src/mod/event_handlers/mod_kazoo/kazoo_node.c b/src/mod/event_handlers/mod_kazoo/kazoo_node.c
index 17da6dc582..a92fe49aa2 100644
--- a/src/mod/event_handlers/mod_kazoo/kazoo_node.c
+++ b/src/mod/event_handlers/mod_kazoo/kazoo_node.c
@@ -53,6 +53,8 @@ static char *REQUEST_ATOMS[] = {
"nixevent",
"sendevent",
"sendmsg",
+ "commands",
+ "command",
"bind",
"getpid",
"version",
@@ -62,7 +64,8 @@ static char *REQUEST_ATOMS[] = {
"fetch_reply",
"config",
"bgapi4",
- "api4"
+ "api4",
+ "json_api"
};
typedef enum {
@@ -72,6 +75,8 @@ typedef enum {
REQUEST_NIXEVENT,
REQUEST_SENDEVENT,
REQUEST_SENDMSG,
+ REQUEST_COMMANDS,
+ REQUEST_COMMAND,
REQUEST_BIND,
REQUEST_GETPID,
REQUEST_VERSION,
@@ -82,11 +87,13 @@ typedef enum {
REQUEST_CONFIG,
REQUEST_BGAPI4,
REQUEST_API4,
+ REQUEST_JSON_API,
REQUEST_MAX
} request_atoms_t;
static switch_status_t find_request(char *atom, int *request) {
- for (int i = 0; i < REQUEST_MAX; i++) {
+ int i;
+ for (i = 0; i < REQUEST_MAX; i++) {
if(!strncmp(atom, REQUEST_ATOMS[i], MAXATOMLEN)) {
*request = i;
return SWITCH_STATUS_SUCCESS;
@@ -200,14 +207,21 @@ SWITCH_DECLARE(switch_status_t) kazoo_api_execute(const char *cmd, const char *a
char *arg_used;
char *cmd_used;
int fire_event = 0;
+ char *arg_expanded;
+ switch_event_t* evt;
switch_assert(stream != NULL);
switch_assert(stream->data != NULL);
switch_assert(stream->write_function != NULL);
- cmd_used = (char *) cmd;
- arg_used = (char *) arg;
+ arg_expanded = (char *) arg;
+ switch_event_create(&evt, SWITCH_EVENT_GENERAL);
+ arg_expanded = switch_event_expand_headers(evt, arg);
+ switch_event_destroy(&evt);
+
+ cmd_used = (char *) cmd;
+ arg_used = arg_expanded;
if (!stream->param_event) {
switch_event_create(&stream->param_event, SWITCH_EVENT_API);
@@ -221,6 +235,9 @@ SWITCH_DECLARE(switch_status_t) kazoo_api_execute(const char *cmd, const char *a
if (arg_used && *arg_used) {
switch_event_add_header_string(stream->param_event, SWITCH_STACK_BOTTOM, "API-Command-Argument", arg_used);
}
+ if (arg_expanded && *arg_expanded) {
+ switch_event_add_header_string(stream->param_event, SWITCH_STACK_BOTTOM, "API-Command-Argument-Expanded", arg_expanded);
+ }
}
@@ -247,10 +264,14 @@ SWITCH_DECLARE(switch_status_t) kazoo_api_execute(const char *cmd, const char *a
switch_safe_free(cmd_used);
}
- if (arg_used != arg) {
+ if (arg_used != arg_expanded) {
switch_safe_free(arg_used);
}
+ if (arg_expanded != arg) {
+ switch_safe_free(arg_expanded);
+ }
+
return status;
}
@@ -267,7 +288,7 @@ static switch_status_t api_exec_stream(char *cmd, char *arg, switch_stream_handl
}
} else if (!stream->data || !strlen(stream->data)) {
*reply = switch_mprintf("%s: Command returned no output", cmd);
- status = SWITCH_STATUS_FALSE;
+ status = SWITCH_STATUS_SUCCESS;
} else {
*reply = strdup(stream->data);
status = SWITCH_STATUS_SUCCESS;
@@ -357,14 +378,13 @@ static void *SWITCH_THREAD_FUNC bgapi4_exec(switch_thread_t *thread, void *obj)
return NULL;
}
- SWITCH_STANDARD_STREAM(stream);
+ SWITCH_STANDARD_STREAM(stream);
switch_event_create(&stream.param_event, SWITCH_EVENT_API);
- switch_malloc(send_msg, sizeof(*send_msg));
- memcpy(&send_msg->pid, &acs->pid, sizeof(erlang_pid));
+ switch_malloc(send_msg, sizeof(*send_msg));
+ memcpy(&send_msg->pid, &acs->pid, sizeof(erlang_pid));
ei_x_new_with_version(&send_msg->buf);
-
ei_x_encode_tuple_header(&send_msg->buf, (stream.param_event ? 4 : 3));
if (api_exec_stream(cmd, arg, &stream, &reply) == SWITCH_STATUS_SUCCESS) {
@@ -376,9 +396,9 @@ static void *SWITCH_THREAD_FUNC bgapi4_exec(switch_thread_t *thread, void *obj)
_ei_x_encode_string(&send_msg->buf, acs->uuid_str);
_ei_x_encode_string(&send_msg->buf, reply);
- if (stream.param_event) {
+ if (stream.param_event) {
ei_encode_switch_event_headers_2(&send_msg->buf, stream.param_event, 0);
- }
+ }
if (switch_queue_trypush(ei_node->send_msgs, send_msg) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to send bgapi response %s to %s <%d.%d.%d>\n"
@@ -393,9 +413,9 @@ static void *SWITCH_THREAD_FUNC bgapi4_exec(switch_thread_t *thread, void *obj)
switch_atomic_dec(&ei_node->pending_bgapi);
- if (stream.param_event) {
- switch_event_fire(&stream.param_event);
- }
+ if (stream.param_event) {
+ switch_event_fire(&stream.param_event);
+ }
switch_safe_free(reply);
switch_safe_free(acs->arg);
@@ -412,11 +432,10 @@ static void log_sendmsg_request(char *uuid, switch_event_t *event)
switch_ssize_t hlen = -1;
unsigned long CMD_EXECUTE = switch_hashfunc_default("execute", &hlen);
unsigned long CMD_XFEREXT = switch_hashfunc_default("xferext", &hlen);
- // unsigned long CMD_HANGUP = switch_hashfunc_default("hangup", &hlen);
- // unsigned long CMD_NOMEDIA = switch_hashfunc_default("nomedia", &hlen);
- // unsigned long CMD_UNICAST = switch_hashfunc_default("unicast", &hlen);
if (zstr(cmd)) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "log|%s|invalid \n", uuid);
+ DUMP_EVENT(event);
return;
}
@@ -453,6 +472,7 @@ static void log_sendmsg_request(char *uuid, switch_event_t *event)
static switch_status_t build_event(switch_event_t *event, ei_x_buff * buf) {
int propslist_length, arity;
+ int n=0;
if(!event) {
return SWITCH_STATUS_FALSE;
@@ -462,7 +482,7 @@ static switch_status_t build_event(switch_event_t *event, ei_x_buff * buf) {
return SWITCH_STATUS_FALSE;
}
- while (!ei_decode_tuple_header(buf->buff, &buf->index, &arity)) {
+ while (!ei_decode_tuple_header(buf->buff, &buf->index, &arity) && n < propslist_length) {
char key[1024];
char *value;
@@ -482,9 +502,21 @@ static switch_status_t build_event(switch_event_t *event, ei_x_buff * buf) {
switch_safe_free(event->body);
event->body = value;
} else {
+ if(!strcasecmp(key, "Call-ID")) {
+ switch_core_session_t *session = NULL;
+ if(!zstr(value)) {
+ if ((session = switch_core_session_force_locate(value)) != NULL) {
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ switch_channel_event_set_data(channel, event);
+ switch_core_session_rwunlock(session);
+ }
+ }
+ }
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM | SWITCH_STACK_NODUP, key, value);
}
+ n++;
}
+ ei_skip_term(buf->buff, &buf->index);
return SWITCH_STATUS_SUCCESS;
}
@@ -525,6 +557,16 @@ static switch_status_t erlang_response_ok(ei_x_buff *rbuf) {
return SWITCH_STATUS_SUCCESS;
}
+static switch_status_t erlang_response_ok_uuid(ei_x_buff *rbuf, const char * uuid) {
+ if (rbuf) {
+ ei_x_encode_tuple_header(rbuf, 2);
+ ei_x_encode_atom(rbuf, "ok");
+ ei_x_encode_binary(rbuf, uuid, strlen(uuid));
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
static switch_status_t handle_request_noevents(ei_node_t *ei_node, erlang_pid *pid, ei_x_buff *buf, ei_x_buff *rbuf) {
ei_event_stream_t *event_stream;
@@ -554,6 +596,7 @@ static switch_status_t handle_request_nixevent(ei_node_t *ei_node, erlang_pid *p
switch_event_types_t event_type;
ei_event_stream_t *event_stream;
int custom = 0, length = 0;
+ int i;
if (ei_decode_list_header(buf->buff, &buf->index, &length)
|| length == 0) {
@@ -566,7 +609,7 @@ static switch_status_t handle_request_nixevent(ei_node_t *ei_node, erlang_pid *p
return erlang_response_ok(rbuf);
}
- for (int i = 1; i <= length; i++) {
+ for (i = 1; i <= length; i++) {
if (ei_decode_atom_safe(buf->buff, &buf->index, event_name)) {
switch_mutex_unlock(ei_node->event_streams_mutex);
return erlang_response_badarg(rbuf);
@@ -576,16 +619,22 @@ static switch_status_t handle_request_nixevent(ei_node_t *ei_node, erlang_pid *p
remove_event_binding(event_stream, SWITCH_EVENT_CUSTOM, event_name);
} else if (switch_name_event(event_name, &event_type) == SWITCH_STATUS_SUCCESS) {
switch (event_type) {
+
case SWITCH_EVENT_CUSTOM:
custom++;
break;
+
case SWITCH_EVENT_ALL:
- for (switch_event_types_t type = 0; type < SWITCH_EVENT_ALL; type++) {
+ {
+ switch_event_types_t type;
+ for (type = 0; type < SWITCH_EVENT_ALL; type++) {
if(type != SWITCH_EVENT_CUSTOM) {
remove_event_binding(event_stream, type, NULL);
}
}
break;
+ }
+
default:
remove_event_binding(event_stream, event_type, NULL);
}
@@ -632,6 +681,83 @@ static switch_status_t handle_request_sendevent(ei_node_t *ei_node, erlang_pid *
return erlang_response_badarg(rbuf);
}
+static switch_status_t handle_request_command(ei_node_t *ei_node, erlang_pid *pid, ei_x_buff *buf, ei_x_buff *rbuf) {
+ switch_core_session_t *session;
+ switch_event_t *event = NULL;
+ char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
+ switch_uuid_t cmd_uuid;
+ char cmd_uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
+
+ if (ei_decode_string_or_binary_limited(buf->buff, &buf->index, sizeof(uuid_str), uuid_str)) {
+ return erlang_response_badarg(rbuf);
+ }
+
+ switch_uuid_get(&cmd_uuid);
+ switch_uuid_format(cmd_uuid_str, &cmd_uuid);
+
+ switch_event_create(&event, SWITCH_EVENT_COMMAND);
+ if (build_event(event, buf) != SWITCH_STATUS_SUCCESS) {
+ return erlang_response_badarg(rbuf);
+ }
+
+ log_sendmsg_request(uuid_str, event);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event-uuid", cmd_uuid_str);
+
+ if (zstr_buf(uuid_str) || !(session = switch_core_session_locate(uuid_str))) {
+ return erlang_response_baduuid(rbuf);
+ }
+ switch_core_session_queue_private_event(session, &event, SWITCH_FALSE);
+ switch_core_session_rwunlock(session);
+
+ return erlang_response_ok_uuid(rbuf, cmd_uuid_str);
+}
+
+static switch_status_t handle_request_commands(ei_node_t *ei_node, erlang_pid *pid, ei_x_buff *buf, ei_x_buff *rbuf) {
+ switch_core_session_t *session;
+ char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
+ int propslist_length, n;
+ switch_uuid_t cmd_uuid;
+ char cmd_uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
+
+ if (ei_decode_string_or_binary_limited(buf->buff, &buf->index, sizeof(uuid_str), uuid_str)) {
+ return erlang_response_badarg(rbuf);
+ }
+
+ if (zstr_buf(uuid_str) || !(session = switch_core_session_locate(uuid_str))) {
+ return erlang_response_baduuid(rbuf);
+ }
+
+ switch_uuid_get(&cmd_uuid);
+ switch_uuid_format(cmd_uuid_str, &cmd_uuid);
+
+ if (ei_decode_list_header(buf->buff, &buf->index, &propslist_length)) {
+ switch_core_session_rwunlock(session);
+ return SWITCH_STATUS_FALSE;
+ }
+
+ for(n = 0; n < propslist_length; n++) {
+ switch_event_t *event = NULL;
+ switch_event_create(&event, SWITCH_EVENT_COMMAND);
+ if (build_event(event, buf) != SWITCH_STATUS_SUCCESS) {
+ switch_core_session_rwunlock(session);
+ return erlang_response_badarg(rbuf);
+ }
+ log_sendmsg_request(uuid_str, event);
+ if(n == (propslist_length - 1)) {
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event-uuid", cmd_uuid_str);
+ } else {
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event-uuid", "null");
+// switch_event_del_header_val(event, "event-uuid-name", NULL);
+ }
+ switch_core_session_queue_private_event(session, &event, SWITCH_FALSE);
+ }
+
+ switch_core_session_rwunlock(session);
+
+ return erlang_response_ok_uuid(rbuf, cmd_uuid_str);
+
+}
+
static switch_status_t handle_request_sendmsg(ei_node_t *ei_node, erlang_pid *pid, ei_x_buff *buf, ei_x_buff *rbuf) {
switch_core_session_t *session;
switch_event_t *event = NULL;
@@ -659,8 +785,8 @@ static switch_status_t handle_request_sendmsg(ei_node_t *ei_node, erlang_pid *pi
static switch_status_t handle_request_config(ei_node_t *ei_node, erlang_pid *pid, ei_x_buff *buf, ei_x_buff *rbuf) {
- fetch_config_filters();
- return erlang_response_ok(rbuf);
+ fetch_config();
+ return erlang_response_ok(rbuf);
}
static switch_status_t handle_request_bind(ei_node_t *ei_node, erlang_pid *pid, ei_x_buff *buf, ei_x_buff *rbuf) {
@@ -675,8 +801,10 @@ static switch_status_t handle_request_bind(ei_node_t *ei_node, erlang_pid *pid,
switch(section) {
case SWITCH_XML_SECTION_CONFIG:
add_fetch_handler(ei_node, pid, kazoo_globals.config_fetch_binding);
- if(!kazoo_globals.config_filters_fetched)
- fetch_config_filters();
+ if(!kazoo_globals.config_fetched) {
+ kazoo_globals.config_fetched = 1;
+ fetch_config();
+ }
break;
case SWITCH_XML_SECTION_DIRECTORY:
add_fetch_handler(ei_node, pid, kazoo_globals.directory_fetch_binding);
@@ -684,12 +812,15 @@ static switch_status_t handle_request_bind(ei_node_t *ei_node, erlang_pid *pid,
case SWITCH_XML_SECTION_DIALPLAN:
add_fetch_handler(ei_node, pid, kazoo_globals.dialplan_fetch_binding);
break;
- case SWITCH_XML_SECTION_CHATPLAN:
- add_fetch_handler(ei_node, pid, kazoo_globals.chatplan_fetch_binding);
- break;
case SWITCH_XML_SECTION_CHANNELS:
add_fetch_handler(ei_node, pid, kazoo_globals.channels_fetch_binding);
break;
+ case SWITCH_XML_SECTION_LANGUAGES:
+ add_fetch_handler(ei_node, pid, kazoo_globals.languages_fetch_binding);
+ break;
+ case SWITCH_XML_SECTION_CHATPLAN:
+ add_fetch_handler(ei_node, pid, kazoo_globals.chatplan_fetch_binding);
+ break;
default:
return erlang_response_badarg(rbuf);
}
@@ -796,10 +927,10 @@ static switch_status_t handle_request_api4(ei_node_t *ei_node, erlang_pid *pid,
status = api_exec_stream(cmd, arg, &stream, &reply);
if (status == SWITCH_STATUS_SUCCESS) {
- ei_x_encode_tuple_header(buf, 2);
+ ei_x_encode_tuple_header(rbuf, 2);
ei_x_encode_atom(rbuf, "ok");
} else {
- ei_x_encode_tuple_header(buf, (stream.param_event ? 3 : 2));
+ ei_x_encode_tuple_header(rbuf, (stream.param_event ? 3 : 2));
ei_x_encode_atom(rbuf, "error");
}
@@ -822,6 +953,61 @@ static switch_status_t handle_request_api4(ei_node_t *ei_node, erlang_pid *pid,
return SWITCH_STATUS_SUCCESS;
}
+static switch_status_t handle_request_json_api(ei_node_t *ei_node, erlang_pid *pid, ei_x_buff *buf, ei_x_buff *rbuf)
+{
+ char *arg;
+ cJSON *jcmd = NULL;
+ switch_core_session_t *session = NULL;
+ const char *uuid = NULL;
+ char *response = NULL;
+ const char *parse_end = NULL;
+ switch_status_t status = SWITCH_STATUS_SUCCESS;
+
+ if (ei_decode_string_or_binary(buf->buff, &buf->index, &arg)) {
+ return erlang_response_badarg(rbuf);
+ }
+
+ jcmd = cJSON_ParseWithOpts(arg, &parse_end, 0);
+
+ if (!jcmd) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "json api error: %s\n", parse_end);
+ ei_x_encode_tuple_header(rbuf, 2);
+ ei_x_encode_atom(rbuf, "error");
+ ei_x_encode_tuple_header(rbuf, 2);
+ ei_x_encode_atom(rbuf, "parse_error");
+ _ei_x_encode_string(rbuf, parse_end);
+ return status;
+ }
+
+ if ((uuid = cJSON_GetObjectCstr(jcmd, "uuid"))) {
+ if (!(session = switch_core_session_locate(uuid))) {
+ return erlang_response_baduuid(rbuf);
+ }
+ }
+
+ status = switch_json_api_execute(jcmd, session, NULL);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "json api (%i): %s\n", status , arg);
+
+ response = cJSON_PrintUnformatted(jcmd);
+ ei_x_encode_tuple_header(rbuf, 2);
+ if (status == SWITCH_STATUS_SUCCESS) {
+ ei_x_encode_atom(rbuf, "ok");
+ } else {
+ ei_x_encode_atom(rbuf, "error");
+ }
+ _ei_x_encode_string(rbuf, response);
+ switch_safe_free(response);
+
+ cJSON_Delete(jcmd);
+ switch_safe_free(arg);
+
+ if (session) {
+ switch_core_session_rwunlock(session);
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
static switch_status_t handle_request_api(ei_node_t *ei_node, erlang_pid *pid, ei_x_buff *buf, ei_x_buff *rbuf) {
char cmd[MAXATOMLEN + 1];
char *arg;
@@ -834,7 +1020,7 @@ static switch_status_t handle_request_api(ei_node_t *ei_node, erlang_pid *pid, e
return erlang_response_badarg(rbuf);
}
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "exec: %s(%s)\n", cmd, arg);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "exec: %s(%s)\n", cmd, arg);
if (rbuf) {
char *reply;
@@ -858,9 +1044,9 @@ static switch_status_t handle_request_api(ei_node_t *ei_node, erlang_pid *pid, e
static switch_status_t handle_request_event(ei_node_t *ei_node, erlang_pid *pid, ei_x_buff *buf, ei_x_buff *rbuf) {
char event_name[MAXATOMLEN + 1];
- switch_event_types_t event_type;
ei_event_stream_t *event_stream;
- int custom = 0, length = 0;
+ int length = 0;
+ int i;
if (ei_decode_list_header(buf->buff, &buf->index, &length) || !length) {
return erlang_response_badarg(rbuf);
@@ -868,38 +1054,18 @@ static switch_status_t handle_request_event(ei_node_t *ei_node, erlang_pid *pid,
switch_mutex_lock(ei_node->event_streams_mutex);
if (!(event_stream = find_event_stream(ei_node->event_streams, pid))) {
- event_stream = new_event_stream(&ei_node->event_streams, pid);
+ event_stream = new_event_stream(ei_node, pid);
/* ensure we are notified if the requesting processes dies so we can clean up */
ei_link(ei_node, ei_self(&kazoo_globals.ei_cnode), pid);
}
- for (int i = 1; i <= length; i++) {
+ for (i = 1; i <= length; i++) {
+
if (ei_decode_atom_safe(buf->buff, &buf->index, event_name)) {
switch_mutex_unlock(ei_node->event_streams_mutex);
return erlang_response_badarg(rbuf);
}
-
- if (custom) {
- add_event_binding(event_stream, SWITCH_EVENT_CUSTOM, event_name);
- } else if (switch_name_event(event_name, &event_type) == SWITCH_STATUS_SUCCESS) {
- switch (event_type) {
- case SWITCH_EVENT_CUSTOM:
- custom++;
- break;
- case SWITCH_EVENT_ALL:
- for (switch_event_types_t type = 0; type < SWITCH_EVENT_ALL; type++) {
- if(type != SWITCH_EVENT_CUSTOM) {
- add_event_binding(event_stream, type, NULL);
- }
- }
- break;
- default:
- add_event_binding(event_stream, event_type, NULL);
- }
- } else {
- switch_mutex_unlock(ei_node->event_streams_mutex);
- return erlang_response_badarg(rbuf);
- }
+ add_event_binding(event_stream, event_name);
}
switch_mutex_unlock(ei_node->event_streams_mutex);
@@ -935,13 +1101,13 @@ static switch_status_t handle_request_fetch_reply(ei_node_t *ei_node, erlang_pid
}
if (ei_decode_string_or_binary(buf->buff, &buf->index, &xml_str)) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Ignoring a fetch reply without XML\n");
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Ignoring a fetch reply without XML : %s \n", uuid_str);
return erlang_response_badarg(rbuf);
}
if (zstr(xml_str)) {
switch_safe_free(xml_str);
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Ignoring an empty fetch reply\n");
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Ignoring an empty fetch reply : %s\n", uuid_str);
return erlang_response_badarg(rbuf);
}
@@ -955,21 +1121,24 @@ static switch_status_t handle_request_fetch_reply(ei_node_t *ei_node, erlang_pid
case SWITCH_XML_SECTION_DIALPLAN:
result = fetch_reply(uuid_str, xml_str, kazoo_globals.dialplan_fetch_binding);
break;
- case SWITCH_XML_SECTION_CHATPLAN:
- result = fetch_reply(uuid_str, xml_str, kazoo_globals.chatplan_fetch_binding);
- break;
case SWITCH_XML_SECTION_CHANNELS:
result = fetch_reply(uuid_str, xml_str, kazoo_globals.channels_fetch_binding);
break;
+ case SWITCH_XML_SECTION_LANGUAGES:
+ result = fetch_reply(uuid_str, xml_str, kazoo_globals.languages_fetch_binding);
+ break;
+ case SWITCH_XML_SECTION_CHATPLAN:
+ result = fetch_reply(uuid_str, xml_str, kazoo_globals.chatplan_fetch_binding);
+ break;
default:
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Recieved fetch reply for an unknown configuration section: %s\n", section_str);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Received fetch reply %s for an unknown configuration section: %s : %s\n", uuid_str, section_str, xml_str);
return erlang_response_badarg(rbuf);
}
if (result == SWITCH_STATUS_SUCCESS) {
return erlang_response_ok(rbuf);
} else {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Recieved fetch reply for an unknown/expired UUID: %s\n", uuid_str);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Received fetch reply %s is unknown or has expired : %s\n", uuid_str, xml_str);
return erlang_response_baduuid(rbuf);
}
}
@@ -988,12 +1157,12 @@ static switch_status_t handle_kazoo_request(ei_node_t *ei_node, erlang_pid *pid,
}
if (ei_decode_atom_safe(buf->buff, &buf->index, atom)) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Recieved mod_kazoo message that did not contain a command (ensure you are using Kazoo v2.14+).\n");
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Received mod_kazoo message that did not contain a command (ensure you are using Kazoo v2.14+).\n");
return erlang_response_badarg(rbuf);
}
if (find_request(atom, &request) != SWITCH_STATUS_SUCCESS) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Recieved mod_kazoo message for unimplemented feature (ensure you are using Kazoo v2.14+): %s\n", atom);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Received mod_kazoo message for unimplemented feature (ensure you are using Kazoo v2.14+): %s\n", atom);
return erlang_response_badarg(rbuf);
}
@@ -1010,6 +1179,10 @@ static switch_status_t handle_kazoo_request(ei_node_t *ei_node, erlang_pid *pid,
return handle_request_sendevent(ei_node, pid, buf, rbuf);
case REQUEST_SENDMSG:
return handle_request_sendmsg(ei_node, pid, buf, rbuf);
+ case REQUEST_COMMAND:
+ return handle_request_command(ei_node, pid, buf, rbuf);
+ case REQUEST_COMMANDS:
+ return handle_request_commands(ei_node, pid, buf, rbuf);
case REQUEST_BIND:
return handle_request_bind(ei_node, pid, buf, rbuf);
case REQUEST_GETPID:
@@ -1024,12 +1197,14 @@ static switch_status_t handle_kazoo_request(ei_node_t *ei_node, erlang_pid *pid,
return handle_request_event(ei_node, pid, buf, rbuf);
case REQUEST_FETCH_REPLY:
return handle_request_fetch_reply(ei_node, pid, buf, rbuf);
- case REQUEST_CONFIG:
- return handle_request_config(ei_node, pid, buf, rbuf);
- case REQUEST_BGAPI4:
- return handle_request_bgapi4(ei_node, pid, buf, rbuf);
+ case REQUEST_CONFIG:
+ return handle_request_config(ei_node, pid, buf, rbuf);
+ case REQUEST_BGAPI4:
+ return handle_request_bgapi4(ei_node, pid, buf, rbuf);
case REQUEST_API4:
return handle_request_api4(ei_node, pid, buf, rbuf);
+ case REQUEST_JSON_API:
+ return handle_request_json_api(ei_node, pid, buf, rbuf);
default:
return erlang_response_notimplemented(rbuf);
}
@@ -1052,7 +1227,7 @@ static switch_status_t handle_mod_kazoo_request(ei_node_t *ei_node, erlang_msg *
ei_decode_tuple_header(buf->buff, &buf->index, &arity);
if (ei_decode_atom_safe(buf->buff, &buf->index, atom)) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Recieved erlang message tuple that did not start with an atom (ensure you are using Kazoo v2.14+).\n");
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Received erlang message tuple that did not start with an atom (ensure you are using Kazoo v2.14+).\n");
return SWITCH_STATUS_GENERR;
}
@@ -1108,7 +1283,7 @@ static switch_status_t handle_mod_kazoo_request(ei_node_t *ei_node, erlang_msg *
return status;
} else {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Recieved inappropriate erlang message (ensure you are using Kazoo v2.14+)\n");
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Received inappropriate erlang message (ensure you are using Kazoo v2.14+)\n");
return SWITCH_STATUS_GENERR;
}
}
@@ -1214,7 +1389,7 @@ static switch_status_t handle_erl_send(ei_node_t *ei_node, erlang_msg *msg, ei_x
} else if (!strncmp(msg->toname, "mod_kazoo", MAXATOMLEN)) {
return handle_mod_kazoo_request(ei_node, msg, buf);
} else {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Recieved erlang message to unknown process \"%s\" (ensure you are using Kazoo v2.14+).\n", msg->toname);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Received erlang message to unknown process \"%s\" (ensure you are using Kazoo v2.14+).\n", msg->toname);
return SWITCH_STATUS_GENERR;
}
}
@@ -1262,7 +1437,7 @@ static void *SWITCH_THREAD_FUNC receive_handler(switch_thread_t *thread, void *o
while (switch_test_flag(ei_node, LFLAG_RUNNING) && switch_test_flag(&kazoo_globals, LFLAG_RUNNING)) {
void *pop;
- if (switch_queue_pop_timeout(ei_node->received_msgs, &pop, 500000) == SWITCH_STATUS_SUCCESS) {
+ if (switch_queue_pop_timeout(ei_node->received_msgs, &pop, 100000) == SWITCH_STATUS_SUCCESS) {
ei_received_msg_t *received_msg = (ei_received_msg_t *) pop;
handle_erl_msg(ei_node, &received_msg->msg, &received_msg->buf);
ei_x_free(&received_msg->buf);
@@ -1313,7 +1488,7 @@ static void *SWITCH_THREAD_FUNC handle_node(switch_thread_t *thread, void *obj)
}
while (++send_msg_count <= kazoo_globals.send_msg_batch
- && switch_queue_trypop(ei_node->send_msgs, &pop) == SWITCH_STATUS_SUCCESS) {
+ && switch_queue_pop_timeout(ei_node->send_msgs, &pop, 20000) == SWITCH_STATUS_SUCCESS) {
ei_send_msg_t *send_msg = (ei_send_msg_t *) pop;
ei_helper_send(ei_node, &send_msg->pid, &send_msg->buf);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Sent erlang message to %s <%d.%d.%d>\n"
@@ -1431,16 +1606,18 @@ switch_status_t new_kazoo_node(int nodefd, ErlConnect *conn) {
ei_node->nodefd = nodefd;
ei_node->peer_nodename = switch_core_strdup(ei_node->pool, conn->nodename);
ei_node->created_time = switch_micro_time_now();
+ ei_node->legacy = kazoo_globals.legacy_events;
+ ei_node->event_stream_framing = kazoo_globals.event_stream_framing;
/* store the IP and node name we are talking with */
switch_os_sock_put(&ei_node->socket, (switch_os_socket_t *)&nodefd, pool);
switch_socket_addr_get(&sa, SWITCH_TRUE, ei_node->socket);
- ei_node->local_port = switch_sockaddr_get_port(sa);
+ ei_node->remote_port = switch_sockaddr_get_port(sa);
switch_get_addr(ei_node->remote_ip, sizeof (ei_node->remote_ip), sa);
switch_socket_addr_get(&sa, SWITCH_FALSE, ei_node->socket);
- ei_node->remote_port = switch_sockaddr_get_port(sa);
+ ei_node->local_port = switch_sockaddr_get_port(sa);
switch_get_addr(ei_node->local_ip, sizeof (ei_node->local_ip), sa);
switch_queue_create(&ei_node->send_msgs, MAX_QUEUE_LEN, pool);
@@ -1451,8 +1628,7 @@ switch_status_t new_kazoo_node(int nodefd, ErlConnect *conn) {
/* when we start we are running */
switch_set_flag(ei_node, LFLAG_RUNNING);
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "New erlang connection from node %s (%s:%d)\n", ei_node->peer_nodename, ei_node->remote_ip, ei_node->remote_port);
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "New erlang connection to node %s (%s:%d)\n", ei_node->peer_nodename, ei_node->local_ip, ei_node->local_port);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "New erlang connection from node %s (%s:%d) -> (%s:%d)\n", ei_node->peer_nodename, ei_node->remote_ip, ei_node->remote_port, ei_node->local_ip, ei_node->local_port);
for(i = 0; i < kazoo_globals.num_worker_threads; i++) {
switch_threadattr_create(&thd_attr, ei_node->pool);
diff --git a/src/mod/event_handlers/mod_kazoo/kazoo_tweaks.c b/src/mod/event_handlers/mod_kazoo/kazoo_tweaks.c
new file mode 100644
index 0000000000..67f4d37a99
--- /dev/null
+++ b/src/mod/event_handlers/mod_kazoo/kazoo_tweaks.c
@@ -0,0 +1,741 @@
+/*
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005-2012, Anthony Minessale II
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ *
+ * The Initial Developer of the Original Code is
+ * Anthony Minessale II
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Luis Azedo
+ *
+ * mod_hacks.c -- hacks with state handlers
+ *
+ */
+#include "mod_kazoo.h"
+
+#define INTERACTION_VARIABLE "Call-Interaction-ID"
+#define BRIDGE_INTERCEPT_VARIABLE "Bridge-Intercepted"
+
+static char *TWEAK_NAMES[] = {
+ "interaction-id",
+ "export-vars",
+ "switch-uri",
+ "replaces-call-id",
+ "loopback-vars",
+ "caller-id",
+ "transfers",
+ "bridge",
+ "bridge-replaces-aleg",
+ "bridge-replaces-call-id",
+ "bridge-variables",
+ "restore-caller-id-on-blind-xfer"
+};
+
+static const char *bridge_variables[] = {
+ "Call-Control-Queue",
+ "Call-Control-PID",
+ "Call-Control-Node",
+ INTERACTION_VARIABLE,
+ "ecallmgr_Ecallmgr-Node",
+ "sip_h_k-cid",
+ "Switch-URI",
+ "Switch-URL",
+ NULL
+};
+
+static switch_status_t kz_tweaks_signal_bridge_on_hangup(switch_core_session_t *session)
+{
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ switch_event_t *my_event;
+
+ const char *peer_uuid = switch_channel_get_variable(channel, "Bridge-B-Unique-ID");
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "tweak signal bridge on hangup: %s , %s\n", switch_core_session_get_uuid(session), peer_uuid);
+
+
+ if (switch_event_create(&my_event, SWITCH_EVENT_CHANNEL_UNBRIDGE) == SWITCH_STATUS_SUCCESS) {
+ switch_event_add_header_string(my_event, SWITCH_STACK_BOTTOM, "Bridge-A-Unique-ID", switch_core_session_get_uuid(session));
+ switch_event_add_header_string(my_event, SWITCH_STACK_BOTTOM, "Bridge-B-Unique-ID", peer_uuid);
+ switch_channel_event_set_data(channel, my_event);
+ switch_event_fire(&my_event);
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static const switch_state_handler_table_t kz_tweaks_signal_bridge_state_handlers = {
+ /*.on_init */ NULL,
+ /*.on_routing */ NULL,
+ /*.on_execute */ NULL,
+ /*.on_hangup */ kz_tweaks_signal_bridge_on_hangup,
+ /*.on_exchange_media */ NULL,
+ /*.on_soft_execute */ NULL,
+ /*.on_consume_media */ NULL,
+ /*.on_hibernate */ NULL,
+ /*.on_reset */ NULL,
+ /*.on_park */ NULL,
+ /*.on_reporting */ NULL,
+ /*.on_destroy */ NULL
+};
+
+static void kz_tweaks_handle_bridge_variables(switch_event_t *event)
+{
+ switch_core_session_t *a_session = NULL, *b_session = NULL;
+ const char *a_leg = switch_event_get_header(event, "Bridge-A-Unique-ID");
+ const char *b_leg = switch_event_get_header(event, "Bridge-B-Unique-ID");
+ int i;
+
+ if (!kz_test_tweak(KZ_TWEAK_BRIDGE_VARIABLES)) return;
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "tweak bridge event handler: variables : %s , %s\n", a_leg, b_leg);
+
+
+ if (a_leg && (a_session = switch_core_session_force_locate(a_leg)) != NULL) {
+ switch_channel_t *a_channel = switch_core_session_get_channel(a_session);
+ if(switch_channel_get_variable_dup(a_channel, bridge_variables[0], SWITCH_FALSE, -1) == NULL) {
+ if(b_leg && (b_session = switch_core_session_force_locate(b_leg)) != NULL) {
+ switch_channel_t *b_channel = switch_core_session_get_channel(b_session);
+ for(i = 0; bridge_variables[i] != NULL; i++) {
+ const char *val = switch_channel_get_variable_dup(b_channel, bridge_variables[i], SWITCH_FALSE, -1);
+ switch_channel_set_variable(a_channel, bridge_variables[i], val);
+ }
+ switch_core_session_rwunlock(b_session);
+ }
+ } else {
+ if(b_leg && (b_session = switch_core_session_force_locate(b_leg)) != NULL) {
+ switch_channel_t *b_channel = switch_core_session_get_channel(b_session);
+ if(switch_channel_get_variable_dup(b_channel, bridge_variables[0], SWITCH_FALSE, -1) == NULL) {
+ for(i = 0; bridge_variables[i] != NULL; i++) {
+ const char *val = switch_channel_get_variable_dup(a_channel, bridge_variables[i], SWITCH_FALSE, -1);
+ switch_channel_set_variable(b_channel, bridge_variables[i], val);
+ }
+ }
+ switch_core_session_rwunlock(b_session);
+ }
+ }
+ switch_core_session_rwunlock(a_session);
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "NOT FOUND : %s\n", a_leg);
+ }
+
+}
+
+static void kz_tweaks_handle_bridge_intercepted(switch_event_t *event)
+{
+ switch_event_t *my_event;
+ switch_core_session_t *a_session = NULL;
+ switch_core_session_t *b_session = NULL;
+
+ const char *uuid = switch_event_get_header(event, "Unique-ID");
+ const char *a_leg = switch_event_get_header(event, "Bridge-A-Unique-ID");
+ const char *b_leg = switch_event_get_header(event, "Bridge-B-Unique-ID");
+ const char *bridge_intercepted = NULL;
+
+ if (!kz_test_tweak(KZ_TWEAK_BRIDGE_REPLACES_ALEG)) return;
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "tweak bridge event handler: intercepted : %s , %s, %s\n", uuid, a_leg, b_leg);
+
+
+ if ((a_session = switch_core_session_locate(a_leg)) != NULL) {
+ switch_channel_t *a_channel = switch_core_session_get_channel(a_session);
+ bridge_intercepted = switch_channel_get_variable_dup(a_channel, BRIDGE_INTERCEPT_VARIABLE, SWITCH_TRUE, -1);
+ switch_channel_set_variable(a_channel, BRIDGE_INTERCEPT_VARIABLE, NULL);
+ if (bridge_intercepted && switch_true(bridge_intercepted)) {
+ switch_channel_set_variable(a_channel, "Bridge-B-Unique-ID", b_leg);
+ switch_channel_add_state_handler(a_channel, &kz_tweaks_signal_bridge_state_handlers);
+
+ if ((b_session = switch_core_session_locate(b_leg)) != NULL) {
+ switch_channel_t *b_channel = switch_core_session_get_channel(b_session);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "creating channel_bridge event A - %s , B - %s\n", switch_core_session_get_uuid(b_session), uuid);
+ if (switch_event_create(&my_event, SWITCH_EVENT_CHANNEL_BRIDGE) == SWITCH_STATUS_SUCCESS) {
+ switch_event_add_header_string(my_event, SWITCH_STACK_BOTTOM, "Bridge-A-Unique-ID", switch_core_session_get_uuid(b_session));
+ switch_event_add_header_string(my_event, SWITCH_STACK_BOTTOM, "Bridge-B-Unique-ID", uuid);
+ switch_channel_event_set_data(b_channel, my_event);
+ switch_event_fire(&my_event);
+ }
+ switch_core_session_rwunlock(b_session);
+ }
+ }
+ switch_core_session_rwunlock(a_session);
+ }
+ switch_safe_strdup(bridge_intercepted);
+}
+
+static void kz_tweaks_channel_bridge_event_handler(switch_event_t *event)
+{
+ const char *uuid = switch_event_get_header(event, "Unique-ID");
+
+ if (!kz_test_tweak(KZ_TWEAK_BRIDGE)) return;
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "tweak bridge event handler: %s\n", uuid);
+
+ kz_tweaks_handle_bridge_intercepted(event);
+ kz_tweaks_handle_bridge_variables(event);
+}
+
+// TRANSFERS
+
+static void kz_tweaks_channel_replaced_event_handler(switch_event_t *event)
+{
+ const char *uuid = switch_event_get_header(event, "Unique-ID");
+ const char *replaced_by = switch_event_get_header(event, "att_xfer_replaced_by");
+
+ if (!kz_test_tweak(KZ_TWEAK_TRANSFERS)) return;
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "REPLACED : %s , %s\n", uuid, replaced_by);
+}
+
+static void kz_tweaks_channel_intercepted_event_handler(switch_event_t *event)
+{
+ switch_core_session_t *uuid_session = NULL;
+ const char *uuid = switch_event_get_header(event, "Unique-ID");
+ const char *peer_uuid = switch_event_get_header(event, "intercepted_by");
+
+ if (!kz_test_tweak(KZ_TWEAK_TRANSFERS)) return;
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "tweak intercepted handler : %s was intercepted by %s\n", uuid, peer_uuid);
+
+ if ((uuid_session = switch_core_session_force_locate(peer_uuid)) != NULL) {
+ switch_channel_t *uuid_channel = switch_core_session_get_channel(uuid_session);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "marking %s for channel_bridge handling\n", peer_uuid);
+ switch_channel_set_variable(uuid_channel, BRIDGE_INTERCEPT_VARIABLE, "true");
+ switch_core_session_rwunlock(uuid_session);
+ }
+
+}
+
+static void kz_tweaks_channel_transferor_event_handler(switch_event_t *event)
+{
+ switch_core_session_t *uuid_session = NULL;
+ switch_event_t *evt = NULL;
+ const char *uuid = switch_event_get_header(event, "Unique-ID");
+
+ const char *orig_call_id = switch_event_get_header(event, "att_xfer_original_call_id");
+ const char *dest_peer_uuid = switch_event_get_header(event, "att_xfer_destination_peer_uuid");
+ const char *dest_call_id = switch_event_get_header(event, "att_xfer_destination_call_id");
+
+ const char *file = switch_event_get_header(event, "Event-Calling-File");
+ const char *func = switch_event_get_header(event, "Event-Calling-Function");
+ const char *line = switch_event_get_header(event, "Event-Calling-Line-Number");
+
+ if (!kz_test_tweak(KZ_TWEAK_TRANSFERS)) return;
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "TRANSFEROR : %s , %s , %s, %s, %s , %s , %s \n", uuid, orig_call_id, dest_peer_uuid, dest_call_id, file, func, line);
+ if ((uuid_session = switch_core_session_force_locate(uuid)) != NULL) {
+ switch_channel_t *uuid_channel = switch_core_session_get_channel(uuid_session);
+ const char* interaction_id = switch_channel_get_variable_dup(uuid_channel, INTERACTION_VARIABLE, SWITCH_TRUE, -1);
+ // set to uuid & peer_uuid
+ if(interaction_id != NULL) {
+ switch_core_session_t *session = NULL;
+ if(dest_call_id && (session = switch_core_session_force_locate(dest_call_id)) != NULL) {
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ const char* prv_interaction_id = switch_channel_get_variable_dup(channel, INTERACTION_VARIABLE, SWITCH_TRUE, -1);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "LOCATING UUID PRV : %s : %s\n", prv_interaction_id, interaction_id);
+ switch_channel_set_variable(channel, INTERACTION_VARIABLE, interaction_id);
+ if (switch_event_create(&evt, SWITCH_EVENT_CHANNEL_DATA) == SWITCH_STATUS_SUCCESS) {
+ switch_channel_event_set_data(channel, evt);
+ switch_event_fire(&evt);
+ }
+ switch_core_session_rwunlock(session);
+ switch_safe_strdup(prv_interaction_id);
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "TRANSFEROR NO UUID SESSION: %s , %s , %s \n", uuid, dest_call_id, dest_peer_uuid);
+ }
+ if(dest_peer_uuid && (session = switch_core_session_force_locate(dest_peer_uuid)) != NULL) {
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ const char* prv_interaction_id = switch_channel_get_variable_dup(channel, INTERACTION_VARIABLE, SWITCH_TRUE, -1);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "LOCATING PEER UUID PRV : %s : %s\n", prv_interaction_id, interaction_id);
+ switch_channel_set_variable(channel, INTERACTION_VARIABLE, interaction_id);
+ if (switch_event_create(&evt, SWITCH_EVENT_CHANNEL_DATA) == SWITCH_STATUS_SUCCESS) {
+ switch_channel_event_set_data(channel, evt);
+ switch_event_fire(&evt);
+ }
+ switch_core_session_rwunlock(session);
+ switch_safe_strdup(prv_interaction_id);
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "TRANSFEROR NO PEER SESSION: %s , %s , %s \n", uuid, dest_call_id, dest_peer_uuid);
+ }
+ if(orig_call_id && (session = switch_core_session_force_locate(orig_call_id)) != NULL) {
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ const char* prv_interaction_id = switch_channel_get_variable_dup(channel, INTERACTION_VARIABLE, SWITCH_TRUE, -1);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "LOCATING PEER UUID PRV : %s : %s\n", prv_interaction_id, interaction_id);
+ switch_channel_set_variable(channel, INTERACTION_VARIABLE, interaction_id);
+ if (switch_event_create(&evt, SWITCH_EVENT_CHANNEL_DATA) == SWITCH_STATUS_SUCCESS) {
+ switch_channel_event_set_data(channel, evt);
+ switch_event_fire(&evt);
+ }
+ switch_core_session_rwunlock(session);
+ switch_safe_strdup(prv_interaction_id);
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "TRANSFEROR NO PEER SESSION: %s , %s , %s \n", uuid, dest_call_id, dest_peer_uuid);
+ }
+ switch_safe_strdup(interaction_id);
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "TRANSFEROR ID = NULL : %s , %s , %s \n", uuid, dest_call_id, dest_peer_uuid);
+ }
+ switch_core_session_rwunlock(uuid_session);
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SESSION NOT FOUND : %s\n", uuid);
+ }
+}
+
+static void kz_tweaks_channel_transferee_event_handler(switch_event_t *event)
+{
+ const char *uuid = switch_event_get_header(event, "Unique-ID");
+ const char *replaced_by_uuid = switch_event_get_header(event, "att_xfer_replaced_call_id");
+
+ if (!kz_test_tweak(KZ_TWEAK_TRANSFERS)) return;
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "TRANSFEREE : %s replaced by %s\n", uuid, replaced_by_uuid);
+}
+
+// END TRANSFERS
+
+
+static switch_status_t kz_tweaks_handle_loopback(switch_core_session_t *session)
+{
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ switch_channel_t *a_channel = NULL;
+ const char * loopback_leg = NULL;
+ const char * loopback_aleg = NULL;
+ switch_core_session_t *a_session = NULL;
+ switch_event_t *event = NULL;
+ switch_event_header_t *header = NULL;
+ switch_event_t *to_add = NULL;
+ switch_event_t *to_remove = NULL;
+ switch_caller_profile_t *caller;
+ int n = 0;
+
+ if (!kz_test_tweak(KZ_TWEAK_LOOPBACK_VARS)) {
+ return SWITCH_STATUS_SUCCESS;
+ }
+
+ caller = switch_channel_get_caller_profile(channel);
+ if(strncmp(caller->source, "mod_loopback", 12))
+ return SWITCH_STATUS_SUCCESS;
+
+ if((loopback_leg = switch_channel_get_variable(channel, "loopback_leg")) == NULL)
+ return SWITCH_STATUS_SUCCESS;
+
+ if(strncmp(loopback_leg, "B", 1))
+ return SWITCH_STATUS_SUCCESS;
+
+ switch_channel_get_variables(channel, &event);
+ switch_event_create_plain(&to_add, SWITCH_EVENT_CHANNEL_DATA);
+ switch_event_create_plain(&to_remove, SWITCH_EVENT_CHANNEL_DATA);
+
+ for(header = event->headers; header; header = header->next) {
+ if(!strncmp(header->name, "Export-Loopback-", 16)) {
+ kz_switch_event_add_variable_name_printf(to_add, SWITCH_STACK_BOTTOM, header->value, "%s", header->name+16);
+ switch_channel_set_variable(channel, header->name, NULL);
+ n++;
+ } else if(!strncmp(header->name, "sip_loopback_", 13)) {
+ kz_switch_event_add_variable_name_printf(to_add, SWITCH_STACK_BOTTOM, header->value, "sip_%s", header->name+13);
+ } else if(!strncmp(header->name, "ecallmgr_", 9)) {
+ switch_event_add_header_string(to_remove, SWITCH_STACK_BOTTOM, header->name, header->value);
+ }
+ }
+ if(n) {
+ for(header = to_remove->headers; header; header = header->next) {
+ switch_channel_set_variable(channel, header->name, NULL);
+ }
+ }
+
+ for(header = to_add->headers; header; header = header->next) {
+ switch_channel_set_variable(channel, header->name, header->value);
+ }
+
+ // cleanup leg A
+ loopback_aleg = switch_channel_get_variable(channel, "other_loopback_leg_uuid");
+ if(loopback_aleg != NULL) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "found loopback a-leg uuid - %s\n", loopback_aleg);
+ if ((a_session = switch_core_session_locate(loopback_aleg))) {
+ a_channel = switch_core_session_get_channel(a_session);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "found loopback session a - %s\n", loopback_aleg);
+ switch_channel_del_variable_prefix(a_channel, "Export-Loopback-");
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Couldn't locate loopback session a - %s\n", loopback_aleg);
+ }
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Couldn't find loopback a-leg uuid!\n");
+ }
+
+ /*
+ * set Interaction-ID
+ * if we're not crossing account boundaries
+ */
+ if (kz_test_tweak(KZ_TWEAK_INTERACTION_ID)) {
+ if (a_channel) {
+ const char *interaction_id = switch_channel_get_variable_dup(a_channel, INTERACTION_VARIABLE, SWITCH_FALSE, -1);
+ const char *a_account_id = switch_channel_get_variable_dup(a_channel, "ecallmgr_Account-ID", SWITCH_FALSE, -1);
+ const char *b_account_id = switch_channel_get_variable_dup(channel, "ecallmgr_Account-ID", SWITCH_FALSE, -1);
+ if ((!a_account_id) || (!b_account_id) || (!strcmp(a_account_id, b_account_id))) {
+ switch_channel_set_variable(channel, INTERACTION_VARIABLE, interaction_id);
+ }
+ }
+ }
+
+ if (a_session){
+ switch_core_session_rwunlock(a_session);
+ }
+ switch_event_destroy(&event);
+ switch_event_destroy(&to_add);
+ switch_event_destroy(&to_remove);
+
+ return SWITCH_STATUS_SUCCESS;
+
+}
+
+static void kz_tweaks_handle_caller_id(switch_core_session_t *session)
+{
+ if (kz_test_tweak(KZ_TWEAK_CALLER_ID)) {
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ switch_caller_profile_t* caller = switch_channel_get_caller_profile(channel);
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "CHECKING CALLER-ID\n");
+ if (caller && switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
+ const char* val = NULL;
+ if((val=switch_caller_get_field_by_name(caller, "Endpoint-Caller-ID-Name"))) {
+ caller->caller_id_name = val;
+ caller->orig_caller_id_name = val;
+ }
+ if((val=switch_caller_get_field_by_name(caller, "Endpoint-Caller-ID-Number"))) {
+ caller->caller_id_number = val;
+ caller->orig_caller_id_number = val;
+ }
+ }
+ }
+}
+
+/*
+static switch_status_t kz_tweaks_handle_auth_token(switch_core_session_t *session)
+{
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ switch_event_t *event;
+ const char *token = switch_channel_get_variable(channel, "sip_h_X-FS-Auth-Token");
+ if(token) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Authenticating user for nightmare xfer %s\n", token);
+ if (switch_ivr_set_user(session, token) == SWITCH_STATUS_SUCCESS) {
+ if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_DATA) == SWITCH_STATUS_SUCCESS) {
+ switch_channel_event_set_data(channel, event);
+ switch_event_fire(&event);
+ }
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Authenticated user from nightmare xfer %s\n", token);
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Error Authenticating user for nightmare xfer %s\n", token);
+ }
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+
+}
+*/
+
+static switch_status_t kz_tweaks_handle_nightmare_xfer_interaction_id(switch_core_session_t *session)
+{
+ if (kz_test_tweak(KZ_TWEAK_INTERACTION_ID)) {
+ switch_core_session_t *replace_session = NULL;
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ const char *replaced_call_id = switch_channel_get_variable(channel, "sip_replaces_call_id");
+ const char *core_uuid = switch_channel_get_variable(channel, "sip_h_X-FS-From-Core-UUID");
+ const char *partner_uuid = switch_channel_get_variable(channel, "sip_h_X-FS-Refer-Partner-UUID");
+ const char *interaction_id = switch_channel_get_variable(channel, "sip_h_X-FS-Call-Interaction-ID");
+ if(core_uuid && partner_uuid && replaced_call_id && interaction_id) {
+ switch_channel_set_variable(channel, INTERACTION_VARIABLE, interaction_id);
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "checking nightmare xfer tweak for %s\n", switch_channel_get_uuid(channel));
+ if ((replace_session = switch_core_session_locate(replaced_call_id))) {
+ switch_channel_t *replaced_call_channel = switch_core_session_get_channel(replace_session);
+ switch_channel_set_variable(replaced_call_channel, INTERACTION_VARIABLE, interaction_id);
+ switch_core_session_rwunlock(replace_session);
+ }
+ if ((replace_session = switch_core_session_locate(partner_uuid))) {
+ switch_channel_t *replaced_call_channel = switch_core_session_get_channel(replace_session);
+ switch_channel_set_variable(replaced_call_channel, INTERACTION_VARIABLE, interaction_id);
+ switch_core_session_rwunlock(replace_session);
+ }
+ }
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+
+}
+
+static switch_status_t kz_tweaks_handle_replaces_call_id(switch_core_session_t *session)
+{
+ if (kz_test_tweak(KZ_TWEAK_REPLACES_CALL_ID)) {
+ switch_core_session_t *replace_call_session = NULL;
+ switch_event_t *event;
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ const char *replaced_call_id = switch_channel_get_variable(channel, "sip_replaces_call_id");
+ const char *core_uuid = switch_channel_get_variable(channel, "sip_h_X-FS-From-Core-UUID");
+ if((!core_uuid) && replaced_call_id) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "checking replaces header tweak for %s\n", replaced_call_id);
+ if ((replace_call_session = switch_core_session_locate(replaced_call_id))) {
+ switch_channel_t *replaced_call_channel = switch_core_session_get_channel(replace_call_session);
+ int i;
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "setting bridge variables from %s to %s\n", replaced_call_id, switch_channel_get_uuid(channel));
+ for(i = 0; bridge_variables[i] != NULL; i++) {
+ const char *val = switch_channel_get_variable_dup(replaced_call_channel, bridge_variables[i], SWITCH_TRUE, -1);
+ switch_channel_set_variable(channel, bridge_variables[i], val);
+ switch_safe_strdup(val);
+ }
+ if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_DATA) == SWITCH_STATUS_SUCCESS) {
+ switch_channel_event_set_data(channel, event);
+ switch_event_fire(&event);
+ }
+ switch_core_session_rwunlock(replace_call_session);
+ }
+ }
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+
+}
+
+
+static switch_status_t kz_tweaks_handle_switch_uri(switch_core_session_t *session)
+{
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ if (kz_test_tweak(KZ_TWEAK_SWITCH_URI)) {
+ const char *profile_url = switch_channel_get_variable(channel, "sofia_profile_url");
+ if(profile_url) {
+ int n = strcspn(profile_url, "@");
+ switch_channel_set_variable(channel, "Switch-URL", profile_url);
+ switch_channel_set_variable_printf(channel, "Switch-URI", "sip:%s", n > 0 ? profile_url + n + 1 : profile_url);
+ }
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+
+}
+
+static void kz_tweaks_handle_interaction_id(switch_core_session_t *session)
+{
+ const char *expr = "${expr(ceil((${Event-Date-Timestamp} / 1000000) + $${UNIX_EPOCH_IN_GREGORIAN}))}-${regex(${create_uuid()}|^([^-]*)|%1)}";
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ char * val = NULL;
+ switch_core_session_t *peer_session = NULL;
+ const char* peer_interaction_id = NULL;
+
+ if (kz_test_tweak(KZ_TWEAK_INTERACTION_ID)) {
+ val = kz_expand(expr);
+ if (val) {
+ switch_channel_set_variable(channel, "Original-"INTERACTION_VARIABLE, val);
+ if(switch_core_session_get_partner(session, &peer_session) == SWITCH_STATUS_SUCCESS) {
+ switch_channel_t *peer_channel = switch_core_session_get_channel(peer_session);
+ peer_interaction_id = switch_channel_get_variable_dup(peer_channel, INTERACTION_VARIABLE, SWITCH_FALSE, -1);
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "PEER_SESSION => %s\n", peer_interaction_id);
+ if(peer_interaction_id) {
+ switch_channel_set_variable(channel, INTERACTION_VARIABLE, peer_interaction_id);
+ }
+ switch_core_session_rwunlock(peer_session);
+ } else if (!switch_channel_get_variable_dup(channel, INTERACTION_VARIABLE, SWITCH_FALSE, -1)) {
+ switch_channel_set_variable(channel, INTERACTION_VARIABLE, val);
+ }
+ }
+
+ switch_safe_free(val);
+ }
+
+}
+
+static switch_status_t kz_outgoing_channel(switch_core_session_t * session, switch_event_t * event, switch_caller_profile_t * cp, switch_core_session_t * peer_session, switch_originate_flag_t flag)
+{
+ if (kz_test_tweak(KZ_TWEAK_INTERACTION_ID)) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "GOT OUTGOING\n");
+ if (peer_session) {
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ const char* interaction_id = switch_channel_get_variable_dup(channel, INTERACTION_VARIABLE, SWITCH_FALSE, -1);
+ switch_channel_t *peer_channel = switch_core_session_get_channel(peer_session);
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "SESSION && PEER_SESSION => %s\n", interaction_id );
+ if (interaction_id) {
+ switch_channel_set_variable(peer_channel, INTERACTION_VARIABLE, interaction_id);
+ }
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "NO SESSION && PEER_SESSION\n");
+ }
+ }
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t kz_tweaks_register_handle_blind_xfer(switch_core_session_t *session)
+{
+ if (kz_test_tweak(KZ_TWEAK_RESTORE_CALLER_ID_ON_BLIND_XFER)) {
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ switch_channel_set_variable(channel, "execute_on_blind_transfer", "kz_restore_caller_id");
+ }
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t kz_tweaks_set_export_vars(switch_core_session_t *session)
+{
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ const char *exports;
+ char *var, *new_exports, *new_exports_d = NULL;
+
+ if (kz_test_tweak(KZ_TWEAK_EXPORT_VARS)) {
+ exports = switch_channel_get_variable(channel, SWITCH_EXPORT_VARS_VARIABLE);
+ var = switch_core_session_strdup(session, "Switch-URI,Switch-URL");
+
+ if (exports) {
+ new_exports_d = switch_mprintf("%s,%s", exports, var);
+ new_exports = new_exports_d;
+ } else {
+ new_exports = var;
+ }
+
+ switch_channel_set_variable(channel, SWITCH_EXPORT_VARS_VARIABLE, new_exports);
+
+ switch_safe_free(new_exports_d);
+ }
+
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t kz_tweaks_on_init(switch_core_session_t *session)
+{
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "checking tweaks for %s\n", switch_channel_get_uuid(channel));
+ switch_channel_set_flag(channel, CF_VERBOSE_EVENTS);
+ switch_core_event_hook_add_outgoing_channel(session, kz_outgoing_channel);
+ kz_tweaks_handle_interaction_id(session);
+ kz_tweaks_handle_switch_uri(session);
+ kz_tweaks_handle_caller_id(session);
+// kz_tweaks_handle_auth_token(session);
+ kz_tweaks_handle_nightmare_xfer_interaction_id(session);
+ kz_tweaks_handle_replaces_call_id(session);
+ kz_tweaks_handle_loopback(session);
+ kz_tweaks_register_handle_blind_xfer(session);
+ kz_tweaks_set_export_vars(session);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_state_handler_table_t kz_tweaks_state_handlers = {
+ /*.on_init */ kz_tweaks_on_init,
+ /*.on_routing */ NULL,
+ /*.on_execute */ NULL,
+ /*.on_hangup */ NULL,
+ /*.on_exchange_media */ NULL,
+ /*.on_soft_execute */ NULL,
+ /*.on_consume_media */ NULL,
+ /*.on_hibernate */ NULL,
+ /*.on_reset */ NULL,
+ /*.on_park */ NULL,
+ /*.on_reporting */ NULL,
+ /*.on_destroy */ NULL
+};
+
+
+static void kz_tweaks_register_state_handlers()
+{
+/*
+ * we may need two handlers
+ * one with SSH_FLAG_PRE_EXEC
+ * and another without it
+ * mod_loopback tweaks needs post-init (SSH_FLAG_PRE_EXEC off)
+ *
+ * kz_tweaks_state_handlers.flags = SSH_FLAG_PRE_EXEC;
+ *
+ */
+ switch_core_add_state_handler(&kz_tweaks_state_handlers);
+}
+
+static void kz_tweaks_unregister_state_handlers()
+{
+ switch_core_remove_state_handler(&kz_tweaks_state_handlers);
+}
+
+static void kz_tweaks_bind_events()
+{
+ if (switch_event_bind("kz_tweaks", SWITCH_EVENT_CHANNEL_BRIDGE, SWITCH_EVENT_SUBCLASS_ANY, kz_tweaks_channel_bridge_event_handler, NULL) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind to channel_bridge event!\n");
+ }
+ if (switch_event_bind("kz_tweaks", SWITCH_EVENT_CUSTOM, "sofia::replaced", kz_tweaks_channel_replaced_event_handler, NULL) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind to channel_bridge event!\n");
+ }
+ if (switch_event_bind("kz_tweaks", SWITCH_EVENT_CUSTOM, "sofia::intercepted", kz_tweaks_channel_intercepted_event_handler, NULL) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind to channel_bridge event!\n");
+ }
+ if (switch_event_bind("kz_tweaks", SWITCH_EVENT_CUSTOM, "sofia::transferor", kz_tweaks_channel_transferor_event_handler, NULL) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind to channel_bridge event!\n");
+ }
+ if (switch_event_bind("kz_tweaks", SWITCH_EVENT_CUSTOM, "sofia::transferee", kz_tweaks_channel_transferee_event_handler, NULL) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind to channel_bridge event!\n");
+ }
+}
+
+static void kz_tweaks_unbind_events()
+{
+ switch_event_unbind_callback(kz_tweaks_channel_bridge_event_handler);
+ switch_event_unbind_callback(kz_tweaks_channel_replaced_event_handler);
+ switch_event_unbind_callback(kz_tweaks_channel_intercepted_event_handler);
+ switch_event_unbind_callback(kz_tweaks_channel_transferor_event_handler);
+ switch_event_unbind_callback(kz_tweaks_channel_transferee_event_handler);
+}
+
+void kz_tweaks_add_core_variables()
+{
+ switch_core_set_variable("UNIX_EPOCH_IN_GREGORIAN", "62167219200");
+}
+
+void kz_tweaks_start()
+{
+ kz_tweaks_add_core_variables();
+ kz_tweaks_register_state_handlers();
+ kz_tweaks_bind_events();
+}
+
+void kz_tweaks_stop()
+{
+ kz_tweaks_unbind_events();
+ kz_tweaks_unregister_state_handlers();
+}
+
+SWITCH_DECLARE(const char *) kz_tweak_name(kz_tweak_t tweak)
+{
+ return TWEAK_NAMES[tweak];
+}
+
+SWITCH_DECLARE(switch_status_t) kz_name_tweak(const char *name, kz_tweak_t *type)
+{
+ kz_tweak_t x;
+ for (x = 0; x < KZ_TWEAK_MAX; x++) {
+ if (!strcasecmp(name, TWEAK_NAMES[x])) {
+ *type = x;
+ return SWITCH_STATUS_SUCCESS;
+ }
+ }
+
+ return SWITCH_STATUS_FALSE;
+}
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4:
+ */
+
+
diff --git a/src/mod/event_handlers/mod_kazoo/kazoo_utils.c b/src/mod/event_handlers/mod_kazoo/kazoo_utils.c
index 024e98b858..f4050bb34a 100644
--- a/src/mod/event_handlers/mod_kazoo/kazoo_utils.c
+++ b/src/mod/event_handlers/mod_kazoo/kazoo_utils.c
@@ -34,663 +34,603 @@
*/
#include "mod_kazoo.h"
-/* Stolen from code added to ei in R12B-5.
- * Since not everyone has this version yet;
- * provide our own version.
- * */
+#define kz_resize(l) {\
+char *dp;\
+olen += (len + l + block);\
+cpos = c - data;\
+if ((dp = realloc(data, olen))) {\
+ data = dp;\
+ c = data + cpos;\
+ memset(c, 0, olen - cpos);\
+ }} \
-#define put8(s,n) do { \
- (s)[0] = (char)((n) & 0xff); \
- (s) += 1; \
- } while (0)
-#define put32be(s,n) do { \
- (s)[0] = ((n) >> 24) & 0xff; \
- (s)[1] = ((n) >> 16) & 0xff; \
- (s)[2] = ((n) >> 8) & 0xff; \
- (s)[3] = (n) & 0xff; \
- (s) += 4; \
- } while (0)
+void kz_check_set_profile_var(switch_channel_t *channel, char* var, char *val)
+{
+ int idx = 0;
+ while(kazoo_globals.profile_vars_prefixes[idx] != NULL) {
+ char *prefix = kazoo_globals.profile_vars_prefixes[idx];
+ if (!strncasecmp(var, prefix, strlen(prefix))) {
+ switch_channel_set_profile_var(channel, var + strlen(prefix), val);
-#ifdef EI_DEBUG
-static void ei_x_print_reg_msg(ei_x_buff *buf, char *dest, int send) {
- char *mbuf = NULL;
- int i = 1;
-
- ei_s_print_term(&mbuf, buf->buff, &i);
-
- if (send) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Encoded term %s to '%s'\n", mbuf, dest);
- } else {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Decoded term %s for '%s'\n", mbuf, dest);
- }
-
- free(mbuf);
-}
-
-static void ei_x_print_msg(ei_x_buff *buf, erlang_pid *pid, int send) {
- char *pbuf = NULL;
- int i = 0;
- ei_x_buff pidbuf;
-
- ei_x_new(&pidbuf);
- ei_x_encode_pid(&pidbuf, pid);
-
- ei_s_print_term(&pbuf, pidbuf.buff, &i);
-
- ei_x_print_reg_msg(buf, pbuf, send);
- free(pbuf);
-}
-#endif
-
-void ei_encode_switch_event_headers(ei_x_buff *ebuf, switch_event_t *event) {
- ei_encode_switch_event_headers_2(ebuf, event, 1);
-}
-
-void ei_encode_switch_event_headers_2(ei_x_buff *ebuf, switch_event_t *event, int encode) {
- switch_event_header_t *hp;
- char *uuid = switch_event_get_header(event, "unique-id");
- int i;
-
- for (i = 0, hp = event->headers; hp; hp = hp->next, i++);
-
- if (event->body)
- i++;
-
- ei_x_encode_list_header(ebuf, i + 1);
-
- if (uuid) {
- char *unique_id = switch_event_get_header(event, "unique-id");
- ei_x_encode_binary(ebuf, unique_id, strlen(unique_id));
- } else {
- ei_x_encode_atom(ebuf, "undefined");
- }
-
- for (hp = event->headers; hp; hp = hp->next) {
- ei_x_encode_tuple_header(ebuf, 2);
- ei_x_encode_binary(ebuf, hp->name, strlen(hp->name));
- if(encode)
- switch_url_decode(hp->value);
- ei_x_encode_binary(ebuf, hp->value, strlen(hp->value));
- }
-
- if (event->body) {
- ei_x_encode_tuple_header(ebuf, 2);
- ei_x_encode_binary(ebuf, "body", strlen("body"));
- ei_x_encode_binary(ebuf, event->body, strlen(event->body));
- }
-
- ei_x_encode_empty_list(ebuf);
-}
-
-void close_socket(switch_socket_t ** sock) {
- if (*sock) {
- switch_socket_shutdown(*sock, SWITCH_SHUTDOWN_READWRITE);
- switch_socket_close(*sock);
- *sock = NULL;
+ }
+ idx++;
}
}
-void close_socketfd(int *sockfd) {
- if (*sockfd) {
- shutdown(*sockfd, SHUT_RDWR);
- close(*sockfd);
+SWITCH_DECLARE(switch_status_t) kz_switch_core_merge_variables(switch_event_t *event)
+{
+ switch_event_t *global_vars;
+ switch_status_t status = switch_core_get_variables(&global_vars);
+ if(status == SWITCH_STATUS_SUCCESS) {
+ switch_event_merge(event, global_vars);
+ switch_event_destroy(&global_vars);
}
+ return status;
}
-switch_socket_t *create_socket_with_port(switch_memory_pool_t *pool, switch_port_t port) {
- switch_sockaddr_t *sa;
- switch_socket_t *socket;
+SWITCH_DECLARE(switch_status_t) kz_switch_core_base_headers_for_expand(switch_event_t **event)
+{
+ switch_status_t status = SWITCH_STATUS_GENERR;
+ *event = NULL;
+ if(switch_event_create(event, SWITCH_EVENT_GENERAL) == SWITCH_STATUS_SUCCESS) {
+ status = kz_switch_core_merge_variables(*event);
+ }
+ return status;
+}
- if(switch_sockaddr_info_get(&sa, kazoo_globals.ip, SWITCH_UNSPEC, port, 0, pool)) {
+SWITCH_DECLARE(switch_status_t) kz_expand_api_execute(const char *cmd, const char *arg, switch_core_session_t *session, switch_stream_handle_t *stream)
+{
+ switch_api_interface_t *api;
+ switch_status_t status;
+ char *arg_used;
+ char *cmd_used;
+
+ switch_assert(stream != NULL);
+ switch_assert(stream->data != NULL);
+ switch_assert(stream->write_function != NULL);
+
+ if (strcasecmp(cmd, "console_complete")) {
+ cmd_used = switch_strip_whitespace(cmd);
+ arg_used = switch_strip_whitespace(arg);
+ } else {
+ cmd_used = (char *) cmd;
+ arg_used = (char *) arg;
+ }
+
+ if (cmd_used && (api = switch_loadable_module_get_api_interface(cmd_used)) != 0) {
+ if ((status = api->function(arg_used, session, stream)) != SWITCH_STATUS_SUCCESS) {
+ stream->write_function(stream, "COMMAND RETURNED ERROR!\n");
+ }
+ UNPROTECT_INTERFACE(api);
+ } else {
+ status = SWITCH_STATUS_FALSE;
+ stream->write_function(stream, "INVALID COMMAND!\n");
+ }
+
+ if (cmd_used != cmd) {
+ switch_safe_free(cmd_used);
+ }
+
+ if (arg_used != arg) {
+ switch_safe_free(arg_used);
+ }
+
+ return status;
+}
+
+
+SWITCH_DECLARE(char *) kz_event_expand_headers_check(switch_event_t *event, const char *in, switch_event_t *var_list, switch_event_t *api_list, uint32_t recur)
+{
+ char *p, *c = NULL;
+ char *data, *indup, *endof_indup;
+ size_t sp = 0, len = 0, olen = 0, vtype = 0, br = 0, cpos, block = 128;
+ const char *sub_val = NULL;
+ char *cloned_sub_val = NULL, *expanded_sub_val = NULL;
+ char *func_val = NULL;
+ int nv = 0;
+ char *gvar = NULL, *sb = NULL;
+
+ if (recur > 100) {
+ return (char *) in;
+ }
+
+ if (zstr(in)) {
+ return (char *) in;
+ }
+
+ nv = switch_string_var_check_const(in) || switch_string_has_escaped_data(in);
+
+ if (!nv) {
+ return (char *) in;
+ }
+
+ nv = 0;
+ olen = strlen(in) + 1;
+ indup = strdup(in);
+ endof_indup = end_of_p(indup) + 1;
+
+ if ((data = malloc(olen))) {
+ memset(data, 0, olen);
+ c = data;
+ for (p = indup; p && p < endof_indup && *p; p++) {
+ int global = 0;
+ vtype = 0;
+
+ if (*p == '\\') {
+ if (*(p + 1) == '$') {
+ nv = 1;
+ p++;
+ if (*(p + 1) == '$') {
+ p++;
+ }
+ } else if (*(p + 1) == '\'') {
+ p++;
+ continue;
+ } else if (*(p + 1) == '\\') {
+ if (len + 1 >= olen) {
+ kz_resize(1);
+ }
+
+ *c++ = *p++;
+ len++;
+ continue;
+ }
+ }
+
+ if (*p == '$' && !nv) {
+ if (*(p + 1) == '$') {
+ p++;
+ global++;
+ }
+
+ if (*(p + 1)) {
+ if (*(p + 1) == '{') {
+ vtype = global ? 3 : 1;
+ } else {
+ nv = 1;
+ }
+ } else {
+ nv = 1;
+ }
+ }
+
+ if (nv) {
+ if (len + 1 >= olen) {
+ kz_resize(1);
+ }
+
+ *c++ = *p;
+ len++;
+ nv = 0;
+ continue;
+ }
+
+ if (vtype) {
+ char *s = p, *e, *vname, *vval = NULL;
+ size_t nlen;
+
+ s++;
+
+ if ((vtype == 1 || vtype == 3) && *s == '{') {
+ br = 1;
+ s++;
+ }
+
+ e = s;
+ vname = s;
+ while (*e) {
+ if (br == 1 && *e == '}') {
+ br = 0;
+ *e++ = '\0';
+ break;
+ }
+
+ if (br > 0) {
+ if (e != s && *e == '{') {
+ br++;
+ } else if (br > 1 && *e == '}') {
+ br--;
+ }
+ }
+
+ e++;
+ }
+ p = e > endof_indup ? endof_indup : e;
+
+ vval = NULL;
+ for(sb = vname; sb && *sb; sb++) {
+ if (*sb == ' ') {
+ vval = sb;
+ break;
+ } else if (*sb == '(') {
+ vval = sb;
+ br = 1;
+ break;
+ }
+ }
+
+ if (vval) {
+ e = vval - 1;
+ *vval++ = '\0';
+
+ while (*e == ' ') {
+ *e-- = '\0';
+ }
+ e = vval;
+
+ while (e && *e) {
+ if (*e == '(') {
+ br++;
+ } else if (br > 1 && *e == ')') {
+ br--;
+ } else if (br == 1 && *e == ')') {
+ *e = '\0';
+ break;
+ }
+ e++;
+ }
+
+ vtype = 2;
+ }
+
+ if (vtype == 1 || vtype == 3) {
+ char *expanded = NULL;
+ int offset = 0;
+ int ooffset = 0;
+ char *ptr;
+ int idx = -1;
+
+ if ((expanded = kz_event_expand_headers_check(event, (char *) vname, var_list, api_list, recur+1)) == vname) {
+ expanded = NULL;
+ } else {
+ vname = expanded;
+ }
+ if ((ptr = strchr(vname, ':'))) {
+ *ptr++ = '\0';
+ offset = atoi(ptr);
+ if ((ptr = strchr(ptr, ':'))) {
+ ptr++;
+ ooffset = atoi(ptr);
+ }
+ }
+
+ if ((ptr = strchr(vname, '[')) && strchr(ptr, ']')) {
+ *ptr++ = '\0';
+ idx = atoi(ptr);
+ }
+
+ if (vtype == 3 || !(sub_val = switch_event_get_header_idx(event, vname, idx))) {
+ switch_safe_free(gvar);
+ if ((gvar = switch_core_get_variable_dup(vname))) {
+ sub_val = gvar;
+ }
+
+ if (var_list && !switch_event_check_permission_list(var_list, vname)) {
+ sub_val = "";
+ }
+
+
+ if ((expanded_sub_val = kz_event_expand_headers_check(event, sub_val, var_list, api_list, recur+1)) == sub_val) {
+ expanded_sub_val = NULL;
+ } else {
+ sub_val = expanded_sub_val;
+ }
+ }
+
+ if (sub_val) {
+ if (offset || ooffset) {
+ cloned_sub_val = strdup(sub_val);
+ switch_assert(cloned_sub_val);
+ sub_val = cloned_sub_val;
+ }
+
+ if (offset >= 0) {
+ sub_val += offset;
+ } else if ((size_t) abs(offset) <= strlen(sub_val)) {
+ sub_val = cloned_sub_val + (strlen(cloned_sub_val) + offset);
+ }
+
+ if (ooffset > 0 && (size_t) ooffset < strlen(sub_val)) {
+ if ((ptr = (char *) sub_val + ooffset)) {
+ *ptr = '\0';
+ }
+ }
+ }
+
+ switch_safe_free(expanded);
+ } else {
+ switch_stream_handle_t stream = { 0 };
+ char *expanded = NULL;
+
+ SWITCH_STANDARD_STREAM(stream);
+
+ if (stream.data) {
+ char *expanded_vname = NULL;
+
+ if ((expanded_vname = kz_event_expand_headers_check(event, (char *) vname, var_list, api_list, recur+1)) == vname) {
+ expanded_vname = NULL;
+ } else {
+ vname = expanded_vname;
+ }
+
+ if ((expanded = kz_event_expand_headers_check(event, vval, var_list, api_list, recur+1)) == vval) {
+ expanded = NULL;
+ } else {
+ vval = expanded;
+ }
+
+ if (!switch_core_test_flag(SCF_API_EXPANSION) || (api_list && !switch_event_check_permission_list(api_list, vname))) {
+ func_val = NULL;
+ sub_val = "";
+ } else {
+ stream.param_event = event;
+ if (kz_expand_api_execute(vname, vval, NULL, &stream) == SWITCH_STATUS_SUCCESS) {
+ func_val = stream.data;
+ sub_val = func_val;
+ } else {
+ free(stream.data);
+ }
+ }
+
+ switch_safe_free(expanded);
+ switch_safe_free(expanded_vname);
+
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n");
+ free(data);
+ free(indup);
+ return (char *) in;
+ }
+ }
+ if ((nlen = sub_val ? strlen(sub_val) : 0)) {
+ if (len + nlen >= olen) {
+ kz_resize(nlen);
+ }
+
+ len += nlen;
+ strcat(c, sub_val);
+ c += nlen;
+ }
+
+ switch_safe_free(func_val);
+ switch_safe_free(cloned_sub_val);
+ switch_safe_free(expanded_sub_val);
+ sub_val = NULL;
+ vname = NULL;
+ vtype = 0;
+ br = 0;
+ }
+
+ if (sp) {
+ if (len + 1 >= olen) {
+ kz_resize(1);
+ }
+
+ *c++ = ' ';
+ sp = 0;
+ len++;
+ }
+
+ if (*p == '$') {
+ p--;
+ } else {
+ if (len + 1 >= olen) {
+ kz_resize(1);
+ }
+
+ *c++ = *p;
+ len++;
+ }
+ }
+ }
+ free(indup);
+ switch_safe_free(gvar);
+
+ return data;
+}
+
+SWITCH_DECLARE(char *) kz_event_expand_headers(switch_event_t *event, const char *in)
+{
+ return kz_event_expand_headers_check(event, in, NULL, NULL, 0);
+}
+
+SWITCH_DECLARE(char *) kz_event_expand(const char *in)
+{
+ switch_event_t *event = NULL;
+ char *ret = NULL;
+ kz_switch_core_base_headers_for_expand(&event);
+ ret = kz_event_expand_headers_check(event, in, NULL, NULL, 0);
+ switch_event_destroy(&event);
+ return ret;
+}
+
+SWITCH_DECLARE(char *) kz_expand(const char *in)
+{
+ switch_event_t *event = NULL;
+ char *ret = NULL;
+ kz_switch_core_base_headers_for_expand(&event);
+ ret = kz_event_expand_headers_check(event, in, NULL, NULL, 0);
+ switch_event_destroy(&event);
+ return ret;
+}
+
+SWITCH_DECLARE(char *) kz_expand_pool(switch_memory_pool_t *pool, const char *in)
+{
+ char *expanded;
+ char *dup = NULL;
+
+ if(!(expanded = kz_expand(in))) {
return NULL;
}
+ dup = switch_core_strdup(pool, expanded);
- if (switch_socket_create(&socket, switch_sockaddr_get_family(sa), SOCK_STREAM, SWITCH_PROTO_TCP, pool)) {
- return NULL;
+ if (expanded != in) {
+ switch_safe_free(expanded);
}
- if (switch_socket_opt_set(socket, SWITCH_SO_REUSEADDR, 1)) {
- return NULL;
- }
-
- if (switch_socket_bind(socket, sa)) {
- return NULL;
- }
-
- if (switch_socket_listen(socket, 5)){
- return NULL;
- }
-
- switch_getnameinfo(&kazoo_globals.hostname, sa, 0);
-
- // if (kazoo_globals.nat_map && switch_nat_get_type()) {
- // switch_nat_add_mapping(port, SWITCH_NAT_TCP, NULL, SWITCH_FALSE);
- // }
-
- return socket;
+ return dup;
}
-switch_socket_t *create_socket(switch_memory_pool_t *pool) {
- return create_socket_with_port(pool, 0);
-
+char* kz_switch_event_get_first_of(switch_event_t *event, const char *list[])
+{
+ switch_event_header_t *header = NULL;
+ int i = 0;
+ while(list[i] != NULL) {
+ if((header = switch_event_get_header_ptr(event, list[i])) != NULL)
+ break;
+ i++;
+ }
+ if(header != NULL) {
+ return header->value;
+ } else {
+ return "nodomain";
+ }
}
-switch_status_t create_ei_cnode(const char *ip_addr, const char *name, struct ei_cnode_s *ei_cnode) {
- char hostname[EI_MAXHOSTNAMELEN + 1] = "";
- char nodename[MAXNODELEN + 1];
- char cnodename[EI_MAXALIVELEN + 1];
- //EI_MAX_COOKIE_SIZE+1
- char *atsign;
+SWITCH_DECLARE(switch_status_t) kz_switch_event_add_variable_name_printf(switch_event_t *event, switch_stack_t stack, const char *val, const char *fmt, ...)
+{
+ int ret = 0;
+ char *varname;
+ va_list ap;
+ switch_status_t status = SWITCH_STATUS_SUCCESS;
- /* copy the erlang interface nodename into something we can modify */
- strncpy(cnodename, name, EI_MAXALIVELEN);
+ switch_assert(event != NULL);
- if ((atsign = strchr(cnodename, '@'))) {
- /* we got a qualified node name, don't guess the host/domain */
- snprintf(nodename, MAXNODELEN + 1, "%s", kazoo_globals.ei_nodename);
- /* truncate the alivename at the @ */
- *atsign = '\0';
- } else {
- if (zstr(kazoo_globals.hostname) || !strncasecmp(kazoo_globals.ip, "0.0.0.0", 7) || !strncasecmp(kazoo_globals.ip, "::", 2)) {
- memcpy(hostname, switch_core_get_hostname(), EI_MAXHOSTNAMELEN);
- } else {
- memcpy(hostname, kazoo_globals.hostname, EI_MAXHOSTNAMELEN);
- }
- snprintf(nodename, MAXNODELEN + 1, "%s@%s", kazoo_globals.ei_nodename, hostname);
- }
+ va_start(ap, fmt);
+ ret = switch_vasprintf(&varname, fmt, ap);
+ va_end(ap);
- if (kazoo_globals.ei_shortname) {
- char *off;
- if ((off = strchr(nodename, '.'))) {
- *off = '\0';
+ if (ret == -1) {
+ return SWITCH_STATUS_MEMERR;
+ }
+
+ status = switch_event_add_header_string(event, stack, varname, val);
+
+ free(varname);
+
+ return status;
+}
+
+SWITCH_DECLARE(switch_xml_t) kz_xml_child(switch_xml_t xml, const char *name)
+{
+ xml = (xml) ? xml->child : NULL;
+ while (xml && strcasecmp(name, xml->name))
+ xml = xml->sibling;
+ return xml;
+}
+
+void kz_xml_process(switch_xml_t cfg)
+{
+ switch_xml_t xml_process;
+ for (xml_process = kz_xml_child(cfg, "X-PRE-PROCESS"); xml_process; xml_process = xml_process->next) {
+ const char *cmd = switch_xml_attr(xml_process, "cmd");
+ const char *data = switch_xml_attr(xml_process, "data");
+ if(cmd != NULL && !strcasecmp(cmd, "set") && data) {
+ char *name = (char *) data;
+ char *val = strchr(name, '=');
+
+ if (val) {
+ char *ve = val++;
+ while (*val && *val == ' ') {
+ val++;
+ }
+ *ve-- = '\0';
+ while (*ve && *ve == ' ') {
+ *ve-- = '\0';
+ }
+ }
+
+ if (name && val) {
+ switch_core_set_variable(name, val);
+ }
}
}
- /* init the ec stuff */
- if (ei_connect_xinit(ei_cnode, hostname, cnodename, nodename, (Erl_IpAddr) ip_addr, kazoo_globals.ei_cookie, 0) < 0) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to initialize the erlang interface connection structure\n");
- return SWITCH_STATUS_FALSE;
- }
-
- return SWITCH_STATUS_SUCCESS;
}
-switch_status_t ei_compare_pids(const erlang_pid *pid1, const erlang_pid *pid2) {
- if ((!strcmp(pid1->node, pid2->node))
- && pid1->creation == pid2->creation
- && pid1->num == pid2->num
- && pid1->serial == pid2->serial) {
- return SWITCH_STATUS_SUCCESS;
- } else {
- return SWITCH_STATUS_FALSE;
- }
-}
-
-void ei_link(ei_node_t *ei_node, erlang_pid * from, erlang_pid * to) {
- char msgbuf[2048];
- char *s;
- int index = 0;
-
- index = 5; /* max sizes: */
- ei_encode_version(msgbuf, &index); /* 1 */
- ei_encode_tuple_header(msgbuf, &index, 3);
- ei_encode_long(msgbuf, &index, ERL_LINK);
- ei_encode_pid(msgbuf, &index, from); /* 268 */
- ei_encode_pid(msgbuf, &index, to); /* 268 */
-
- /* 5 byte header missing */
- s = msgbuf;
- put32be(s, index - 4); /* 4 */
- put8(s, ERL_PASS_THROUGH); /* 1 */
- /* sum: 542 */
-
- if (write(ei_node->nodefd, msgbuf, index) == -1) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Failed to link to process on %s\n", ei_node->peer_nodename);
- }
-}
-
-void ei_encode_switch_event(ei_x_buff *ebuf, switch_event_t *event) {
- ei_x_encode_tuple_header(ebuf, 2);
- ei_x_encode_atom(ebuf, "event");
- ei_encode_switch_event_headers(ebuf, event);
-}
-
-int ei_helper_send(ei_node_t *ei_node, erlang_pid *to, ei_x_buff *buf) {
- int ret = 0;
-
- if (ei_node->nodefd) {
-#ifdef EI_DEBUG
- ei_x_print_msg(buf, to, 1);
-#endif
- ret = ei_send(ei_node->nodefd, to, buf->buff, buf->index);
- }
-
- return ret;
-}
-
-int ei_decode_atom_safe(char *buf, int *index, char *dst) {
- int type, size;
-
- ei_get_type(buf, index, &type, &size);
-
- if (type != ERL_ATOM_EXT) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unexpected erlang term type %d (size %d), needed atom\n", type, size);
- return -1;
- } else if (size > MAXATOMLEN) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Requested decoding of atom with size %d into a buffer of size %d\n", size, MAXATOMLEN);
- return -1;
- } else {
- return ei_decode_atom(buf, index, dst);
- }
-}
-
-int ei_decode_string_or_binary(char *buf, int *index, char **dst) {
- int type, size, res;
- long len;
-
- ei_get_type(buf, index, &type, &size);
-
- if (type != ERL_STRING_EXT && type != ERL_BINARY_EXT && type != ERL_NIL_EXT) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unexpected erlang term type %d (size %d), needed binary or string\n", type, size);
- return -1;
- }
-
- *dst = malloc(size + 1);
-
- if (type == ERL_NIL_EXT) {
- res = 0;
- **dst = '\0';
- } else if (type == ERL_BINARY_EXT) {
- res = ei_decode_binary(buf, index, *dst, &len);
- (*dst)[len] = '\0';
- } else {
- res = ei_decode_string(buf, index, *dst);
- }
-
- return res;
-}
-
-int ei_decode_string_or_binary_limited(char *buf, int *index, int maxsize, char *dst) {
- int type, size, res;
- long len;
-
- ei_get_type(buf, index, &type, &size);
-
- if (type != ERL_STRING_EXT && type != ERL_BINARY_EXT && type != ERL_NIL_EXT) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unexpected erlang term type %d (size %d), needed binary or string\n", type, size);
- return -1;
- }
-
- if (size > maxsize) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Requested decoding of %s with size %d into a buffer of size %d\n",
- type == ERL_BINARY_EXT ? "binary" : "string", size, maxsize);
- return -1;
- }
-
- if (type == ERL_NIL_EXT) {
- res = 0;
- *dst = '\0';
- } else if (type == ERL_BINARY_EXT) {
- res = ei_decode_binary(buf, index, dst, &len);
- dst[len] = '\0'; /* binaries aren't null terminated */
- } else {
- res = ei_decode_string(buf, index, dst);
- }
-
- return res;
-}
-
-switch_hash_t *create_default_filter() {
- switch_hash_t *filter;
-
- switch_core_hash_init(&filter);
-
- switch_core_hash_insert(filter, "Acquired-UUID", "1");
- switch_core_hash_insert(filter, "action", "1");
- switch_core_hash_insert(filter, "Action", "1");
- switch_core_hash_insert(filter, "alt_event_type", "1");
- switch_core_hash_insert(filter, "Answer-State", "1");
- switch_core_hash_insert(filter, "Application", "1");
- switch_core_hash_insert(filter, "Application-Data", "1");
- switch_core_hash_insert(filter, "Application-Name", "1");
- switch_core_hash_insert(filter, "Application-Response", "1");
- switch_core_hash_insert(filter, "att_xfer_replaced_by", "1");
- switch_core_hash_insert(filter, "Auth-Method", "1");
- switch_core_hash_insert(filter, "Auth-Realm", "1");
- switch_core_hash_insert(filter, "Auth-User", "1");
- switch_core_hash_insert(filter, "Bridge-A-Unique-ID", "1");
- switch_core_hash_insert(filter, "Bridge-B-Unique-ID", "1");
- switch_core_hash_insert(filter, "Call-Direction", "1");
- switch_core_hash_insert(filter, "Caller-Callee-ID-Name", "1");
- switch_core_hash_insert(filter, "Caller-Callee-ID-Number", "1");
- switch_core_hash_insert(filter, "Caller-Caller-ID-Name", "1");
- switch_core_hash_insert(filter, "Caller-Caller-ID-Number", "1");
- switch_core_hash_insert(filter, "Caller-Screen-Bit", "1");
- switch_core_hash_insert(filter, "Caller-Privacy-Hide-Name", "1");
- switch_core_hash_insert(filter, "Caller-Privacy-Hide-Number", "1");
- switch_core_hash_insert(filter, "Caller-Context", "1");
- switch_core_hash_insert(filter, "Caller-Controls", "1");
- switch_core_hash_insert(filter, "Caller-Destination-Number", "1");
- switch_core_hash_insert(filter, "Caller-Dialplan", "1");
- switch_core_hash_insert(filter, "Caller-Network-Addr", "1");
- switch_core_hash_insert(filter, "Caller-Unique-ID", "1");
- switch_core_hash_insert(filter, "Call-ID", "1");
- switch_core_hash_insert(filter, "Channel-Call-State", "1");
- switch_core_hash_insert(filter, "Channel-Call-UUID", "1");
- switch_core_hash_insert(filter, "Channel-Presence-ID", "1");
- switch_core_hash_insert(filter, "Channel-State", "1");
- switch_core_hash_insert(filter, "Chat-Permissions", "1");
- switch_core_hash_insert(filter, "Conference-Name", "1");
- switch_core_hash_insert(filter, "Conference-Profile-Name", "1");
- switch_core_hash_insert(filter, "Conference-Unique-ID", "1");
- switch_core_hash_insert(filter, "contact", "1");
- switch_core_hash_insert(filter, "Detected-Tone", "1");
- switch_core_hash_insert(filter, "dialog_state", "1");
- switch_core_hash_insert(filter, "direction", "1");
- switch_core_hash_insert(filter, "Distributed-From", "1");
- switch_core_hash_insert(filter, "DTMF-Digit", "1");
- switch_core_hash_insert(filter, "DTMF-Duration", "1");
- switch_core_hash_insert(filter, "Event-Date-Timestamp", "1");
- switch_core_hash_insert(filter, "Event-Name", "1");
- switch_core_hash_insert(filter, "Event-Subclass", "1");
- switch_core_hash_insert(filter, "expires", "1");
- switch_core_hash_insert(filter, "Expires", "1");
- switch_core_hash_insert(filter, "Ext-SIP-IP", "1");
- switch_core_hash_insert(filter, "File", "1");
- switch_core_hash_insert(filter, "FreeSWITCH-Hostname", "1");
- switch_core_hash_insert(filter, "from", "1");
- switch_core_hash_insert(filter, "Hunt-Destination-Number", "1");
- switch_core_hash_insert(filter, "ip", "1");
- switch_core_hash_insert(filter, "Message-Account", "1");
- switch_core_hash_insert(filter, "metadata", "1");
- switch_core_hash_insert(filter, "old_node_channel_uuid", "1");
- switch_core_hash_insert(filter, "Other-Leg-Callee-ID-Name", "1");
- switch_core_hash_insert(filter, "Other-Leg-Callee-ID-Number", "1");
- switch_core_hash_insert(filter, "Other-Leg-Caller-ID-Name", "1");
- switch_core_hash_insert(filter, "Other-Leg-Caller-ID-Number", "1");
- switch_core_hash_insert(filter, "Other-Leg-Destination-Number", "1");
- switch_core_hash_insert(filter, "Other-Leg-Direction", "1");
- switch_core_hash_insert(filter, "Other-Leg-Unique-ID", "1");
- switch_core_hash_insert(filter, "Other-Leg-Channel-Name", "1");
- switch_core_hash_insert(filter, "Participant-Type", "1");
- switch_core_hash_insert(filter, "Path", "1");
- switch_core_hash_insert(filter, "profile_name", "1");
- switch_core_hash_insert(filter, "Profiles", "1");
- switch_core_hash_insert(filter, "proto-specific-event-name", "1");
- switch_core_hash_insert(filter, "Raw-Application-Data", "1");
- switch_core_hash_insert(filter, "realm", "1");
- switch_core_hash_insert(filter, "Resigning-UUID", "1");
- switch_core_hash_insert(filter, "set", "1");
- switch_core_hash_insert(filter, "sip_auto_answer", "1");
- switch_core_hash_insert(filter, "sip_auth_method", "1");
- switch_core_hash_insert(filter, "sip_from_host", "1");
- switch_core_hash_insert(filter, "sip_from_user", "1");
- switch_core_hash_insert(filter, "sip_to_host", "1");
- switch_core_hash_insert(filter, "sip_to_user", "1");
- switch_core_hash_insert(filter, "sub-call-id", "1");
- switch_core_hash_insert(filter, "technology", "1");
- switch_core_hash_insert(filter, "to", "1");
- switch_core_hash_insert(filter, "Unique-ID", "1");
- switch_core_hash_insert(filter, "URL", "1");
- switch_core_hash_insert(filter, "username", "1");
- switch_core_hash_insert(filter, "variable_channel_is_moving", "1");
- switch_core_hash_insert(filter, "variable_collected_digits", "1");
- switch_core_hash_insert(filter, "variable_current_application", "1");
- switch_core_hash_insert(filter, "variable_current_application_data", "1");
- switch_core_hash_insert(filter, "variable_domain_name", "1");
- switch_core_hash_insert(filter, "variable_effective_caller_id_name", "1");
- switch_core_hash_insert(filter, "variable_effective_caller_id_number", "1");
- switch_core_hash_insert(filter, "variable_holding_uuid", "1");
- switch_core_hash_insert(filter, "variable_hold_music", "1");
- switch_core_hash_insert(filter, "variable_media_group_id", "1");
- switch_core_hash_insert(filter, "variable_originate_disposition", "1");
- switch_core_hash_insert(filter, "variable_origination_uuid", "1");
- switch_core_hash_insert(filter, "variable_playback_terminator_used", "1");
- switch_core_hash_insert(filter, "variable_presence_id", "1");
- switch_core_hash_insert(filter, "variable_record_ms", "1");
- switch_core_hash_insert(filter, "variable_recovered", "1");
- switch_core_hash_insert(filter, "variable_silence_hits_exhausted", "1");
- switch_core_hash_insert(filter, "variable_sip_auth_realm", "1");
- switch_core_hash_insert(filter, "variable_sip_from_host", "1");
- switch_core_hash_insert(filter, "variable_sip_from_user", "1");
- switch_core_hash_insert(filter, "variable_sip_from_tag", "1");
- switch_core_hash_insert(filter, "variable_sip_h_X-AUTH-IP", "1");
- switch_core_hash_insert(filter, "variable_sip_received_ip", "1");
- switch_core_hash_insert(filter, "variable_sip_to_host", "1");
- switch_core_hash_insert(filter, "variable_sip_to_user", "1");
- switch_core_hash_insert(filter, "variable_sip_to_tag", "1");
- switch_core_hash_insert(filter, "variable_sofia_profile_name", "1");
- switch_core_hash_insert(filter, "variable_transfer_history", "1");
- switch_core_hash_insert(filter, "variable_user_name", "1");
- switch_core_hash_insert(filter, "variable_endpoint_disposition", "1");
- switch_core_hash_insert(filter, "variable_originate_disposition", "1");
- switch_core_hash_insert(filter, "variable_bridge_hangup_cause", "1");
- switch_core_hash_insert(filter, "variable_hangup_cause", "1");
- switch_core_hash_insert(filter, "variable_last_bridge_proto_specific_hangup_cause", "1");
- switch_core_hash_insert(filter, "variable_proto_specific_hangup_cause", "1");
- switch_core_hash_insert(filter, "VM-Call-ID", "1");
- switch_core_hash_insert(filter, "VM-sub-call-id", "1");
- switch_core_hash_insert(filter, "whistle_application_name", "1");
- switch_core_hash_insert(filter, "whistle_application_response", "1");
- switch_core_hash_insert(filter, "whistle_event_name", "1");
- switch_core_hash_insert(filter, "kazoo_application_name", "1");
- switch_core_hash_insert(filter, "kazoo_application_response", "1");
- switch_core_hash_insert(filter, "kazoo_event_name", "1");
- switch_core_hash_insert(filter, "sip_auto_answer_notify", "1");
- switch_core_hash_insert(filter, "eavesdrop_group", "1");
- switch_core_hash_insert(filter, "origination_caller_id_name", "1");
- switch_core_hash_insert(filter, "origination_caller_id_number", "1");
- switch_core_hash_insert(filter, "origination_callee_id_name", "1");
- switch_core_hash_insert(filter, "origination_callee_id_number", "1");
- switch_core_hash_insert(filter, "sip_auth_username", "1");
- switch_core_hash_insert(filter, "sip_auth_password", "1");
- switch_core_hash_insert(filter, "effective_caller_id_name", "1");
- switch_core_hash_insert(filter, "effective_caller_id_number", "1");
- switch_core_hash_insert(filter, "effective_callee_id_name", "1");
- switch_core_hash_insert(filter, "effective_callee_id_number", "1");
- switch_core_hash_insert(filter, "variable_destination_number", "1");
- switch_core_hash_insert(filter, "variable_effective_callee_id_name", "1");
- switch_core_hash_insert(filter, "variable_effective_callee_id_number", "1");
- switch_core_hash_insert(filter, "variable_record_silence_hits", "1");
- switch_core_hash_insert(filter, "variable_refer_uuid", "1");
- switch_core_hash_insert(filter, "variable_sip_call_id", "1");
- switch_core_hash_insert(filter, "variable_sip_h_Referred-By", "1");
- switch_core_hash_insert(filter, "variable_sip_h_X-AUTH-PORT", "1");
- switch_core_hash_insert(filter, "variable_sip_loopback_req_uri", "1");
- switch_core_hash_insert(filter, "variable_sip_received_port", "1");
- switch_core_hash_insert(filter, "variable_sip_refer_to", "1");
- switch_core_hash_insert(filter, "variable_sip_req_host", "1");
- switch_core_hash_insert(filter, "variable_sip_req_uri", "1");
- switch_core_hash_insert(filter, "variable_transfer_source", "1");
- switch_core_hash_insert(filter, "variable_uuid", "1");
-
- /* Registration headers */
- switch_core_hash_insert(filter, "call-id", "1");
- switch_core_hash_insert(filter, "profile-name", "1");
- switch_core_hash_insert(filter, "from-user", "1");
- switch_core_hash_insert(filter, "from-host", "1");
- switch_core_hash_insert(filter, "presence-hosts", "1");
- switch_core_hash_insert(filter, "contact", "1");
- switch_core_hash_insert(filter, "rpid", "1");
- switch_core_hash_insert(filter, "status", "1");
- switch_core_hash_insert(filter, "expires", "1");
- switch_core_hash_insert(filter, "to-user", "1");
- switch_core_hash_insert(filter, "to-host", "1");
- switch_core_hash_insert(filter, "network-ip", "1");
- switch_core_hash_insert(filter, "network-port", "1");
- switch_core_hash_insert(filter, "username", "1");
- switch_core_hash_insert(filter, "realm", "1");
- switch_core_hash_insert(filter, "user-agent", "1");
-
- switch_core_hash_insert(filter, "Hangup-Cause", "1");
- switch_core_hash_insert(filter, "Unique-ID", "1");
- switch_core_hash_insert(filter, "variable_switch_r_sdp", "1");
- switch_core_hash_insert(filter, "variable_rtp_local_sdp_str", "1");
- switch_core_hash_insert(filter, "variable_sip_to_uri", "1");
- switch_core_hash_insert(filter, "variable_sip_from_uri", "1");
- switch_core_hash_insert(filter, "variable_sip_user_agent", "1");
- switch_core_hash_insert(filter, "variable_duration", "1");
- switch_core_hash_insert(filter, "variable_billsec", "1");
- switch_core_hash_insert(filter, "variable_billmsec", "1");
- switch_core_hash_insert(filter, "variable_progresssec", "1");
- switch_core_hash_insert(filter, "variable_progress_uepoch", "1");
- switch_core_hash_insert(filter, "variable_progress_media_uepoch", "1");
- switch_core_hash_insert(filter, "variable_start_uepoch", "1");
- switch_core_hash_insert(filter, "variable_digits_dialed", "1");
- switch_core_hash_insert(filter, "Member-ID", "1");
- switch_core_hash_insert(filter, "Floor", "1");
- switch_core_hash_insert(filter, "Video", "1");
- switch_core_hash_insert(filter, "Hear", "1");
- switch_core_hash_insert(filter, "Speak", "1");
- switch_core_hash_insert(filter, "Talking", "1");
- switch_core_hash_insert(filter, "Current-Energy", "1");
- switch_core_hash_insert(filter, "Energy-Level", "1");
- switch_core_hash_insert(filter, "Mute-Detect", "1");
-
- /* RTMP headers */
- switch_core_hash_insert(filter, "RTMP-Session-ID", "1");
- switch_core_hash_insert(filter, "RTMP-Profile", "1");
- switch_core_hash_insert(filter, "RTMP-Flash-Version", "1");
- switch_core_hash_insert(filter, "RTMP-SWF-URL", "1");
- switch_core_hash_insert(filter, "RTMP-TC-URL", "1");
- switch_core_hash_insert(filter, "RTMP-Page-URL", "1");
- switch_core_hash_insert(filter, "User", "1");
- switch_core_hash_insert(filter, "Domain", "1");
-
- /* Fax headers */
- switch_core_hash_insert(filter, "variable_fax_bad_rows", "1");
- switch_core_hash_insert(filter, "variable_fax_document_total_pages", "1");
- switch_core_hash_insert(filter, "variable_fax_document_transferred_pages", "1");
- switch_core_hash_insert(filter, "variable_fax_ecm_used", "1");
- switch_core_hash_insert(filter, "variable_fax_result_code", "1");
- switch_core_hash_insert(filter, "variable_fax_result_text", "1");
- switch_core_hash_insert(filter, "variable_fax_success", "1");
- switch_core_hash_insert(filter, "variable_fax_transfer_rate", "1");
- switch_core_hash_insert(filter, "variable_fax_local_station_id", "1");
- switch_core_hash_insert(filter, "variable_fax_remote_station_id", "1");
- switch_core_hash_insert(filter, "variable_fax_remote_country", "1");
- switch_core_hash_insert(filter, "variable_fax_remote_vendor", "1");
- switch_core_hash_insert(filter, "variable_fax_remote_model", "1");
- switch_core_hash_insert(filter, "variable_fax_image_resolution", "1");
- switch_core_hash_insert(filter, "variable_fax_file_image_resolution", "1");
- switch_core_hash_insert(filter, "variable_fax_image_size", "1");
- switch_core_hash_insert(filter, "variable_fax_image_pixel_size", "1");
- switch_core_hash_insert(filter, "variable_fax_file_image_pixel_size", "1");
- switch_core_hash_insert(filter, "variable_fax_longest_bad_row_run", "1");
- switch_core_hash_insert(filter, "variable_fax_encoding", "1");
- switch_core_hash_insert(filter, "variable_fax_encoding_name", "1");
- switch_core_hash_insert(filter, "variable_fax_header", "1");
- switch_core_hash_insert(filter, "variable_fax_ident", "1");
- switch_core_hash_insert(filter, "variable_fax_timezone", "1");
- switch_core_hash_insert(filter, "variable_fax_doc_id", "1");
- switch_core_hash_insert(filter, "variable_fax_doc_database", "1");
- switch_core_hash_insert(filter, "variable_has_t38", "1");
-
- /* Secure headers */
- switch_core_hash_insert(filter, "variable_sdp_secure_savp_only", "1");
- switch_core_hash_insert(filter, "variable_rtp_has_crypto", "1");
- switch_core_hash_insert(filter, "variable_rtp_secure_media", "1");
- switch_core_hash_insert(filter, "variable_rtp_secure_media_confirmed", "1");
- switch_core_hash_insert(filter, "variable_rtp_secure_media_confirmed_audio", "1");
- switch_core_hash_insert(filter, "variable_rtp_secure_media_confirmed_video", "1");
- switch_core_hash_insert(filter, "variable_zrtp_secure_media", "1");
- switch_core_hash_insert(filter, "variable_zrtp_secure_media_confirmed", "1");
- switch_core_hash_insert(filter, "variable_zrtp_secure_media_confirmed_audio", "1");
- switch_core_hash_insert(filter, "variable_zrtp_secure_media_confirmed_video", "1");
- switch_core_hash_insert(filter, "sdp_secure_savp_only", "1");
- switch_core_hash_insert(filter, "rtp_has_crypto", "1");
- switch_core_hash_insert(filter, "rtp_secure_media", "1");
- switch_core_hash_insert(filter, "rtp_secure_media_confirmed", "1");
- switch_core_hash_insert(filter, "rtp_secure_media_confirmed_audio", "1");
- switch_core_hash_insert(filter, "rtp_secure_media_confirmed_video", "1");
- switch_core_hash_insert(filter, "zrtp_secure_media", "1");
- switch_core_hash_insert(filter, "zrtp_secure_media_confirmed", "1");
- switch_core_hash_insert(filter, "zrtp_secure_media_confirmed_audio", "1");
- switch_core_hash_insert(filter, "zrtp_secure_media_confirmed_video", "1");
-
- /* Device Redirect headers */
- switch_core_hash_insert(filter, "variable_last_bridge_hangup_cause", "1");
- switch_core_hash_insert(filter, "variable_sip_redirected_by", "1");
- switch_core_hash_insert(filter, "intercepted_by", "1");
- switch_core_hash_insert(filter, "variable_bridge_uuid", "1");
- switch_core_hash_insert(filter, "Record-File-Path", "1");
-
- /* Loopback headers */
- switch_core_hash_insert(filter, "variable_loopback_bowout_on_execute", "1");
- switch_core_hash_insert(filter, "variable_loopback_bowout", "1");
- switch_core_hash_insert(filter, "variable_other_loopback_leg_uuid", "1");
- switch_core_hash_insert(filter, "variable_loopback_leg", "1");
- switch_core_hash_insert(filter, "variable_is_loopback", "1");
-
- // SMS
- switch_core_hash_insert(filter, "Message-ID", "1");
- switch_core_hash_insert(filter, "Delivery-Failure", "1");
- switch_core_hash_insert(filter, "Delivery-Result-Code", "1");
-
- return filter;
-}
-
-static void *SWITCH_THREAD_FUNC fetch_config_filters_exec(switch_thread_t *thread, void *obj)
+void kz_event_decode(switch_event_t *event)
{
- char *cf = "kazoo.conf";
- switch_xml_t cfg, xml, child, param;
- switch_event_t *params;
- switch_memory_pool_t *pool = (switch_memory_pool_t *)obj;
-
- switch_event_create(¶ms, SWITCH_EVENT_REQUEST_PARAMS);
- switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "Action", "request-filter");
-
- if (!(xml = switch_xml_open_cfg(cf, &cfg, params))) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to open configuration file %s\n", cf);
- } else if ((child = switch_xml_child(cfg, "event-filter"))) {
- switch_hash_t *filter;
- switch_hash_t *old_filter;
-
- switch_core_hash_init(&filter);
- for (param = switch_xml_child(child, "header"); param; param = param->next) {
- char *var = (char *) switch_xml_attr_soft(param, "name");
- switch_core_hash_insert(filter, var, "1");
+ switch_event_header_t *hp;
+ int i;
+ for (hp = event->headers; hp; hp = hp->next) {
+ if (hp->idx) {
+ for(i = 0; i < hp->idx; i++) {
+ switch_url_decode(hp->array[i]);
}
+ } else {
+ switch_url_decode(hp->value);
+ }
+ }
+}
- old_filter = kazoo_globals.event_filter;
- kazoo_globals.config_filters_fetched = 1;
- kazoo_globals.event_filter = filter;
- if (old_filter) {
- switch_core_hash_destroy(&old_filter);
- }
+char * kz_expand_vars(char *xml_str) {
+ return kz_expand_vars_pool(xml_str, NULL);
+}
- switch_xml_free(xml);
+char * kz_expand_vars_pool(char *xml_str, switch_memory_pool_t *pool) {
+ char *var, *val;
+ char *rp = xml_str; /* read pointer */
+ char *ep, *wp, *buff; /* end pointer, write pointer, write buffer */
+
+ if (!(strstr(xml_str, "$${"))) {
+ return xml_str;
}
- if (params) switch_event_destroy(¶ms);
- switch_core_destroy_memory_pool(&pool);
+ switch_zmalloc(buff, strlen(xml_str) * 2);
+ wp = buff;
+ ep = buff + (strlen(xml_str) * 2) - 1;
- return NULL;
-}
+ while (*rp && wp < ep) {
+ if (*rp == '$' && *(rp + 1) == '$' && *(rp + 2) == '{') {
+ char *e = switch_find_end_paren(rp + 2, '{', '}');
-void fetch_config_filters() {
- switch_memory_pool_t *pool;
- switch_thread_t *thread;
- switch_threadattr_t *thd_attr = NULL;
- switch_uuid_t uuid;
+ if (e) {
+ rp += 3;
+ var = rp;
+ *e++ = '\0';
+ rp = e;
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "trying to expand %s \n", var);
+ if ((val = switch_core_get_variable_dup(var))) {
+ char *p;
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "expanded %s to %s\n", var, val);
+ for (p = val; p && *p && wp <= ep; p++) {
+ *wp++ = *p;
+ }
+ switch_safe_free(val);
+ }
+ continue;
+ }
+ }
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "fetching kazoo filters\n");
+ *wp++ = *rp++;
+ }
- switch_core_new_memory_pool(&pool);
+ *wp++ = '\0';
- switch_threadattr_create(&thd_attr, pool);
- switch_threadattr_detach_set(thd_attr, 1);
- switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
-
- switch_uuid_get(&uuid);
- switch_thread_create(&thread, thd_attr, fetch_config_filters_exec, pool, pool);
+ if(pool) {
+ char * ret = switch_core_strdup(pool, buff);
+ switch_safe_free(buff);
+ return ret;
+ } else {
+ switch_safe_free(xml_str);
+ return buff;
+ }
}
-
+switch_status_t kz_json_api(const char * command, cJSON *args, cJSON **res)
+{
+ switch_status_t status = SWITCH_STATUS_SUCCESS;
+ cJSON *req = cJSON_CreateObject();
+ cJSON_AddItemToObject(req, "command", cJSON_CreateString(command));
+ cJSON_AddItemToObject(req, "data", args ? args : cJSON_CreateObject());
+ status = switch_json_api_execute(req, NULL, res);
+ cJSON_Delete(req);
+ return status;
+}
/* For Emacs:
* Local Variables:
diff --git a/src/mod/event_handlers/mod_kazoo/kz_node.c b/src/mod/event_handlers/mod_kazoo/kz_node.c
new file mode 100644
index 0000000000..26c362980b
--- /dev/null
+++ b/src/mod/event_handlers/mod_kazoo/kz_node.c
@@ -0,0 +1,91 @@
+#include "mod_kazoo.h"
+
+static int kz_nodes_module_names_array_callback(void *pArg, const char *module_name)
+{
+ cJSON *json = (cJSON *) pArg;
+ if(!strstr(module_name, "CORE")) {
+ cJSON_AddItemToArray(json, cJSON_CreateString(module_name));
+ }
+ return 0;
+}
+
+void kz_nodes_collect_media_role(cJSON *container)
+{
+ cJSON *retval = NULL;
+ if(kz_json_api("sofia.status.info", NULL, &retval) == SWITCH_STATUS_SUCCESS) {
+ if(retval != NULL && (!(retval->type & cJSON_NULL))) {
+ cJSON_AddItemToObject(container, "Media", cJSON_Duplicate(retval, 1));
+ }
+ }
+ if(retval) {
+ cJSON_Delete(retval);
+ }
+}
+
+void kz_nodes_collect_modules(cJSON *container)
+{
+ cJSON *modules = cJSON_CreateObject();
+ cJSON *loaded = cJSON_CreateArray();
+ cJSON *available = cJSON_CreateArray();
+ switch_loadable_module_enumerate_available(SWITCH_GLOBAL_dirs.mod_dir, kz_nodes_module_names_array_callback, available);
+ switch_loadable_module_enumerate_loaded(kz_nodes_module_names_array_callback, loaded);
+ cJSON_AddItemToObject(modules, "available", available);
+ cJSON_AddItemToObject(modules, "loaded", loaded);
+ cJSON_AddItemToObject(container, "Modules", modules);
+}
+
+void kz_nodes_collect_runtime(cJSON *container)
+{
+ cJSON *retval = NULL;
+ if(kz_json_api("status", NULL, &retval) == SWITCH_STATUS_SUCCESS) {
+ if(retval != NULL && (!(retval->type & cJSON_NULL))) {
+ cJSON *val = cJSON_Duplicate(retval, 1);
+ cJSON_AddItemToObject(val, "Core-UUID", cJSON_CreateString(switch_core_get_uuid()));
+ cJSON_AddItemToObject(container, "Runtime-Info", val);
+ }
+ }
+ if(retval) {
+ cJSON_Delete(retval);
+ }
+}
+
+void kz_nodes_collect_apps(cJSON *container)
+{
+ cJSON *apps = cJSON_CreateObject();
+ cJSON *app = cJSON_CreateObject();
+ cJSON_AddItemToObject(app, "Uptime", cJSON_CreateNumber(switch_core_uptime()));
+ cJSON_AddItemToObject(apps, "freeswitch", app);
+ cJSON_AddItemToObject(container, "WhApps", apps);
+}
+
+void kz_nodes_collect_roles(cJSON *container)
+{
+ cJSON *roles = cJSON_CreateObject();
+ cJSON_AddItemToObject(container, "Roles", roles);
+ kz_nodes_collect_media_role(roles);
+}
+
+cJSON * kz_node_create()
+{
+ cJSON *node = cJSON_CreateObject();
+
+ kz_nodes_collect_apps(node);
+ kz_nodes_collect_runtime(node);
+ kz_nodes_collect_modules(node);
+ kz_nodes_collect_roles(node);
+
+ return node;
+}
+
+SWITCH_STANDARD_JSON_API(kz_node_info_json_function)
+{
+ cJSON * ret = kz_node_create();
+ *json_reply = ret;
+ return SWITCH_STATUS_SUCCESS;
+}
+
+void add_kz_node(switch_loadable_module_interface_t **module_interface)
+{
+ switch_json_api_interface_t *json_api_interface = NULL;
+ SWITCH_ADD_JSON_API(json_api_interface, "node.info", "JSON node API", kz_node_info_json_function, "");
+}
diff --git a/src/mod/event_handlers/mod_kazoo/mod_kazoo.c b/src/mod/event_handlers/mod_kazoo/mod_kazoo.c
index b666920d3f..ca0538039b 100644
--- a/src/mod/event_handlers/mod_kazoo/mod_kazoo.c
+++ b/src/mod/event_handlers/mod_kazoo/mod_kazoo.c
@@ -32,608 +32,12 @@
*/
#include "mod_kazoo.h"
-#define KAZOO_DESC "kazoo information"
-#define KAZOO_SYNTAX " []"
+globals_t kazoo_globals = {0};
+
-globals_t kazoo_globals;
-SWITCH_MODULE_LOAD_FUNCTION(mod_kazoo_load);
-SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_kazoo_shutdown);
-SWITCH_MODULE_RUNTIME_FUNCTION(mod_kazoo_runtime);
SWITCH_MODULE_DEFINITION(mod_kazoo, mod_kazoo_load, mod_kazoo_shutdown, mod_kazoo_runtime);
-SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_pref_ip, kazoo_globals.ip);
-SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_pref_ei_cookie, kazoo_globals.ei_cookie);
-SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_pref_ei_nodename, kazoo_globals.ei_nodename);
-SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_pref_kazoo_var_prefix, kazoo_globals.kazoo_var_prefix);
-
-static switch_status_t api_erlang_status(switch_stream_handle_t *stream) {
- switch_sockaddr_t *sa;
- uint16_t port;
- char ipbuf[48];
- const char *ip_addr;
- ei_node_t *ei_node;
-
- switch_socket_addr_get(&sa, SWITCH_FALSE, kazoo_globals.acceptor);
-
- port = switch_sockaddr_get_port(sa);
- ip_addr = switch_get_addr(ipbuf, sizeof (ipbuf), sa);
-
- stream->write_function(stream, "Running %s\n", VERSION);
- stream->write_function(stream, "Listening for new Erlang connections on %s:%u with cookie %s\n", ip_addr, port, kazoo_globals.ei_cookie);
- stream->write_function(stream, "Registered as Erlang node %s, visible as %s\n", kazoo_globals.ei_cnode.thisnodename, kazoo_globals.ei_cnode.thisalivename);
-
- if (kazoo_globals.ei_compat_rel) {
- stream->write_function(stream, "Using Erlang compatibility mode: %d\n", kazoo_globals.ei_compat_rel);
- }
-
- switch_thread_rwlock_rdlock(kazoo_globals.ei_nodes_lock);
- ei_node = kazoo_globals.ei_nodes;
- if (!ei_node) {
- stream->write_function(stream, "No erlang nodes connected\n");
- } else {
- stream->write_function(stream, "Connected to:\n");
- while(ei_node != NULL) {
- unsigned int year, day, hour, min, sec, delta;
-
- delta = (switch_micro_time_now() - ei_node->created_time) / 1000000;
- sec = delta % 60;
- min = delta / 60 % 60;
- hour = delta / 3600 % 24;
- day = delta / 86400 % 7;
- year = delta / 31556926 % 12;
- stream->write_function(stream, " %s (%s:%d) up %d years, %d days, %d hours, %d minutes, %d seconds\n"
- ,ei_node->peer_nodename, ei_node->remote_ip, ei_node->remote_port, year, day, hour, min, sec);
- ei_node = ei_node->next;
- }
- }
- switch_thread_rwlock_unlock(kazoo_globals.ei_nodes_lock);
-
- return SWITCH_STATUS_SUCCESS;
-}
-
-static switch_status_t api_erlang_event_filter(switch_stream_handle_t *stream) {
- switch_hash_index_t *hi = NULL;
- int column = 0;
-
- for (hi = (switch_hash_index_t *)switch_core_hash_first_iter(kazoo_globals.event_filter, hi); hi; hi = switch_core_hash_next(&hi)) {
- const void *key;
- void *val;
- switch_core_hash_this(hi, &key, NULL, &val);
- stream->write_function(stream, "%-50s", (char *)key);
- if (++column > 2) {
- stream->write_function(stream, "\n");
- column = 0;
- }
- }
-
- if (++column > 2) {
- stream->write_function(stream, "\n");
- column = 0;
- }
-
- stream->write_function(stream, "%-50s", kazoo_globals.kazoo_var_prefix);
-
- return SWITCH_STATUS_SUCCESS;
-}
-
-static switch_status_t api_erlang_nodes_list(switch_stream_handle_t *stream) {
- ei_node_t *ei_node;
-
- switch_thread_rwlock_rdlock(kazoo_globals.ei_nodes_lock);
- ei_node = kazoo_globals.ei_nodes;
- while(ei_node != NULL) {
- stream->write_function(stream, "%s (%s)\n", ei_node->peer_nodename, ei_node->remote_ip);
- ei_node = ei_node->next;
- }
- switch_thread_rwlock_unlock(kazoo_globals.ei_nodes_lock);
-
- return SWITCH_STATUS_SUCCESS;
-}
-
-static switch_status_t api_erlang_nodes_count(switch_stream_handle_t *stream) {
- ei_node_t *ei_node;
- int count = 0;
-
- switch_thread_rwlock_rdlock(kazoo_globals.ei_nodes_lock);
- ei_node = kazoo_globals.ei_nodes;
- while(ei_node != NULL) {
- count++;
- ei_node = ei_node->next;
- }
- switch_thread_rwlock_unlock(kazoo_globals.ei_nodes_lock);
-
- stream->write_function(stream, "%d\n", count);
-
- return SWITCH_STATUS_SUCCESS;
-}
-
-static switch_status_t api_complete_erlang_node(const char *line, const char *cursor, switch_console_callback_match_t **matches) {
- switch_console_callback_match_t *my_matches = NULL;
- switch_status_t status = SWITCH_STATUS_FALSE;
- ei_node_t *ei_node;
-
- switch_thread_rwlock_rdlock(kazoo_globals.ei_nodes_lock);
- ei_node = kazoo_globals.ei_nodes;
- while(ei_node != NULL) {
- switch_console_push_match(&my_matches, ei_node->peer_nodename);
- ei_node = ei_node->next;
- }
- switch_thread_rwlock_unlock(kazoo_globals.ei_nodes_lock);
-
- if (my_matches) {
- *matches = my_matches;
- status = SWITCH_STATUS_SUCCESS;
- }
-
- return status;
-}
-
-static switch_status_t handle_node_api_event_stream(ei_event_stream_t *event_stream, switch_stream_handle_t *stream) {
- ei_event_binding_t *binding;
- int column = 0;
-
- switch_mutex_lock(event_stream->socket_mutex);
- if (event_stream->connected == SWITCH_FALSE) {
- switch_sockaddr_t *sa;
- uint16_t port;
- char ipbuf[48] = {0};
- const char *ip_addr;
-
- switch_socket_addr_get(&sa, SWITCH_TRUE, event_stream->acceptor);
- port = switch_sockaddr_get_port(sa);
- ip_addr = switch_get_addr(ipbuf, sizeof (ipbuf), sa);
-
- if (zstr(ip_addr)) {
- ip_addr = kazoo_globals.ip;
- }
-
- stream->write_function(stream, "%s:%d -> disconnected\n"
- ,ip_addr, port);
- } else {
- stream->write_function(stream, "%s:%d -> %s:%d\n"
- ,event_stream->local_ip, event_stream->local_port
- ,event_stream->remote_ip, event_stream->remote_port);
- }
-
- binding = event_stream->bindings;
- while(binding != NULL) {
- if (binding->type == SWITCH_EVENT_CUSTOM) {
- stream->write_function(stream, "CUSTOM %-43s", binding->subclass_name);
- } else {
- stream->write_function(stream, "%-50s", switch_event_name(binding->type));
- }
-
- if (++column > 2) {
- stream->write_function(stream, "\n");
- column = 0;
- }
-
- binding = binding->next;
- }
- switch_mutex_unlock(event_stream->socket_mutex);
-
- if (!column) {
- stream->write_function(stream, "\n");
- } else {
- stream->write_function(stream, "\n\n");
- }
-
- return SWITCH_STATUS_SUCCESS;
-}
-
-static switch_status_t handle_node_api_event_streams(ei_node_t *ei_node, switch_stream_handle_t *stream) {
- ei_event_stream_t *event_stream;
-
- switch_mutex_lock(ei_node->event_streams_mutex);
- event_stream = ei_node->event_streams;
- while(event_stream != NULL) {
- handle_node_api_event_stream(event_stream, stream);
- event_stream = event_stream->next;
- }
- switch_mutex_unlock(ei_node->event_streams_mutex);
-
- return SWITCH_STATUS_SUCCESS;
-}
-
-static switch_status_t handle_node_api_command(ei_node_t *ei_node, switch_stream_handle_t *stream, uint32_t command) {
- unsigned int year, day, hour, min, sec, delta;
-
- switch (command) {
- case API_COMMAND_DISCONNECT:
- stream->write_function(stream, "Disconnecting erlang node %s at managers request\n", ei_node->peer_nodename);
- switch_clear_flag(ei_node, LFLAG_RUNNING);
- break;
- case API_COMMAND_REMOTE_IP:
- delta = (switch_micro_time_now() - ei_node->created_time) / 1000000;
- sec = delta % 60;
- min = delta / 60 % 60;
- hour = delta / 3600 % 24;
- day = delta / 86400 % 7;
- year = delta / 31556926 % 12;
-
- stream->write_function(stream, "Uptime %d years, %d days, %d hours, %d minutes, %d seconds\n", year, day, hour, min, sec);
- stream->write_function(stream, "Local Address %s:%d\n", ei_node->local_ip, ei_node->local_port);
- stream->write_function(stream, "Remote Address %s:%d\n", ei_node->remote_ip, ei_node->remote_port);
- break;
- case API_COMMAND_STREAMS:
- handle_node_api_event_streams(ei_node, stream);
- break;
- case API_COMMAND_BINDINGS:
- handle_api_command_streams(ei_node, stream);
- break;
- default:
- break;
- }
-
- return SWITCH_STATUS_SUCCESS;
-}
-
-static switch_status_t api_erlang_node_command(switch_stream_handle_t *stream, const char *nodename, uint32_t command) {
- ei_node_t *ei_node;
-
- switch_thread_rwlock_rdlock(kazoo_globals.ei_nodes_lock);
- ei_node = kazoo_globals.ei_nodes;
- while(ei_node != NULL) {
- int length = strlen(ei_node->peer_nodename);
-
- if (!strncmp(ei_node->peer_nodename, nodename, length)) {
- handle_node_api_command(ei_node, stream, command);
- switch_thread_rwlock_unlock(kazoo_globals.ei_nodes_lock);
- return SWITCH_STATUS_SUCCESS;
- }
-
- ei_node = ei_node->next;
- }
- switch_thread_rwlock_unlock(kazoo_globals.ei_nodes_lock);
-
- return SWITCH_STATUS_NOTFOUND;
-}
-
-static int read_cookie_from_file(char *filename) {
- int fd;
- char cookie[MAXATOMLEN + 1];
- char *end;
- struct stat buf;
- ssize_t res;
-
- if (!stat(filename, &buf)) {
- if ((buf.st_mode & S_IRWXG) || (buf.st_mode & S_IRWXO)) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s must only be accessible by owner only.\n", filename);
- return 2;
- }
- if (buf.st_size > MAXATOMLEN) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s contains a cookie larger than the maximum atom size of %d.\n", filename, MAXATOMLEN);
- return 2;
- }
- fd = open(filename, O_RDONLY);
- if (fd < 1) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to open cookie file %s : %d.\n", filename, errno);
- return 2;
- }
-
- if ((res = read(fd, cookie, MAXATOMLEN)) < 1) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to read cookie file %s : %d.\n", filename, errno);
- }
-
- cookie[MAXATOMLEN] = '\0';
-
- /* replace any end of line characters with a null */
- if ((end = strchr(cookie, '\n'))) {
- *end = '\0';
- }
-
- if ((end = strchr(cookie, '\r'))) {
- *end = '\0';
- }
-
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set cookie from file %s: %s\n", filename, cookie);
-
- set_pref_ei_cookie(cookie);
- return 0;
- } else {
- /* don't error here, because we might be blindly trying to read $HOME/.erlang.cookie, and that can fail silently */
- return 1;
- }
-}
-
-static switch_status_t config(void) {
- char *cf = "kazoo.conf";
- switch_xml_t cfg, xml, child, param;
- kazoo_globals.send_all_headers = 0;
- kazoo_globals.send_all_private_headers = 1;
- kazoo_globals.connection_timeout = 500;
- kazoo_globals.receive_timeout = 200;
- kazoo_globals.receive_msg_preallocate = 2000;
- kazoo_globals.event_stream_preallocate = 4000;
- kazoo_globals.send_msg_batch = 10;
- kazoo_globals.event_stream_framing = 2;
- kazoo_globals.port = 0;
- kazoo_globals.io_fault_tolerance = 10;
-
- if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to open configuration file %s\n", cf);
- return SWITCH_STATUS_FALSE;
- } else {
- if ((child = switch_xml_child(cfg, "settings"))) {
- for (param = switch_xml_child(child, "param"); param; param = param->next) {
- char *var = (char *) switch_xml_attr_soft(param, "name");
- char *val = (char *) switch_xml_attr_soft(param, "value");
-
- if (!strcmp(var, "listen-ip")) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set bind ip address: %s\n", val);
- set_pref_ip(val);
- } else if (!strcmp(var, "listen-port")) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set bind port: %s\n", val);
- kazoo_globals.port = atoi(val);
- } else if (!strcmp(var, "cookie")) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set cookie: %s\n", val);
- set_pref_ei_cookie(val);
- } else if (!strcmp(var, "cookie-file")) {
- if (read_cookie_from_file(val) == 1) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to read cookie from %s\n", val);
- }
- } else if (!strcmp(var, "nodename")) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set node name: %s\n", val);
- set_pref_ei_nodename(val);
- } else if (!strcmp(var, "shortname")) {
- kazoo_globals.ei_shortname = switch_true(val);
- } else if (!strcmp(var, "kazoo-var-prefix")) {
- set_pref_kazoo_var_prefix(val);
- } else if (!strcmp(var, "compat-rel")) {
- if (atoi(val) >= 7)
- kazoo_globals.ei_compat_rel = atoi(val);
- else
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid compatibility release '%s' specified\n", val);
- } else if (!strcmp(var, "nat-map")) {
- kazoo_globals.nat_map = switch_true(val);
- } else if (!strcmp(var, "send-all-headers")) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set send-all-headers: %s\n", val);
- kazoo_globals.send_all_headers = switch_true(val);
- } else if (!strcmp(var, "send-all-private-headers")) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set send-all-private-headers: %s\n", val);
- kazoo_globals.send_all_private_headers = switch_true(val);
- } else if (!strcmp(var, "connection-timeout")) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set connection-timeout: %s\n", val);
- kazoo_globals.connection_timeout = atoi(val);
- } else if (!strcmp(var, "receive-timeout")) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set receive-timeout: %s\n", val);
- kazoo_globals.receive_timeout = atoi(val);
- } else if (!strcmp(var, "receive-msg-preallocate")) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set receive-msg-preallocate: %s\n", val);
- kazoo_globals.receive_msg_preallocate = atoi(val);
- } else if (!strcmp(var, "event-stream-preallocate")) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set event-stream-preallocate: %s\n", val);
- kazoo_globals.event_stream_preallocate = atoi(val);
- } else if (!strcmp(var, "send-msg-batch-size")) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set send-msg-batch-size: %s\n", val);
- kazoo_globals.send_msg_batch = atoi(val);
- } else if (!strcmp(var, "event-stream-framing")) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set event-stream-framing: %s\n", val);
- kazoo_globals.event_stream_framing = atoi(val);
- } else if (!strcmp(var, "io-fault-tolerance")) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set io-fault-tolerance: %s\n", val);
- kazoo_globals.io_fault_tolerance = atoi(val);
- }
- }
- }
-
- if ((child = switch_xml_child(cfg, "event-filter"))) {
- switch_hash_t *filter;
-
- switch_core_hash_init(&filter);
- for (param = switch_xml_child(child, "header"); param; param = param->next) {
- char *var = (char *) switch_xml_attr_soft(param, "name");
- switch_core_hash_insert(filter, var, "1");
- }
-
- kazoo_globals.event_filter = filter;
- }
-
- switch_xml_free(xml);
- }
-
- if (kazoo_globals.receive_msg_preallocate < 0) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid receive message preallocate value, disabled\n");
- kazoo_globals.receive_msg_preallocate = 0;
- }
-
- if (kazoo_globals.event_stream_preallocate < 0) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid event stream preallocate value, disabled\n");
- kazoo_globals.event_stream_preallocate = 0;
- }
-
- if (kazoo_globals.send_msg_batch < 1) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid send message batch size, reverting to default\n");
- kazoo_globals.send_msg_batch = 10;
- }
-
- if (kazoo_globals.io_fault_tolerance < 1) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid I/O fault tolerance, reverting to default\n");
- kazoo_globals.io_fault_tolerance = 10;
- }
-
- if (!kazoo_globals.event_filter) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Event filter not found in configuration, using default\n");
- kazoo_globals.event_filter = create_default_filter();
- }
-
- if (kazoo_globals.event_stream_framing < 1 || kazoo_globals.event_stream_framing > 4) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid event stream framing value, using default\n");
- kazoo_globals.event_stream_framing = 2;
- }
-
- if (zstr(kazoo_globals.kazoo_var_prefix)) {
- set_pref_kazoo_var_prefix("variable_ecallmgr*");
- kazoo_globals.var_prefix_length = 17; //ignore the *
- } else {
- /* we could use the global pool but then we would have to conditionally
- * free the pointer if it was not drawn from the XML */
- char *buf;
- int size = switch_snprintf(NULL, 0, "variable_%s*", kazoo_globals.kazoo_var_prefix) + 1;
-
- switch_malloc(buf, size);
- switch_snprintf(buf, size, "variable_%s*", kazoo_globals.kazoo_var_prefix);
- switch_safe_free(kazoo_globals.kazoo_var_prefix);
- kazoo_globals.kazoo_var_prefix = buf;
- kazoo_globals.var_prefix_length = size - 2; //ignore the *
- }
-
- if (!kazoo_globals.num_worker_threads) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Number of worker threads not found in configuration, using default\n");
- kazoo_globals.num_worker_threads = 10;
- }
-
- if (zstr(kazoo_globals.ip)) {
- set_pref_ip("0.0.0.0");
- }
-
- if (zstr(kazoo_globals.ei_cookie)) {
- int res;
- char *home_dir = getenv("HOME");
- char path_buf[1024];
-
- if (!zstr(home_dir)) {
- /* $HOME/.erlang.cookie */
- switch_snprintf(path_buf, sizeof (path_buf), "%s%s%s", home_dir, SWITCH_PATH_SEPARATOR, ".erlang.cookie");
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Checking for cookie at path: %s\n", path_buf);
-
- res = read_cookie_from_file(path_buf);
- if (res) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "No cookie or valid cookie file specified, using default cookie\n");
- set_pref_ei_cookie("ClueCon");
- }
- }
- }
-
- if (!kazoo_globals.ei_nodename) {
- set_pref_ei_nodename("freeswitch");
- }
-
- if (!kazoo_globals.nat_map) {
- kazoo_globals.nat_map = 0;
- }
-
- return SWITCH_STATUS_SUCCESS;
-}
-
-static switch_status_t create_acceptor() {
- switch_sockaddr_t *sa;
- uint16_t port;
- char ipbuf[48];
- const char *ip_addr;
-
- /* if the config has specified an erlang release compatibility then pass that along to the erlang interface */
- if (kazoo_globals.ei_compat_rel) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Compatability with OTP R%d requested\n", kazoo_globals.ei_compat_rel);
- ei_set_compat_rel(kazoo_globals.ei_compat_rel);
- }
-
- if (!(kazoo_globals.acceptor = create_socket_with_port(kazoo_globals.pool, kazoo_globals.port))) {
- return SWITCH_STATUS_SOCKERR;
- }
-
- switch_socket_addr_get(&sa, SWITCH_FALSE, kazoo_globals.acceptor);
-
- port = switch_sockaddr_get_port(sa);
- ip_addr = switch_get_addr(ipbuf, sizeof (ipbuf), sa);
-
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Erlang connection acceptor listening on %s:%u\n", ip_addr, port);
-
- /* try to initialize the erlang interface */
- if (create_ei_cnode(ip_addr, kazoo_globals.ei_nodename, &kazoo_globals.ei_cnode) != SWITCH_STATUS_SUCCESS) {
- return SWITCH_STATUS_SOCKERR;
- }
-
- /* tell the erlang port manager where we can be reached. this returns a file descriptor pointing to epmd or -1 */
- if ((kazoo_globals.epmdfd = ei_publish(&kazoo_globals.ei_cnode, port)) == -1) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
- "Failed to publish port to epmd. Try starting it yourself or run an erl shell with the -sname or -name option.\n");
- return SWITCH_STATUS_SOCKERR;
- }
-
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Connected to epmd and published erlang cnode name %s at port %d\n", kazoo_globals.ei_cnode.thisnodename, port);
-
- return SWITCH_STATUS_SUCCESS;
-}
-
-SWITCH_STANDARD_API(exec_api_cmd)
-{
- char *argv[1024] = { 0 };
- int unknown_command = 1, argc = 0;
- char *mycmd = NULL;
-
- const char *usage_string = "USAGE:\n"
- "--------------------------------------------------------------------------------------------------------------------\n"
- "erlang status - provides an overview of the current status\n"
- "erlang event_filter - lists the event headers that will be sent to Erlang nodes\n"
- "erlang nodes list - lists connected Erlang nodes (usefull for monitoring tools)\n"
- "erlang nodes count - provides a count of connected Erlang nodes (usefull for monitoring tools)\n"
- "erlang node disconnect - disconnects an Erlang node\n"
- "erlang node connection - Shows the connection info\n"
- "erlang node event_streams - lists the event streams for an Erlang node\n"
- "erlang node fetch_bindings - lists the XML fetch bindings for an Erlang node\n"
- "---------------------------------------------------------------------------------------------------------------------\n";
-
- if (zstr(cmd)) {
- stream->write_function(stream, "%s", usage_string);
- return SWITCH_STATUS_SUCCESS;
- }
-
- if (!(mycmd = strdup(cmd))) {
- return SWITCH_STATUS_MEMERR;
- }
-
- if (!(argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) {
- stream->write_function(stream, "%s", usage_string);
- switch_safe_free(mycmd);
- return SWITCH_STATUS_SUCCESS;
- }
-
- if (zstr(argv[0])) {
- stream->write_function(stream, "%s", usage_string);
- switch_safe_free(mycmd);
- return SWITCH_STATUS_SUCCESS;
- }
-
- if (!strncmp(argv[0], "status", 6)) {
- unknown_command = 0;
- api_erlang_status(stream);
- } else if (!strncmp(argv[0], "event_filter", 6)) {
- unknown_command = 0;
- api_erlang_event_filter(stream);
- } else if (!strncmp(argv[0], "nodes", 6) && !zstr(argv[1])) {
- if (!strncmp(argv[1], "list", 6)) {
- unknown_command = 0;
- api_erlang_nodes_list(stream);
- } else if (!strncmp(argv[1], "count", 6)) {
- unknown_command = 0;
- api_erlang_nodes_count(stream);
- }
- } else if (!strncmp(argv[0], "node", 6) && !zstr(argv[1]) && !zstr(argv[2])) {
- if (!strncmp(argv[2], "disconnect", 6)) {
- unknown_command = 0;
- api_erlang_node_command(stream, argv[1], API_COMMAND_DISCONNECT);
- } else if (!strncmp(argv[2], "connection", 2)) {
- unknown_command = 0;
- api_erlang_node_command(stream, argv[1], API_COMMAND_REMOTE_IP);
- } else if (!strncmp(argv[2], "event_streams", 6)) {
- unknown_command = 0;
- api_erlang_node_command(stream, argv[1], API_COMMAND_STREAMS);
- } else if (!strncmp(argv[2], "fetch_bindings", 6)) {
- unknown_command = 0;
- api_erlang_node_command(stream, argv[1], API_COMMAND_BINDINGS);
- }
- }
-
- if (unknown_command) {
- stream->write_function(stream, "%s", usage_string);
- }
-
- switch_safe_free(mycmd);
- return SWITCH_STATUS_SUCCESS;
-}
-
SWITCH_MODULE_LOAD_FUNCTION(mod_kazoo_load) {
switch_api_interface_t *api_interface = NULL;
switch_application_interface_t *app_interface = NULL;
@@ -643,34 +47,17 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_kazoo_load) {
kazoo_globals.pool = pool;
kazoo_globals.ei_nodes = NULL;
- if(config() != SWITCH_STATUS_SUCCESS) {
+ // ensure epmd is running
+
+ if(kazoo_load_config() != SWITCH_STATUS_SUCCESS) {
// TODO: what would we need to clean up here?
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Improper configuration!\n");
return SWITCH_STATUS_TERM;
}
- if(create_acceptor() != SWITCH_STATUS_SUCCESS) {
- // TODO: what would we need to clean up here
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to create erlang connection acceptor!\n");
- close_socket(&kazoo_globals.acceptor);
- return SWITCH_STATUS_TERM;
- }
-
/* connect my internal structure to the blank pointer passed to me */
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
- /* create an api for cli debug commands */
- SWITCH_ADD_API(api_interface, "erlang", KAZOO_DESC, exec_api_cmd, KAZOO_SYNTAX);
- switch_console_set_complete("add erlang status");
- switch_console_set_complete("add erlang event_filter");
- switch_console_set_complete("add erlang nodes list");
- switch_console_set_complete("add erlang nodes count");
- switch_console_set_complete("add erlang node ::erlang::node disconnect");
- switch_console_set_complete("add erlang node ::erlang::node connection");
- switch_console_set_complete("add erlang node ::erlang::node event_streams");
- switch_console_set_complete("add erlang node ::erlang::node fetch_bindings");
- switch_console_add_complete_func("::erlang::node", api_complete_erlang_node);
-
switch_thread_rwlock_create(&kazoo_globals.ei_nodes_lock, pool);
switch_set_flag(&kazoo_globals, LFLAG_RUNNING);
@@ -678,12 +65,24 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_kazoo_load) {
/* create all XML fetch agents */
bind_fetch_agents();
+ /* create an api for cli debug commands */
+ add_cli_api(module_interface, api_interface);
+
/* add our modified commands */
add_kz_commands(module_interface, api_interface);
/* add our modified dptools */
add_kz_dptools(module_interface, app_interface);
+ /* add our endpoints */
+ add_kz_endpoints(module_interface);
+
+ /* add our kz_node api */
+ add_kz_node(module_interface);
+
+ /* add tweaks */
+ kz_tweaks_start();
+
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS;
}
@@ -691,8 +90,10 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_kazoo_load) {
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_kazoo_shutdown) {
int sanity = 0;
- switch_console_set_complete("del erlang");
- switch_console_del_complete_func("::erlang::node");
+
+ remove_cli_api();
+
+ kz_tweaks_stop();
/* stop taking new requests and start shuting down the threads */
switch_clear_flag(&kazoo_globals, LFLAG_RUNNING);
@@ -706,6 +107,13 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_kazoo_shutdown) {
}
}
+ /* close the connection to epmd and the acceptor */
+ close_socketfd(&kazoo_globals.epmdfd);
+ close_socket(&kazoo_globals.acceptor);
+
+ /* remove all XML fetch agents */
+ unbind_fetch_agents();
+
if (kazoo_globals.event_filter) {
switch_core_hash_destroy(&kazoo_globals.event_filter);
}
@@ -714,71 +122,21 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_kazoo_shutdown) {
switch_thread_rwlock_unlock(kazoo_globals.ei_nodes_lock);
switch_thread_rwlock_destroy(kazoo_globals.ei_nodes_lock);
- /* close the connection to epmd and the acceptor */
- close_socketfd(&kazoo_globals.epmdfd);
- close_socket(&kazoo_globals.acceptor);
-
- /* remove all XML fetch agents */
- unbind_fetch_agents();
-
/* Close the port we reserved for uPnP/Switch behind firewall, if necessary */
- // if (kazoo_globals.nat_map && switch_nat_get_type()) {
- // switch_nat_del_mapping(kazoo_globals.port, SWITCH_NAT_TCP);
- // }
+ if (kazoo_globals.nat_map && switch_nat_get_type()) {
+ switch_nat_del_mapping(kazoo_globals.port, SWITCH_NAT_TCP);
+ }
+
+ kazoo_destroy_config();
/* clean up our allocated preferences */
switch_safe_free(kazoo_globals.ip);
switch_safe_free(kazoo_globals.ei_cookie);
switch_safe_free(kazoo_globals.ei_nodename);
- switch_safe_free(kazoo_globals.kazoo_var_prefix);
return SWITCH_STATUS_SUCCESS;
}
-SWITCH_MODULE_RUNTIME_FUNCTION(mod_kazoo_runtime) {
- switch_os_socket_t os_socket;
-
- switch_atomic_inc(&kazoo_globals.threads);
-
- switch_os_sock_get(&os_socket, kazoo_globals.acceptor);
-
- while (switch_test_flag(&kazoo_globals, LFLAG_RUNNING)) {
- int nodefd;
- ErlConnect conn;
-
- /* zero out errno because ei_accept doesn't differentiate between a */
- /* failed authentication or a socket failure, or a client version */
- /* mismatch or a godzilla attack (and a godzilla attack is highly likely) */
- errno = 0;
-
- /* wait here for an erlang node to connect, timming out to check if our module is still running every now-and-again */
- if ((nodefd = ei_accept_tmo(&kazoo_globals.ei_cnode, (int) os_socket, &conn, kazoo_globals.connection_timeout)) == ERL_ERROR) {
- if (erl_errno == ETIMEDOUT) {
- continue;
- } else if (errno) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Erlang connection acceptor socket error %d %d\n", erl_errno, errno);
- } else {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
- "Erlang node connection failed - ensure your cookie matches '%s' and you are using a good nodename\n", kazoo_globals.ei_cookie);
- }
- continue;
- }
-
- if (!switch_test_flag(&kazoo_globals, LFLAG_RUNNING)) {
- break;
- }
-
- /* NEW ERLANG NODE CONNECTION! Hello friend! */
- new_kazoo_node(nodefd, &conn);
- }
-
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Erlang connection acceptor shut down\n");
-
- switch_atomic_dec(&kazoo_globals.threads);
-
- return SWITCH_STATUS_TERM;
-}
-
/* For Emacs:
* Local Variables:
diff --git a/src/mod/event_handlers/mod_kazoo/mod_kazoo.h b/src/mod/event_handlers/mod_kazoo/mod_kazoo.h
index 9de7db6ea0..1fc12ba2aa 100644
--- a/src/mod/event_handlers/mod_kazoo/mod_kazoo.h
+++ b/src/mod/event_handlers/mod_kazoo/mod_kazoo.h
@@ -1,167 +1,29 @@
#include
#include
+#include
#include
#include
#include