From a03963fb923de1d1353d4bb56fd090bd3f476088 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Sat, 12 Jul 2014 03:27:03 +0500 Subject: [PATCH] fold livetables into verto obj and expose moderator mode --- html5/verto/demo/index.html | 6 +- html5/verto/demo/js/verto-min.js | 28 +- html5/verto/demo/verto.js | 73 ++--- html5/verto/js/src/jquery.FSRTC.js | 2 - html5/verto/js/src/jquery.verto.js | 282 ++++++++++++++++-- .../mod_conference/mod_conference.c | 158 +++++++++- src/mod/endpoints/mod_verto/mod_verto.c | 3 +- src/mod/endpoints/mod_verto/ws.c | 11 +- src/switch_event.c | 1 + 9 files changed, 472 insertions(+), 92 deletions(-) diff --git a/html5/verto/demo/index.html b/html5/verto/demo/index.html index 78bcbe444c..3f665acd42 100644 --- a/html5/verto/demo/index.html +++ b/html5/verto/demo/index.html @@ -73,8 +73,10 @@

-
- +
+
+
+
diff --git a/html5/verto/demo/js/verto-min.js b/html5/verto/demo/js/verto-min.js index 7b2bf2c083..abc2ec45f9 100644 --- a/html5/verto/demo/js/verto-min.js +++ b/html5/verto/demo/js/verto-min.js @@ -34,7 +34,7 @@ getUserMedia({constraints:{audio:true,video:this.options.useVideo?{mandatory:thi function onError(){onStreamError(self);} getUserMedia({constraints:{audio:true,video:this.options.useVideo?{mandatory:this.options.videoParams,optional:[]}:null},video:this.options.useVideo?true:false,onsuccess:onSuccess,onerror:onError});};window.moz=!!navigator.mozGetUserMedia;function RTCPeerConnection(options){var w=window,PeerConnection=w.mozRTCPeerConnection||w.webkitRTCPeerConnection,SessionDescription=w.mozRTCSessionDescription||w.RTCSessionDescription,IceCandidate=w.mozRTCIceCandidate||w.RTCIceCandidate;var STUN={url:!moz?'stun:stun.l.google.com:19302':'stun:23.21.150.121'};var TURN={url:'turn:homeo@turn.bistri.com:80',credential:'homeo'};var iceServers={iceServers:options.iceServers||[STUN]};if(!moz&&!options.iceServers){if(parseInt(navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./)[2])>=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){console.log("WTF ICE",event);if(event.candidate){options.onICE(event.candidate);}else{if(options.onICEComplete){options.onICEComplete();} +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;i0){data.params.useStereo 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&&verto.dialogs[key]){verto.dialogs[key].sendMessage($.verto.enum.message.pvtEvent,data.params);}else if(!list){if(!key){key="UNDEFINED";} +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-1){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":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;} -if(config.onChange){config.onChange(obj,args);}};la.onChange(la,{action:"init"});};$.verto.dialog=function(direction,verto,params){var dialog=this;dialog.params=$.extend({useVideo:verto.options.useVideo,useStereo:verto.options.useStereo,tag:verto.options.tag},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(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 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();});$("#"+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));}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.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("")},4000);}}});} +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":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);}}},});} +$.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;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},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";} diff --git a/html5/verto/demo/verto.js b/html5/verto/demo/verto.js index 1aa29f8558..1dfbeb84c9 100644 --- a/html5/verto/demo/verto.js +++ b/html5/verto/demo/verto.js @@ -1,6 +1,6 @@ 'use strict'; var cur_call = null; -var la = null; +var confMan = null; var $display = $("#display"); var verto; var ringing = false; @@ -9,10 +9,10 @@ function display(msg) { $("#calltitle").html(msg); } -function clearLa() { - if (la) { - la.destroy(); - la = null; +function clearConfMan() { + if (confMan) { + confMan.destroy(); + confMan = null; } $("#conf").hide(); @@ -61,53 +61,21 @@ var callbacks = { console.error("pvtEvent", data.pvtData.action); if (data.pvtData) { switch (data.pvtData.action) { + case "conference-liveArray-part": - clearLa(); + clearConfMan(); break; case "conference-liveArray-join": - - $(".jsDataTable").width(check_vid() ? "650px" : "550px"); - - la = new $.verto.liveTable(verto, data.pvtData.laChannel, data.pvtData.laName, $('#example'), { - subParams: { - callID: dialog.callID - }, - - "onChange": function(obj, args) { - //var len = obj.asArray().length; - $("#mcount").text("Conference Members: " + " (" + obj.arrayLen() + " Total)"); - }, - - "aaData": [], - "aoColumns": [{ - "sTitle": "ID" - }, - { - "sTitle": "Number" - }, - { - "sTitle": "Name" - }, - { - "sTitle": "Codec" - }, - { - "sTitle": "Status", - "sWidth": check_vid() ? "300px" : "150px" - }], - "bAutoWidth": true, - "bDestroy": true, - "bSort": false, - "bInfo": false, - "bFilter": false, - "bLengthChange": false, - "bPaginate": false, - "iDisplayLength": 1000, - - "oLanguage": { - "sEmptyTable": "The Conference is Empty....." - } - }); + clearConfMan(); + confMan = new $.verto.confMan(verto, { + tableID: "#conf_list", + statusID: "#conf_count", + mainModID: "#conf_mod", + displayID: "#conf_display", + dialog: dialog, + hasVid: check_vid(), + laData: data.pvtData + }); $("#conf").show(); @@ -177,7 +145,7 @@ var callbacks = { break; case $.verto.enum.state.hangup: case $.verto.enum.state.destroy: - clearLa(); + clearConfMan(); goto_page("main"); cur_call = null; break; @@ -306,6 +274,8 @@ function pop(id, cname, dft) { function init() { + cur_call = null; + pop("#ext", "verto_demo_ext", "3500"); pop("#name", "verto_demo_name", "FreeSWITCH User"); pop("#cid", "verto_demo_cid", "1008"); @@ -351,8 +321,7 @@ function init() { "minWidth": "1280", "minHeight": "720" } - }, - callbacks); + },callbacks); $("#login").change(function(e) { $("#cid").val(e.currentTarget.value); diff --git a/html5/verto/js/src/jquery.FSRTC.js b/html5/verto/js/src/jquery.FSRTC.js index 28f9306b9e..a90d79feba 100644 --- a/html5/verto/js/src/jquery.FSRTC.js +++ b/html5/verto/js/src/jquery.FSRTC.js @@ -451,8 +451,6 @@ var x = 0; peer.onicecandidate = function(event) { - console.log("WTF ICE", event); - if (event.candidate) { options.onICE(event.candidate); } else { diff --git a/html5/verto/js/src/jquery.verto.js b/html5/verto/js/src/jquery.verto.js index 54e24e4651..4377ae5eef 100644 --- a/html5/verto/js/src/jquery.verto.js +++ b/html5/verto/js/src/jquery.verto.js @@ -219,7 +219,7 @@ } var SERNO = 1; - + function do_subscribe(verto, channel, subChannels, sparams) { var params = sparams || {}; @@ -494,7 +494,11 @@ } } - if (!list && key && verto.dialogs[key]) { + 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) { @@ -855,12 +859,12 @@ var eventHandler = function(v, e, la) { var packet = e.data; + console.error("READ:", packet); + if (packet.name != la.name) { return; } - console.error("READ:", packet); - switch (packet.action) { case "init": @@ -924,19 +928,21 @@ la.verto.unsubscribe(binding); }; - la.bootstrap = function(obj) { + la.sendCommand = function(cmd, obj) { var self = la; - - self.clear(); - self.broadcast(self.context, { - liveArray: { - command: "bootstrap", + 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(); }; @@ -1035,6 +1041,10 @@ } } + if (config.onChange) { + config.onChange(obj, args); + } + try { switch (args.action) { case "bootObj": @@ -1102,11 +1112,7 @@ } else { obj.errs = 0; } - - if (config.onChange) { - config.onChange(obj, args); - } - + }; la.onChange(la, { @@ -1115,6 +1121,248 @@ }; + 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 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(); + }); + + $("#" + 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)); + } 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.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("")}, 4000); + } + + } + }); + + } + + 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": 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); + } + + } + }, + + }); + } + + $.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; + + 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; @@ -1303,7 +1551,7 @@ dialog.setState($.verto.enum.state.destroy); break; case $.verto.enum.state.destroy: - delete verto.dialogs[dialog.callID]; + delete verto.dialogs[dialog.callID]; dialog.rtc.stop(); break; } diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c index 6ce838f352..a4ac240577 100644 --- a/src/mod/applications/mod_conference/mod_conference.c +++ b/src/mod/applications/mod_conference/mod_conference.c @@ -343,6 +343,7 @@ typedef struct conference_obj { char *name; char *la_name; char *la_event_channel; + char *mod_event_channel; char *desc; char *timer_name; char *tts_engine; @@ -1517,6 +1518,102 @@ static cJSON *conference_json_render(conference_obj_t *conference, cJSON *req) return json; } +static void conference_mod_event_channel_handler(const char *event_channel, cJSON *json, const char *key, switch_event_channel_id_t id) +{ + cJSON *data; + const char *action = NULL; + char *value = NULL; + cJSON *jid = 0; + char *conf_name = strdup(event_channel + 15); + int cid = 0; + char *p; + switch_stream_handle_t stream = { 0 }; + char *exec = NULL; + cJSON *msg, *jdata, *jvalue; + char *argv[10] = {0}; + int argc = 0; + + if (conf_name && (p = strchr(conf_name, '@'))) { + *p = '\0'; + } + + if ((data = cJSON_GetObjectItem(json, "data"))) { + action = cJSON_GetObjectCstr(data, "command"); + if ((jid = cJSON_GetObjectItem(data, "id"))) { + cid = jid->valueint; + } + + if ((jvalue = cJSON_GetObjectItem(data, "value"))) { + + if (jvalue->type == cJSON_Array) { + int i; + argc = cJSON_GetArraySize(jvalue); + if (argc > 10) argc = 10; + + for (i = 0; i < argc; i++) { + cJSON *str = cJSON_GetArrayItem(jvalue, i); + if (str->type == cJSON_String) { + argv[i] = str->valuestring; + } + } + } else if (jvalue->type == cJSON_String) { + value = jvalue->valuestring; + argv[argc++] = value; + } + } + } + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ALERT, "conf %s CMD %s [%s] %d\n", conf_name, key, action, cid); + + if (zstr(action)) { + goto end; + } + + SWITCH_STANDARD_STREAM(stream); + + if (!strcasecmp(action, "kick") || !strcasecmp(action, "mute") || !strcasecmp(action, "unmute") || !strcasecmp(action, "tmute")) { + exec = switch_mprintf("%s %s %d", conf_name, action, cid); + } else if (!strcasecmp(action, "volume_in") || !strcasecmp(action, "volume_out")) { + exec = switch_mprintf("%s %s %d %s", conf_name, action, cid, argv[0]); + } else if (!strcasecmp(action, "play") || !strcasecmp(action, "stop")) { + exec = switch_mprintf("%s %s %s", conf_name, action, argv[0]); + } else if (!strcasecmp(action, "recording")) { + if (!argv[1]) { + argv[1] = "all"; + } + exec = switch_mprintf("%s %s %s %s", conf_name, action, argv[0], argv[1]); + } + + if (exec) { + conf_api_main(exec, NULL, &stream); + } + + end: + + msg = cJSON_CreateObject(); + jdata = json_add_child_obj(msg, "data", NULL); + + cJSON_AddItemToObject(msg, "eventChannel", cJSON_CreateString(event_channel)); + cJSON_AddItemToObject(jdata, "action", cJSON_CreateString("response")); + + 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); + } else { + cJSON_AddItemToObject(jdata, "error", cJSON_CreateString("Invalid Command")); + } + + switch_event_channel_broadcast(event_channel, &msg, __FILE__, globals.event_channel_id); + + + switch_safe_free(stream.data); + switch_safe_free(exec); + + switch_safe_free(conf_name); + +} + static void conference_la_event_channel_handler(const char *event_channel, cJSON *json, const char *key, switch_event_channel_id_t id) { switch_live_array_parse_json(json, globals.event_channel_id); @@ -1995,22 +2092,28 @@ static void adv_la(conference_obj_t *conference, conference_member_t *member, sw cJSON *msg, *data; const char *uuid = switch_core_session_get_uuid(member->session); const char *cookie = switch_channel_get_variable(member->channel, "event_channel_cookie"); + const char *event_channel = cookie ? cookie : uuid; msg = cJSON_CreateObject(); data = json_add_child_obj(msg, "pvtData", NULL); - cJSON_AddItemToObject(msg, "eventChannel", cJSON_CreateString(uuid)); + cJSON_AddItemToObject(msg, "eventChannel", cJSON_CreateString(event_channel)); cJSON_AddItemToObject(msg, "eventType", cJSON_CreateString("channelPvtData")); cJSON_AddItemToObject(data, "action", cJSON_CreateString(join ? "conference-liveArray-join" : "conference-liveArray-part")); cJSON_AddItemToObject(data, "laChannel", cJSON_CreateString(conference->la_event_channel)); cJSON_AddItemToObject(data, "laName", cJSON_CreateString(conference->la_name)); + cJSON_AddItemToObject(data, "role", cJSON_CreateString(switch_test_flag(member, MFLAG_MOD) ? "moderator" : "participant")); + if (switch_test_flag(member, MFLAG_MOD)) { + cJSON_AddItemToObject(data, "modChannel", cJSON_CreateString(conference->mod_event_channel)); + } + + switch_event_channel_broadcast(event_channel, &msg, modname, globals.event_channel_id); if (cookie) { switch_event_channel_permission_modify(cookie, conference->la_event_channel, join); + switch_event_channel_permission_modify(cookie, conference->mod_event_channel, join); } - - switch_event_channel_broadcast(uuid, &msg, modname, globals.event_channel_id); } } @@ -2279,8 +2382,14 @@ static switch_status_t conference_add_member(conference_obj_t *conference, confe switch_channel_get_variable(member->channel, "original_read_rate") )); + + + member->status_field = cJSON_CreateString(""); cJSON_AddItemToArray(member->json, member->status_field); + + cJSON_AddItemToArray(member->json, cJSON_CreateNull()); + member_update_status_field(member); //switch_live_array_add_alias(conference->la, switch_core_session_get_uuid(member->session), "conference"); adv_la(conference, member, SWITCH_TRUE); @@ -2875,7 +2984,6 @@ static void *SWITCH_THREAD_FUNC conference_video_thread_run(switch_thread_t *thr static void conference_command_handler(switch_live_array_t *la, const char *cmd, const char *sessid, cJSON *jla, void *user_data) { - } /* Main monitor thread (1 per distinct conference room) */ @@ -2930,8 +3038,10 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v if (strchr(conference->name, '@')) { conference->la_event_channel = switch_core_sprintf(conference->pool, "conference-liveArray.%s", conference->name); + conference->mod_event_channel = switch_core_sprintf(conference->pool, "conference-mod.%s", conference->name); } else { conference->la_event_channel = switch_core_sprintf(conference->pool, "conference-liveArray.%s@%s", conference->name, conference->domain); + conference->mod_event_channel = switch_core_sprintf(conference->pool, "conference-mod.%s@%s", conference->name, conference->domain); } conference->la_name = switch_core_strdup(conference->pool, conference->name); @@ -6279,7 +6389,19 @@ static switch_status_t conf_api_sub_energy(conference_member_t *member, switch_s if (data) { lock_member(member); - member->energy_level = atoi((char *) data); + if (!strcasecmp(data, "up")) { + member->energy_level += 200; + if (member->energy_level > 1800) { + member->energy_level = 1800; + } + } else if (!strcasecmp(data, "down")) { + member->energy_level -= 200; + if (member->energy_level < 0) { + member->energy_level = 0; + } + } else { + member->energy_level = atoi((char *) data); + } unlock_member(member); } if (stream != NULL) { @@ -6397,9 +6519,18 @@ static switch_status_t conf_api_sub_volume_in(conference_member_t *member, switc if (data) { lock_member(member); - member->volume_in_level = atoi((char *) data); - switch_normalize_volume(member->volume_in_level); + if (!strcasecmp(data, "up")) { + member->volume_in_level++; + switch_normalize_volume(member->volume_in_level); + } else if (!strcasecmp(data, "down")) { + member->volume_in_level--; + switch_normalize_volume(member->volume_in_level); + } else { + member->volume_in_level = atoi((char *) data); + switch_normalize_volume(member->volume_in_level); + } unlock_member(member); + } if (stream != NULL) { stream->write_function(stream, "Volume IN %u = %d\n", member->id, member->volume_in_level); @@ -6424,8 +6555,16 @@ static switch_status_t conf_api_sub_volume_out(conference_member_t *member, swit if (data) { lock_member(member); - member->volume_out_level = atoi((char *) data); - switch_normalize_volume(member->volume_out_level); + if (!strcasecmp(data, "up")) { + member->volume_out_level++; + switch_normalize_volume(member->volume_out_level); + } else if (!strcasecmp(data, "down")) { + member->volume_out_level--; + switch_normalize_volume(member->volume_out_level); + } else { + member->volume_out_level = atoi((char *) data); + switch_normalize_volume(member->volume_out_level); + } unlock_member(member); } if (stream != NULL) { @@ -10752,6 +10891,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_conference_load) switch_event_channel_bind("conference", conference_event_channel_handler, &globals.event_channel_id); switch_event_channel_bind("conference-liveArray", conference_la_event_channel_handler, &globals.event_channel_id); + switch_event_channel_bind("conference-mod", conference_mod_event_channel_handler, &globals.event_channel_id); /* build api interface help ".syntax" field string */ p = strdup(""); diff --git a/src/mod/endpoints/mod_verto/mod_verto.c b/src/mod/endpoints/mod_verto/mod_verto.c index ffa95cd546..8de51dc5b2 100644 --- a/src/mod/endpoints/mod_verto/mod_verto.c +++ b/src/mod/endpoints/mod_verto/mod_verto.c @@ -3861,6 +3861,7 @@ static switch_call_cause_t verto_outgoing_channel(switch_core_session_t *session switch_channel_set_variable(channel, "jsock_uuid_str", tech_pvt->jsock_uuid); switch_channel_set_variable(channel, "event_channel_cookie", tech_pvt->jsock_uuid); + if ((caller_profile = switch_caller_profile_dup(switch_core_session_get_pool(*new_session), outbound_profile))) { switch_channel_set_caller_profile(channel, caller_profile); } @@ -3880,7 +3881,7 @@ static switch_call_cause_t verto_outgoing_channel(switch_core_session_t *session void verto_broadcast(const char *event_channel, cJSON *json, const char *key, switch_event_channel_id_t id) { - if (globals.debug > 10) { + if (globals.debug > 9) { char *json_text; if ((json_text = cJSON_Print(json))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ALERT, "EVENT BROADCAST %s %s\n", event_channel, json_text); diff --git a/src/mod/endpoints/mod_verto/ws.c b/src/mod/endpoints/mod_verto/ws.c index 11b92945c8..0ee867dba5 100644 --- a/src/mod/endpoints/mod_verto/ws.c +++ b/src/mod/endpoints/mod_verto/ws.c @@ -368,18 +368,25 @@ ssize_t ws_raw_read(wsh_t *wsh, void *data, size_t bytes, int block) ssize_t ws_raw_write(wsh_t *wsh, void *data, size_t bytes) { size_t r; + int sanity = 2000; if (wsh->ssl) { do { r = SSL_write(wsh->ssl, data, bytes); - } while (r == -1 && SSL_get_error(wsh->ssl, r) == SSL_ERROR_WANT_WRITE); + if (sanity < 2000) { + ms_sleep(1); + } + } while (--sanity > 0 && r == -1 && SSL_get_error(wsh->ssl, r) == SSL_ERROR_WANT_WRITE); return r; } do { r = send(wsh->sock, data, bytes, 0); - } while (r == -1 && xp_is_blocking(xp_errno())); + if (sanity < 2000) { + ms_sleep(1); + } + } while (--sanity > 0 && r == -1 && xp_is_blocking(xp_errno())); //if (r<0) { //printf("wRITE FAIL: %s\n", strerror(errno)); diff --git a/src/switch_event.c b/src/switch_event.c index a2a68fdb68..b108ac1be5 100644 --- a/src/switch_event.c +++ b/src/switch_event.c @@ -2823,6 +2823,7 @@ static uint32_t _switch_event_channel_broadcast(const char *event_channel, const if (np->id == id) { continue; } + np->func(broadcast_channel, json, key, id); x++; }