- *
- * jquery.verto.js - Main interface
- *
- */
-
-(function($) {
-
- 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,
- videoParams: {},
- iceServers: false,
- ringSleep: 6000
- },
- options);
-
- verto.sessid = $.cookie('verto_session_uuid') || generateGUID();
- $.cookie('verto_session_uuid', verto.sessid, {
- expires: 1
- });
-
- verto.dialogs = {};
-
- verto.callbacks = callbacks || {};
-
- verto.eventSUBS = {};
-
- verto.rpcClient = new $.JsonRpcClient({
- login: verto.options.login,
- passwd: verto.options.passwd,
- socketUrl: verto.options.socketUrl,
- 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();
- }
- });
-
- if (verto.options.ringFile && verto.options.tag) {
- verto.ringer = $("#" + verto.options.tag);
- }
-
- verto.rpcClient.call('login', {});
-
- };
-
- $.verto.prototype.iceServers = function(on) {
- var verto = this;
-
- verto.options.iceServers = on;
- };
-
- $.verto.prototype.loginData = function(params) {
- 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();
- 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;
- }
-
- var dialog = new $.verto.dialog($.verto.enum.direction.outbound, this, args);
-
- dialog.invite();
-
- if (callbacks) {
- dialog.callbacks = callbacks;
- }
-
- 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 (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.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;
-
- 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);
- };
-
- 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(obj.asArray());
- 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(obj.asArray());
- } else {
- dt.fnAddData(args.data);
- }
- dt.fnAdjustColumnSizing();
- break;
- case "modify":
- if (!args.data) {
- return;
- }
- //console.debug(args, index);
- dt.fnUpdate(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(obj.asArray());
- 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.confMan = function(verto, params) {
- var confMan = this;
- conf
- 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++;
-
- function genMainMod(jq) {
- var play_id = "play_" + confMan.serno;
- var stop_id = "stop_" + confMan.serno;
- var recording_id = "recording_" + confMan.serno;
- var rec_stop_id = "recording_stop" + confMan.serno;
- var div_id = "confman_" + confMan.serno;
-
- var html = "
" +
- "" +
- "" +
- "" +
- ""
-
- + "
";
-
- jq.html(html);
-
- $("#" + play_id).click(function() {
- var file = prompt("Please enter file name", "");
- 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", "");
- 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 tmute_id = "tmute_" + x;
- var box_id = "box_" + x;
- var volup_id = "volume_in_up" + x;
- var voldn_id = "volume_in_dn" + x;
- var transfer_id = "transfer" + x;
-
-
- var html = "" +
- "" +
- "" +
- "" +
- "" +
- "" +
- "
"
- ;
-
- 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");
- confMan.modCommand("transfer", x, xten);
- });
-
- $("#" + kick_id).click(function() {
- confMan.modCommand("kick", x);
- });
-
- $("#" + tmute_id).click(function() {
- confMan.modCommand("tmute", x);
- });
-
- $("#" + volup_id).click(function() {
- confMan.modCommand("volume_in", x, "up");
- });
-
- $("#" + voldn_id).click(function() {
- confMan.modCommand("volume_in", x, "down");
- });
-
- return html;
- }
-
-
-
- var atitle = "";
- var awidth = 0;
-
- //$(".jsDataTable").width(confMan.params.hasVid ? "900px" : "800px");
-
- if (confMan.params.laData.role === "moderator") {
- atitle = "Action";
- awidth = 200;
-
- 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 (!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);
- }
-
- }
- });
-
- }
-
- 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"
- },
- {
- "sTitle": "Number"
- },
- {
- "sTitle": "Name"
- },
- {
- "sTitle": "Codec"
- },
- {
- "sTitle": "Status",
- "sWidth": confMan.params.hasVid ? "300px" : "150px"
- },
- {
- "sTitle": atitle,
- "sWidth": awidth,
-
- }],
- "bAutoWidth": true,
- "bDestroy": true,
- "bSort": false,
- "bInfo": false,
- "bFilter": false,
- "bLengthChange": false,
- "bPaginate": false,
- "iDisplayLength": 1000,
-
- "oLanguage": {
- "sEmptyTable": "The Conference is Empty....."
- },
-
- "fnRowCallback": row_callback
-
- });
- }
-
- $.verto.confMan.prototype.modCommand = function(cmd, id, value) {
- var confMan = this;
-
- confMan.verto.sendMethod("verto.broadcast", {
- "eventChannel": confMan.params.laData.modChannel,
- "data": {
- "application": "conf-control",
- "command": cmd,
- "id": id,
- "value": value
- }
- });
- }
-
- $.verto.confMan.prototype.destroy = function() {
- var confMan = this;
-
- confMan.destroyed = true;
-
- if (confMan.lt) {
- confMan.lt.destroy();
- }
-
- 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,
- tag: verto.options.tag,
- login: verto.options.login
- },
- params);
-
- 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;
-
- if (dialog.params.callID) {
- dialog.callID = dialog.params.callID;
- } else {
- dialog.callID = dialog.params.callID = generateGUID();
- }
-
- if (dialog.params.tag) {
- dialog.audioStream = document.getElementById(dialog.params.tag);
-
- if (dialog.params.useVideo) {
- dialog.videoStream = dialog.audioStream;
- }
- } //else conjure one TBD
-
- dialog.verto.dialogs[dialog.callID] = dialog;
-
- var RTCcallbacks = {};
-
- if (dialog.direction == $.verto.enum.direction.inbound) {
-
- dialog.params.remote_caller_id_name = dialog.params.caller_id_name;
- dialog.params.remote_caller_id_number = dialog.params.caller_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) {
-
- if (rtc.type == "offer") {
- console.log("offer", rtc.mediaData.SDP);
-
- 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.onError = function(e) {
- console.error("ERROR:", e);
- dialog.hangup();
- };
-
- dialog.rtc = new $.FSRTC({
- callbacks: RTCcallbacks,
- useVideo: dialog.videoStream,
- useAudio: dialog.audioStream,
- useStereo: dialog.params.useStereo,
- videoParams: verto.options.videoParams,
- iceServers: verto.options.iceServers
- });
-
- 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;
- }
-
- obj.dialogParams[i] = dialog.params[i];
- }
-
- 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;
- }
-
- $.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.info("Dialog " + dialog.callID + ": state change from " + dialog.state.name + " to " + state.name);
-
- dialog.lastState = dialog.state;
- dialog.state = state;
-
- if (!dialog.causeCode) {
- dialog.causeCode = 16;
- }
-
- if (!dialog.cause) {
- dialog.cause = "NORMAL CLEARING";
- }
-
- if (dialog.callbacks.onDialogState) {
- dialog.callbacks.onDialogState(this);
- }
-
- switch (dialog.state) {
- 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:
- delete verto.dialogs[dialog.callID];
- 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.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);
-
- };
-
- $.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.transfer = function(dest, params) {
- var dialog = this;
- if (dest) {
- cur_call.sendMethod("verto.modify", {
- action: "transfer",
- destination: dest,
- params: params
- });
- }
- };
-
- $.verto.dialog.prototype.hold = function(params) {
- var dialog = this;
-
- cur_call.sendMethod("verto.modify", {
- action: "hold",
- params: params
- });
- };
-
- $.verto.dialog.prototype.unhold = function(params) {
- var dialog = this;
-
- cur_call.sendMethod("verto.modify", {
- action: "unhold",
- params: params
- });
- };
-
- $.verto.dialog.prototype.toggleHold = function(params) {
- var dialog = this;
-
- cur_call.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) {
- if (params.useVideo) {
- dialog.useVideo(true);
- }
- dialog.params.callee_id_name = params.callee_id_name;
- dialog.params.callee_id_number = params.callee_id_number;
- }
- dialog.rtc.createAnswer(dialog.params.sdp);
- 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.msg);
- };
-
- $.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
- },
- requesting: {
- trying: 1,
- hangup: 1
- },
- recovering: {
- answering: 1,
- hangup: 1
- },
- trying: {
- active: 1,
- early: 1,
- hangup: 1
- },
- ringing: {
- answering: 1,
- hangup: 1
- },
- answering: {
- active: 1,
- hangup: 1
- },
- active: {
- 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");
-
- $.verto.enum = Object.freeze($.verto.enum);
-
- $.verto.saved = [];
-
- $(window).bind('beforeunload', function() {
- for (var i in $.verto.saved) {
- var verto = $.verto.saved[i];
- if (verto) {
- verto.logout();
- verto.purge();
- }
- }
- return $.verto.warnOnUnload;
- });
-
-})(jQuery);
+(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=28)TURN={url:'turn:turn.bistri.com:80',credential:'homeo',username:'homeo'};iceServers.iceServers=[STUN];}}
+var optional={optional:[]};if(!moz){optional.optional=[{DtlsSrtpKeyAgreement:true},{RtpDataChannels:options.onChannelMessage?true:false}];}
+var peer=new PeerConnection(iceServers,optional);openOffererChannel();var x=0;peer.onicecandidate=function(event){if(event.candidate){options.onICE(event.candidate);}else{if(options.onICEComplete){options.onICEComplete();}
+if(options.type=="offer"){if(!moz&&!x&&options.onICESDP){options.onICESDP(peer.localDescription);}}else{if(!x&&options.onICESDP){options.onICESDP(peer.localDescription);}}}};if(options.attachStream)peer.addStream(options.attachStream);if(options.attachStreams&&options.attachStream.length){var streams=options.attachStreams;for(var i=0;i1){return false;}
+return true;}
+$.JsonRpcClient.prototype.closeSocket=function(){if(self.socketReady()){this._ws_socket.onclose=function(w){console.log("Closing Socket")}
+this._ws_socket.close();}}
+$.JsonRpcClient.prototype.loginData=function(params){self.options.login=params.login;self.options.passwd=params.passwd;}
+$.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);}
+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._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;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},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 socket=self.jsonrpcclient.options.getSocket(self.jsonrpcclient.wsOnMessage);if(socket!==null){for(var 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.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;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);};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(obj.asArray());dt.fnAdjustColumnSizing();break;case"add":if(!args.data){console.error("missing data");return;}
+if(args.redraw>-1){dt.fnClearTable();dt.fnAddData(obj.asArray());}else{dt.fnAddData(args.data);}
+dt.fnAdjustColumnSizing();break;case"modify":if(!args.data){return;}
+dt.fnUpdate(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(obj.asArray());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.confMan=function(verto,params){var confMan=this;conf
+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++;function genMainMod(jq){var play_id="play_"+confMan.serno;var stop_id="stop_"+confMan.serno;var recording_id="recording_"+confMan.serno;var rec_stop_id="recording_stop"+confMan.serno;var div_id="confman_"+confMan.serno;var html="
"+""+""+""+""
++"
";jq.html(html);$("#"+play_id).click(function(){var file=prompt("Please enter file name","");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","");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 tmute_id="tmute_"+x;var box_id="box_"+x;var volup_id="volume_in_up"+x;var voldn_id="volume_in_dn"+x;var transfer_id="transfer"+x;var html=""+""+""+""+""+""+"
";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");confMan.modCommand("transfer",x,xten);});$("#"+kick_id).click(function(){confMan.modCommand("kick",x);});$("#"+tmute_id).click(function(){confMan.modCommand("tmute",x);});$("#"+volup_id).click(function(){confMan.modCommand("volume_in",x,"up");});$("#"+voldn_id).click(function(){confMan.modCommand("volume_in",x,"down");});return html;}
+var atitle="";var awidth=0;if(confMan.params.laData.role==="moderator"){atitle="Action";awidth=200;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(!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);}}});}
+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"},{"sTitle":"Number"},{"sTitle":"Name"},{"sTitle":"Codec"},{"sTitle":"Status","sWidth":confMan.params.hasVid?"300px":"150px"},{"sTitle":atitle,"sWidth":awidth,}],"bAutoWidth":true,"bDestroy":true,"bSort":false,"bInfo":false,"bFilter":false,"bLengthChange":false,"bPaginate":false,"iDisplayLength":1000,"oLanguage":{"sEmptyTable":"The Conference is Empty....."},"fnRowCallback":row_callback});}
+$.verto.confMan.prototype.modCommand=function(cmd,id,value){var confMan=this;confMan.verto.sendMethod("verto.broadcast",{"eventChannel":confMan.params.laData.modChannel,"data":{"application":"conf-control","command":cmd,"id":id,"value":value}});}
+$.verto.confMan.prototype.destroy=function(){var confMan=this;confMan.destroyed=true;if(confMan.lt){confMan.lt.destroy();}
+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,tag:verto.options.tag,login:verto.options.login},params);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;if(dialog.params.callID){dialog.callID=dialog.params.callID;}else{dialog.callID=dialog.params.callID=generateGUID();}
+if(dialog.params.tag){dialog.audioStream=document.getElementById(dialog.params.tag);if(dialog.params.useVideo){dialog.videoStream=dialog.audioStream;}}
+dialog.verto.dialogs[dialog.callID]=dialog;var RTCcallbacks={};if(dialog.direction==$.verto.enum.direction.inbound){dialog.params.remote_caller_id_name=dialog.params.caller_id_name;dialog.params.remote_caller_id_number=dialog.params.caller_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){if(rtc.type=="offer"){console.log("offer",rtc.mediaData.SDP);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.onError=function(e){console.error("ERROR:",e);dialog.hangup();};dialog.rtc=new $.FSRTC({callbacks:RTCcallbacks,useVideo:dialog.videoStream,useAudio:dialog.audioStream,useStereo:dialog.params.useStereo,videoParams:verto.options.videoParams,iceServers:verto.options.iceServers});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;}
+obj.dialogParams[i]=dialog.params[i];}
+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;}
+$.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.info("Dialog "+dialog.callID+": state change from "+dialog.state.name+" to "+state.name);dialog.lastState=dialog.state;dialog.state=state;if(!dialog.causeCode){dialog.causeCode=16;}
+if(!dialog.cause){dialog.cause="NORMAL CLEARING";}
+if(dialog.callbacks.onDialogState){dialog.callbacks.onDialogState(this);}
+switch(dialog.state){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:delete dialog.verto.dialogs[dialog.callID];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.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);};$.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.transfer=function(dest,params){var dialog=this;if(dest){cur_call.sendMethod("verto.modify",{action:"transfer",destination:dest,params:params});}};$.verto.dialog.prototype.hold=function(params){var dialog=this;cur_call.sendMethod("verto.modify",{action:"hold",params:params});};$.verto.dialog.prototype.unhold=function(params){var dialog=this;cur_call.sendMethod("verto.modify",{action:"unhold",params:params});};$.verto.dialog.prototype.toggleHold=function(params){var dialog=this;cur_call.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){if(params.useVideo){dialog.useVideo(true);}
+dialog.params.callee_id_name=params.callee_id_name;dialog.params.callee_id_number=params.callee_id_number;}
+dialog.rtc.createAnswer(dialog.params.sdp);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.msg);};$.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},requesting:{trying:1,hangup:1},recovering:{answering:1,hangup:1},trying:{active:1,early:1,hangup:1},ringing:{answering:1,hangup:1},answering:{active:1,hangup:1},active:{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");$.verto.enum=Object.freeze($.verto.enum);$.verto.saved=[];$(window).bind('beforeunload',function(){for(var i in $.verto.saved){var verto=$.verto.saved[i];if(verto){verto.logout();verto.purge();}}
+return $.verto.warnOnUnload;});})(jQuery);
\ No newline at end of file
diff --git a/html5/verto/js/src/jquery.verto.js b/html5/verto/js/src/jquery.verto.js
index 72b2c7dc7e..4530703257 100644
--- a/html5/verto/js/src/jquery.verto.js
+++ b/html5/verto/js/src/jquery.verto.js
@@ -1597,7 +1597,7 @@
dialog.setState($.verto.enum.state.destroy);
break;
case $.verto.enum.state.destroy:
- delete verto.dialogs[dialog.callID];
+ delete dialog.verto.dialogs[dialog.callID];
dialog.rtc.stop();
break;
}