FS-9576 #resolve [Add Realtime Text]

This commit is contained in:
Anthony Minessale 2016-07-10 22:25:14 -05:00
parent 25732c82d2
commit c409499cd9
46 changed files with 2834 additions and 173 deletions

View File

@ -3,9 +3,9 @@
# Must change all of the below together
# For a release, set revision for that tagged release as well and uncomment
AC_INIT([freeswitch], [1.7.0], bugs@freeswitch.org)
AC_INIT([freeswitch], [1.9.0], bugs@freeswitch.org)
AC_SUBST(SWITCH_VERSION_MAJOR, [1])
AC_SUBST(SWITCH_VERSION_MINOR, [7])
AC_SUBST(SWITCH_VERSION_MINOR, [9])
AC_SUBST(SWITCH_VERSION_MICRO, [0])
AC_SUBST(SWITCH_VERSION_REVISION, [])
AC_SUBST(SWITCH_VERSION_REVISION_HUMAN, [])

View File

@ -2062,12 +2062,18 @@
obj.dialogParams = {};
for (var i in dialog.params) {
if (i == "sdp" && method != "verto.invite" && method != "verto.attach") {
if (i == "sdp" && method != "verto.invite" && method != "verto.attach") {
continue;
}
}
if ((obj.noDialogParams && i != "callID")) {
continue;
}
obj.dialogParams[i] = dialog.params[i];
obj.dialogParams[i] = dialog.params[i];
}
delete obj.noDialogParams;
dialog.verto.rpcClient.call(method, obj,
@ -2371,6 +2377,26 @@
}
};
$.verto.dialog.prototype.rtt = function(obj) {
var dialog = this;
var pobj = {};
if (!obj) {
return false;
}
pobj.code = obj.code;
pobj.chars = obj.chars;
if (pobj.chars || pobj.code) {
dialog.sendMethod("verto.info", {
txt: obj,
noDialogParams: true
});
}
};
$.verto.dialog.prototype.transfer = function(dest, params) {
var dialog = this;
if (dest) {
@ -2517,7 +2543,8 @@
$.verto.dialog.prototype.handleInfo = function(params) {
var dialog = this;
dialog.sendMessage($.verto.enum.message.info, params.msg);
dialog.sendMessage($.verto.enum.message.info, params);
};
$.verto.dialog.prototype.handleDisplay = function(params) {

View File

@ -244,6 +244,14 @@ div#preload { display: none; }
<video id="webcam" autoplay="autoplay" style="width:100%;height:100%;object-fit:inherit;"></video>
<br><br>
<table><tr><td>
<div style="width:500px;max-height:300px;overflow-y:scroll;display:block;unicode-bidi:embed;font-family:tahoma;white-space:pre;size:14pt;text-align:left" id="rtt_in"></div>
</td></tr>
<tr><td>
<textarea style="width:500px;height:200px" id="rtt"></textarea>
</td></tr>
</table>
<!--<video id="local_webcam" autoplay="autoplay" style="width:100%;height:100%;object-fit:inherit;"></video>-->
</div><!-- rows -->

View File

@ -255,8 +255,9 @@ if(!dialog.params.remote_caller_id_number){dialog.params.remote_caller_id_number
RTCcallbacks.onMessage=function(rtc,msg){console.debug(msg);};RTCcallbacks.onAnswerSDP=function(rtc,sdp){console.error("answer sdp",sdp);};}else{dialog.params.remote_caller_id_name="Outbound Call";dialog.params.remote_caller_id_number=dialog.params.destination_number;}
RTCcallbacks.onICESDP=function(rtc){console.log("RECV "+rtc.type+" SDP",rtc.mediaData.SDP);if(dialog.state==$.verto.enum.state.requesting||dialog.state==$.verto.enum.state.answering||dialog.state==$.verto.enum.state.active){location.reload();return;}
if(rtc.type=="offer"){if(dialog.state==$.verto.enum.state.active){dialog.setState($.verto.enum.state.requesting);dialog.sendMethod("verto.attach",{sdp:rtc.mediaData.SDP});}else{dialog.setState($.verto.enum.state.requesting);dialog.sendMethod("verto.invite",{sdp:rtc.mediaData.SDP});}}else{dialog.setState($.verto.enum.state.answering);dialog.sendMethod(dialog.attach?"verto.attach":"verto.answer",{sdp:dialog.rtc.mediaData.SDP});}};RTCcallbacks.onICE=function(rtc){if(rtc.type=="offer"){console.log("offer",rtc.mediaData.candidate);return;}};RTCcallbacks.onStream=function(rtc,stream){console.log("stream started");};RTCcallbacks.onError=function(e){console.error("ERROR:",e);dialog.hangup({cause:"Device or Permission Error"});};dialog.rtc=new $.FSRTC({callbacks:RTCcallbacks,localVideo:dialog.screenShare?null:dialog.localVideo,useVideo:dialog.params.useVideo?dialog.videoStream:null,useAudio:dialog.audioStream,useStereo:dialog.params.useStereo,videoParams:dialog.params.videoParams,audioParams:verto.options.audioParams,iceServers:verto.options.iceServers,screenShare:dialog.screenShare,useCamera:dialog.useCamera,useMic:dialog.useMic,useSpeak:dialog.useSpeak});dialog.rtc.verto=dialog.verto;if(dialog.direction==$.verto.enum.direction.inbound){if(dialog.attach){dialog.answer();}else{dialog.ring();}}};$.verto.dialog.prototype.invite=function(){var dialog=this;dialog.rtc.call();};$.verto.dialog.prototype.sendMethod=function(method,obj){var dialog=this;obj.dialogParams={};for(var i in dialog.params){if(i=="sdp"&&method!="verto.invite"&&method!="verto.attach"){continue;}
if((obj.noDialogParams&&i!="callID")){continue;}
obj.dialogParams[i]=dialog.params[i];}
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;}
delete obj.noDialogParams;dialog.verto.rpcClient.call(method,obj,function(e){dialog.processReply(method,true,e);},function(e){dialog.processReply(method,false,e);});};function checkStateChange(oldS,newS){if(newS==$.verto.enum.state.purge||$.verto.enum.states[oldS.name][newS.name]){return true;}
return false;}
function find_name(id){for(var i in $.verto.audioOutDevices){var source=$.verto.audioOutDevices[i];if(source.id===id){return(source.label);}}
return id;}
@ -280,7 +281,8 @@ 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,dialog.localVideo);};$.verto.dialog.prototype.setMute=function(what){var dialog=this;return dialog.rtc.setMute(what);};$.verto.dialog.prototype.getMute=function(){var dialog=this;return dialog.rtc.getMute();};$.verto.dialog.prototype.setVideoMute=function(what){var dialog=this;return dialog.rtc.setVideoMute(what);};$.verto.dialog.prototype.getVideoMute=function(){var dialog=this;return dialog.rtc.getVideoMute();};$.verto.dialog.prototype.useStereo=function(on){var dialog=this;dialog.params.useStereo=on;dialog.rtc.useStereo(on);};$.verto.dialog.prototype.dtmf=function(digits){var dialog=this;if(digits){dialog.sendMethod("verto.info",{dtmf:digits});}};$.verto.dialog.prototype.transfer=function(dest,params){var dialog=this;if(dest){dialog.sendMethod("verto.modify",{action:"transfer",destination:dest,params:params});}};$.verto.dialog.prototype.hold=function(params){var dialog=this;dialog.sendMethod("verto.modify",{action:"hold",params:params});};$.verto.dialog.prototype.unhold=function(params){var dialog=this;dialog.sendMethod("verto.modify",{action:"unhold",params:params});};$.verto.dialog.prototype.toggleHold=function(params){var dialog=this;dialog.sendMethod("verto.modify",{action:"toggleHold",params:params});};$.verto.dialog.prototype.message=function(msg){var dialog=this;var err=0;msg.from=dialog.params.login;if(!msg.to){console.error("Missing To");err++;}
dialog.rtc.useVideo(dialog.videoStream,dialog.localVideo);};$.verto.dialog.prototype.setMute=function(what){var dialog=this;return dialog.rtc.setMute(what);};$.verto.dialog.prototype.getMute=function(){var dialog=this;return dialog.rtc.getMute();};$.verto.dialog.prototype.setVideoMute=function(what){var dialog=this;return dialog.rtc.setVideoMute(what);};$.verto.dialog.prototype.getVideoMute=function(){var dialog=this;return dialog.rtc.getVideoMute();};$.verto.dialog.prototype.useStereo=function(on){var dialog=this;dialog.params.useStereo=on;dialog.rtc.useStereo(on);};$.verto.dialog.prototype.dtmf=function(digits){var dialog=this;if(digits){dialog.sendMethod("verto.info",{dtmf:digits});}};$.verto.dialog.prototype.rtt=function(obj){var dialog=this;var pobj={};if(!obj){return false;}
pobj.code=obj.code;pobj.chars=obj.chars;if(pobj.chars||pobj.code){dialog.sendMethod("verto.info",{txt:obj,noDialogParams:true});}};$.verto.dialog.prototype.transfer=function(dest,params){var dialog=this;if(dest){dialog.sendMethod("verto.modify",{action:"transfer",destination:dest,params:params});}};$.verto.dialog.prototype.hold=function(params){var dialog=this;dialog.sendMethod("verto.modify",{action:"hold",params:params});};$.verto.dialog.prototype.unhold=function(params){var dialog=this;dialog.sendMethod("verto.modify",{action:"unhold",params:params});};$.verto.dialog.prototype.toggleHold=function(params){var dialog=this;dialog.sendMethod("verto.modify",{action:"toggleHold",params:params});};$.verto.dialog.prototype.message=function(msg){var dialog=this;var err=0;msg.from=dialog.params.login;if(!msg.to){console.error("Missing To");err++;}
if(!msg.body){console.error("Missing Body");err++;}
if(err){return false;}
dialog.sendMethod("verto.info",{msg:msg});return true;};$.verto.dialog.prototype.answer=function(params){var dialog=this;if(!dialog.answered){if(!params){params={};}
@ -289,7 +291,7 @@ dialog.params.callee_id_name=params.callee_id_name;dialog.params.callee_id_numbe
if(params.useMic){dialog.useMic=params.useMic;}
if(params.useSpeak){dialog.useSpeak=params.useSpeak;}}
dialog.rtc.createAnswer(params);dialog.answered=true;}};$.verto.dialog.prototype.handleAnswer=function(params){var dialog=this;dialog.gotAnswer=true;if(dialog.state.val>=$.verto.enum.state.active.val){return;}
if(dialog.state.val>=$.verto.enum.state.early.val){dialog.setState($.verto.enum.state.active);}else{if(dialog.gotEarly){console.log("Dialog "+dialog.callID+" Got answer while still establishing early media, delaying...");}else{console.log("Dialog "+dialog.callID+" Answering Channel");dialog.rtc.answer(params.sdp,function(){dialog.setState($.verto.enum.state.active);},function(e){console.error(e);dialog.hangup();});console.log("Dialog "+dialog.callID+"ANSWER SDP",params.sdp);}}};$.verto.dialog.prototype.cidString=function(enc){var dialog=this;var party=dialog.params.remote_caller_id_name+(enc?" &lt;":" <")+dialog.params.remote_caller_id_number+(enc?"&gt;":">");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(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?" &lt;":" <")+dialog.params.remote_caller_id_number+(enc?"&gt;":">");return party;};$.verto.dialog.prototype.sendMessage=function(msg,params){var dialog=this;if(dialog.callbacks.onMessage){dialog.callbacks.onMessage(dialog.verto,dialog,msg,params);}};$.verto.dialog.prototype.handleInfo=function(params){var dialog=this;dialog.sendMessage($.verto.enum.message.info,params);};$.verto.dialog.prototype.handleDisplay=function(params){var dialog=this;if(params.display_name){dialog.params.remote_caller_id_name=params.display_name;}
if(params.display_number){dialog.params.remote_caller_id_number=params.display_number;}
dialog.sendMessage($.verto.enum.message.display,{});};$.verto.dialog.prototype.handleMedia=function(params){var dialog=this;if(dialog.state.val>=$.verto.enum.state.early.val){return;}
dialog.gotEarly=true;dialog.rtc.answer(params.sdp,function(){console.log("Dialog "+dialog.callID+"Establishing early media");dialog.setState($.verto.enum.state.early);if(dialog.gotAnswer){console.log("Dialog "+dialog.callID+"Answering Channel");dialog.setState($.verto.enum.state.active);}},function(e){console.error(e);dialog.hangup();});console.log("Dialog "+dialog.callID+"EARLY SDP",params.sdp);};$.verto.ENUM=function(s){var i=0,o={};s.split(" ").map(function(x){o[x]={name:x,val:i++};});return Object.freeze(o);};$.verto.enum={};$.verto.enum.states=Object.freeze({new:{requesting:1,recovering:1,ringing:1,destroy:1,answering:1,hangup:1},requesting:{trying:1,hangup:1,active:1},recovering:{answering:1,hangup:1},trying:{active:1,early:1,hangup:1},ringing:{answering:1,hangup:1},answering:{active:1,hangup:1},active:{answering:1,requesting:1,hangup:1,held:1},held:{hangup:1,active:1},early:{hangup:1,active:1},hangup:{destroy:1},destroy:{},purge:{destroy:1}});$.verto.enum.state=$.verto.ENUM("new requesting trying recovering ringing answering early active held hangup destroy purge");$.verto.enum.direction=$.verto.ENUM("inbound outbound");$.verto.enum.message=$.verto.ENUM("display info pvtEvent");$.verto.enum=Object.freeze($.verto.enum);$.verto.saved=[];$.verto.unloadJobs=[];$(window).bind('beforeunload',function(){for(var f in $.verto.unloadJobs){$.verto.unloadJobs[f]();}

View File

@ -403,41 +403,67 @@ var callbacks = {
}
break;
case $.verto.enum.message.info:
var body = data.body;
if (data.msg) {
data = data.msg;
var body = data.body;
/*
// This section has been replaced with messageTextToJQ function
if (body.match(/\.gif|\.jpg|\.jpeg|\.png/)) {
if (body.match(/\.gif|\.jpg|\.jpeg|\.png/)) {
var mod = "";
if (body.match(/dropbox.com/)) {
mod = "?dl=1";
mod = "?dl=1";
}
body = body.replace(/(http[s]{0,1}:\/\/\S+)/g, "<a target='_blank' href='$1'>$1<br><img border='0' class='chatimg' src='$1'" + mod + "><\/a>");
} else {
} else {
body = body.replace(/(http[s]{0,1}:\/\/\S+)/g, "<a target='_blank' href='$1'>$1<\/a>");
}
}
if (body.slice(-1) !== "\n") {
if (body.slice(-1) !== "\n") {
body += "\n";
}
body = body.replace(/(?:\r\n|\r|\n)/g, '<br />');
var from = data.from_msg_name || data.from;
}
body = body.replace(/(?:\r\n|\r|\n)/g, '<br />');
var from = data.from_msg_name || data.from;
$("#chatwin").append("<span class=chatuid>" + from + ":</span><br>" + body);
$('#chatwin').animate({"scrollTop": $('#chatwin')[0].scrollHeight}, "fast");
$("#chatwin").append("<span class=chatuid>" + from + ":</span><br>" + body);
$('#chatwin').animate({"scrollTop": $('#chatwin')[0].scrollHeight}, "fast");
*/
var from = data.from_msg_name || data.from;
$('#chatwin')
.append($('<span class="chatuid" />').text(from + ':'))
.append($('<br />'))
.append(messageTextToJQ(body))
.append($('<br />'));
$('#chatwin').animate({"scrollTop": $('#chatwin')[0].scrollHeight}, "fast");
var from = data.from_msg_name || data.from;
$('#chatwin')
.append($('<span class="chatuid" />').text(from + ':'))
.append($('<br />'))
.append(messageTextToJQ(body))
.append($('<br />'));
$('#chatwin').animate({"scrollTop": $('#chatwin')[0].scrollHeight}, "fast");
}
if (data.txt) {
console.log(data.txt);
if (data.txt.chars) {
var a = [...data.txt.chars];
//console.log(a);
for (var x in a) {
if(a[x] == "\r") {
$("#rtt_in").append("\n");
continue;
} else if (a[x] == "\b") {
$("#rtt_in").text($("#rtt_in").text().slice(0, -1));
continue;
}
console.log("[" + a[x] + "]");
$("#rtt_in").append(a[x]);
}
var psconsole = $('#rtt_in');
if(psconsole.length)
psconsole.scrollTop(psconsole[0].scrollHeight - psconsole.height());
}
}
break;
case $.verto.enum.message.display:
var party = dialog.params.remote_caller_id_name + "<" + dialog.params.remote_caller_id_number + ">";
@ -1558,6 +1584,30 @@ function init() {
setupChat();
$("#rtt").val("");
$("#rtt_in").text("");
$("#rtt").keyup(function (event) {
console.error(event);
console.log("KEY (" + event.which + ")\n");
if (event.which == 8) {
cur_call.rtt({code: event.which});
}
if (event.which == 13) {
$("#rtt").val("");
}
});
$("#rtt").keypress(function (event) {
console.error(event);
console.log("TEXT (" + event.which + ")\n");
cur_call.rtt({code: event.which});
});
$("#ext").keyup(function (event) {
if (event.keyCode == 13) {
$( "#callbtn" ).trigger( "click" );

View File

@ -147,6 +147,7 @@ static const char *EVENT_NAMES[] = {
"CALL_SETUP_RESULT",
"CALL_DETAIL",
"DEVICE_STATE",
"REAL_TIME_TEXT",
"ALL"
};

View File

@ -137,6 +137,7 @@ typedef enum {
ESL_EVENT_CALL_SETUP_RESULT,
ESL_EVENT_CALL_DETAIL,
ESL_EVENT_DEVICE_STATE,
ESL_EVENT_REAL_TIME_TEXT,
ESL_EVENT_ALL
} esl_event_types_t;

View File

@ -85,7 +85,7 @@
media = 1*(alpha-numeric)
;typically "audio", "video", "application"
;or "data"
;or "data" or "text"
fmt = 1*(alpha-numeric)
;typically an RTP payload type for audio

View File

@ -1275,7 +1275,7 @@ static void parse_media(sdp_parser_t *p, char *r, sdp_media_t **result)
media = token
;typically "audio", "video", "application"
;or "data"
;or "data" or "text"
fmt = token
;typically an RTP payload type for audio
@ -1378,6 +1378,8 @@ void sdp_media_type(sdp_media_t *m, char const *s)
m->m_type = sdp_media_image, m->m_type_name = "image";
else if (su_casematch(s, "red"))
m->m_type = sdp_media_red, m->m_type_name = "red";
else if (su_casematch(s, "text"))
m->m_type = sdp_media_text, m->m_type_name = "text";
else
m->m_type = sdp_media_x, m->m_type_name = s;
}

View File

@ -583,6 +583,7 @@ static void print_media(sdp_printer_t *p,
case sdp_media_control: media = "control"; break;
case sdp_media_message: media = "message"; break;
case sdp_media_image : media = "image"; break;
case sdp_media_text : media = "text"; break;
default: media = m->m_type_name;
}

View File

@ -232,7 +232,8 @@ typedef enum
sdp_media_message, /**< Messaging sessions*/
sdp_media_image, /**< Image browsing sessions,
* e.g., JPIP or T.38. */
sdp_media_red /**< Redundancy. @NEW_1_12_4. */
sdp_media_red, /**< Redundancy. @NEW_1_12_4. */
sdp_media_text, /**< Realtime Text */
} sdp_media_e;
/** Media transport protocol. */

View File

@ -189,7 +189,13 @@ struct switch_core_session {
uint32_t decoder_errors;
switch_core_video_thread_callback_func_t video_read_callback;
void *video_read_user_data;
switch_core_video_thread_callback_func_t text_read_callback;
void *text_read_user_data;
switch_io_routines_t *io_override;
switch_slin_data_t *sdata;
switch_buffer_t *text_buffer;
switch_mutex_t *text_mutex;
};
struct switch_media_bug {
@ -228,6 +234,11 @@ struct switch_media_bug {
switch_image_t *spy_img[2];
switch_vid_spy_fmt_t spy_fmt;
switch_thread_t *video_bug_thread;
switch_buffer_t *text_buffer;
char *text_framedata;
uint32_t text_framesize;
struct switch_media_bug *next;
};

View File

@ -162,6 +162,8 @@ SWITCH_DECLARE(void) switch_buffer_destroy(switch_buffer_t **buffer);
SWITCH_DECLARE(switch_size_t) switch_buffer_zwrite(_In_ switch_buffer_t *buffer, _In_bytecount_(datalen)
const void *data, _In_ switch_size_t datalen);
SWITCH_DECLARE(void *) switch_buffer_get_head_pointer(switch_buffer_t *buffer);
/** @} */
SWITCH_END_EXTERN_C

View File

@ -317,6 +317,11 @@ SWITCH_DECLARE(switch_status_t) switch_channel_get_variables(switch_channel_t *c
SWITCH_DECLARE(switch_status_t) switch_channel_pass_callee_id(switch_channel_t *channel, switch_channel_t *other_channel);
static inline int switch_channel_var_true(switch_channel_t *channel, const char *variable) {
return switch_true(switch_channel_get_variable_dup(channel, variable, SWITCH_FALSE, -1));
}
/*!
* \brief Start iterating over the entries in the channel variable list.
* \param channel the channel to iterate the variables for

View File

@ -351,6 +351,8 @@ SWITCH_DECLARE(void) switch_core_media_bug_set_read_demux_frame(_In_ switch_medi
*/
SWITCH_DECLARE(switch_core_session_t *) switch_core_media_bug_get_session(_In_ switch_media_bug_t *bug);
SWITCH_DECLARE(const char *) switch_core_media_bug_get_text(switch_media_bug_t *bug);
/*!
\brief Test for the existance of a flag on an media bug
\param bug the object to test
@ -1163,6 +1165,8 @@ SWITCH_DECLARE(void *) switch_core_session_get_stream(_In_ switch_core_session_t
*/
SWITCH_DECLARE(int) switch_core_session_get_stream_count(_In_ switch_core_session_t *session);
SWITCH_DECLARE(const char *) switch_core_session_get_text_buffer(switch_core_session_t *session);
/*!
\brief Launch a thread designed to exist within the scope of a given session
\param session a session to allocate the thread from
@ -2741,6 +2745,8 @@ SWITCH_DECLARE(int) switch_stream_system(const char *cmd, switch_stream_handle_t
SWITCH_DECLARE(switch_call_direction_t) switch_ice_direction(switch_core_session_t *session);
SWITCH_DECLARE(void) switch_core_session_debug_pool(switch_stream_handle_t *stream);
SWITCH_DECLARE(switch_status_t) switch_core_session_override_io_routines(switch_core_session_t *session, switch_io_routines_t *ior);
SWITCH_DECLARE(const char *)switch_version_major(void);
SWITCH_DECLARE(const char *)switch_version_minor(void);
SWITCH_DECLARE(const char *)switch_version_micro(void);
@ -2752,6 +2758,9 @@ SWITCH_DECLARE(const char *)switch_version_full_human(void);
SWITCH_DECLARE(void) switch_core_autobind_cpu(void);
SWITCH_DECLARE(switch_status_t) switch_core_session_start_text_thread(switch_core_session_t *session);
SWITCH_END_EXTERN_C
#endif
/* For Emacs:

View File

@ -41,6 +41,8 @@ typedef struct switch_io_event_hook_read_frame switch_io_event_hook_read_frame_t
typedef struct switch_io_event_hook_video_read_frame switch_io_event_hook_video_read_frame_t;
typedef struct switch_io_event_hook_write_frame switch_io_event_hook_write_frame_t;
typedef struct switch_io_event_hook_video_write_frame switch_io_event_hook_video_write_frame_t;
typedef struct switch_io_event_hook_text_read_frame switch_io_event_hook_text_read_frame_t;
typedef struct switch_io_event_hook_text_write_frame switch_io_event_hook_text_write_frame_t;
typedef struct switch_io_event_hook_kill_channel switch_io_event_hook_kill_channel_t;
typedef struct switch_io_event_hook_send_dtmf switch_io_event_hook_send_dtmf_t;
typedef struct switch_io_event_hook_recv_dtmf switch_io_event_hook_recv_dtmf_t;
@ -54,6 +56,8 @@ typedef switch_status_t (*switch_read_frame_hook_t) (switch_core_session_t *, sw
typedef switch_status_t (*switch_video_read_frame_hook_t) (switch_core_session_t *, switch_frame_t **, switch_io_flag_t, int);
typedef switch_status_t (*switch_write_frame_hook_t) (switch_core_session_t *, switch_frame_t *, switch_io_flag_t, int);
typedef switch_status_t (*switch_video_write_frame_hook_t) (switch_core_session_t *, switch_frame_t *, switch_io_flag_t, int);
typedef switch_status_t (*switch_text_read_frame_hook_t) (switch_core_session_t *, switch_frame_t **, switch_io_flag_t, int);
typedef switch_status_t (*switch_text_write_frame_hook_t) (switch_core_session_t *, switch_frame_t *, switch_io_flag_t, int);
typedef switch_status_t (*switch_kill_channel_hook_t) (switch_core_session_t *, int);
typedef switch_status_t (*switch_send_dtmf_hook_t) (switch_core_session_t *, const switch_dtmf_t *, switch_dtmf_direction_t direction);
typedef switch_status_t (*switch_recv_dtmf_hook_t) (switch_core_session_t *, const switch_dtmf_t *, switch_dtmf_direction_t direction);
@ -108,6 +112,20 @@ struct switch_io_event_hook_video_write_frame {
struct switch_io_event_hook_video_write_frame *next;
};
/*! \brief Node in which to store custom read frame channel callback hooks */
struct switch_io_event_hook_text_read_frame {
/*! the read frame channel callback hook */
switch_read_frame_hook_t text_read_frame;
struct switch_io_event_hook_text_read_frame *next;
};
/*! \brief Node in which to store custom video_write_frame channel callback hooks */
struct switch_io_event_hook_text_write_frame {
/*! the video_write_frame channel callback hook */
switch_video_write_frame_hook_t text_write_frame;
struct switch_io_event_hook_text_write_frame *next;
};
/*! \brief Node in which to store custom kill channel callback hooks */
struct switch_io_event_hook_kill_channel {
/*! the kill channel callback hook */
@ -158,8 +176,12 @@ struct switch_io_event_hooks {
switch_io_event_hook_video_read_frame_t *video_read_frame;
/*! a list of write frame hooks */
switch_io_event_hook_write_frame_t *write_frame;
/*! a list of video write frame hooks */
/*! a list of text write frame hooks */
switch_io_event_hook_video_write_frame_t *video_write_frame;
/*! a list of text write frame hooks */
switch_io_event_hook_text_write_frame_t *text_write_frame;
/*! a list of text read frame hooks */
switch_io_event_hook_text_read_frame_t *text_read_frame;
/*! a list of kill channel hooks */
switch_io_event_hook_kill_channel_t *kill_channel;
/*! a list of send dtmf hooks */
@ -225,6 +247,8 @@ NEW_HOOK_DECL_ADD_P(read_frame);
NEW_HOOK_DECL_ADD_P(write_frame);
NEW_HOOK_DECL_ADD_P(video_read_frame);
NEW_HOOK_DECL_ADD_P(video_write_frame);
NEW_HOOK_DECL_ADD_P(text_read_frame);
NEW_HOOK_DECL_ADD_P(text_write_frame);
NEW_HOOK_DECL_ADD_P(kill_channel);
NEW_HOOK_DECL_ADD_P(send_dtmf);
NEW_HOOK_DECL_ADD_P(recv_dtmf);
@ -238,6 +262,8 @@ NEW_HOOK_DECL_REM_P(read_frame);
NEW_HOOK_DECL_REM_P(write_frame);
NEW_HOOK_DECL_REM_P(video_read_frame);
NEW_HOOK_DECL_REM_P(video_write_frame);
NEW_HOOK_DECL_REM_P(text_read_frame);
NEW_HOOK_DECL_REM_P(text_write_frame);
NEW_HOOK_DECL_REM_P(kill_channel);
NEW_HOOK_DECL_REM_P(send_dtmf);
NEW_HOOK_DECL_REM_P(recv_dtmf);

View File

@ -122,9 +122,11 @@ typedef struct switch_core_media_params_s {
switch_rtp_bug_flag_t manual_rtp_bugs;
switch_rtp_bug_flag_t manual_video_rtp_bugs;
switch_rtp_bug_flag_t manual_text_rtp_bugs;
char *rtcp_audio_interval_msec;
char *rtcp_video_interval_msec;
char *rtcp_text_interval_msec;
char *extrtpip;
@ -331,10 +333,10 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_codec_control(switch_core_sess
SWITCH_DECLARE(switch_timer_t *) switch_core_media_get_timer(switch_core_session_t *session, switch_media_type_t mtype);
SWITCH_DECLARE(void) switch_core_media_start_video_function(switch_core_session_t *session, switch_video_function_t video_function, void *user_data);
SWITCH_DECLARE(void) switch_core_media_end_video_function(switch_core_session_t *session);
SWITCH_DECLARE(void) switch_core_media_start_engine_function(switch_core_session_t *session, switch_media_type_t type, switch_engine_function_t engine_function, void *user_data);
SWITCH_DECLARE(void) switch_core_media_end_engine_function(switch_core_session_t *session, switch_media_type_t type);
SWITCH_DECLARE(switch_status_t) switch_core_session_start_video_thread(switch_core_session_t *session);
SWITCH_DECLARE(int) switch_core_media_check_video_function(switch_core_session_t *session);
SWITCH_DECLARE(int) switch_core_media_check_engine_function(switch_core_session_t *session, switch_media_type_t type);
SWITCH_DECLARE(void) switch_core_session_video_reinit(switch_core_session_t *session);
SWITCH_DECLARE(switch_status_t) switch_core_media_read_lock_unlock(switch_core_session_t *session, switch_media_type_t type, switch_bool_t lock);
@ -353,7 +355,23 @@ SWITCH_DECLARE(switch_bool_t) switch_core_media_check_dtls(switch_core_session_t
SWITCH_DECLARE(switch_status_t) switch_core_media_set_outgoing_bitrate(switch_core_session_t *session, switch_media_type_t type, uint32_t bitrate);
SWITCH_DECLARE(switch_status_t) switch_core_media_reset_jb(switch_core_session_t *session, switch_media_type_t type);
SWITCH_DECLARE(switch_status_t) switch_core_session_wait_for_video_input_params(switch_core_session_t *session, uint32_t timeout_ms);
SWITCH_DECLARE(switch_status_t) switch_core_session_set_text_read_callback(switch_core_session_t *session,
switch_core_text_thread_callback_func_t func, void *user_data);
SWITCH_DECLARE(switch_status_t) switch_core_session_text_read_callback(switch_core_session_t *session, switch_frame_t *frame);
SWITCH_DECLARE(switch_status_t) switch_core_session_read_text_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags,
int stream_id);
SWITCH_DECLARE(switch_status_t) switch_core_session_write_text_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags,
int stream_id);
SWITCH_DECLARE(switch_status_t) switch_rtp_text_factory_create(switch_rtp_text_factory_t **tfP, switch_memory_pool_t *pool);
SWITCH_DECLARE(switch_status_t) switch_rtp_text_factory_destroy(switch_rtp_text_factory_t **tfP);
SWITCH_DECLARE(switch_status_t) switch_core_session_print(switch_core_session_t *session, const char *data);
SWITCH_DECLARE(switch_status_t) switch_core_session_printf(switch_core_session_t *session, const char *fmt, ...);
SWITCH_END_EXTERN_C
#endif
/* For Emacs:

View File

@ -1020,6 +1020,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_stop_video_write_overlay_session(swit
SWITCH_DECLARE(switch_status_t) switch_ivr_video_write_overlay_session(switch_core_session_t *session, const char *img_path,
switch_img_position_t pos, uint8_t alpha);
SWITCH_DECLARE(switch_status_t) switch_ivr_capture_text(switch_core_session_t *session, switch_bool_t on);
/** @} */

View File

@ -39,7 +39,8 @@ typedef enum {
typedef enum {
SJB_VIDEO = 0,
SJB_AUDIO
SJB_AUDIO,
SJB_TEXT
} switch_jb_type_t;

View File

@ -119,6 +119,8 @@ typedef switch_status_t (*switch_io_state_change_t) (switch_core_session_t *);
typedef switch_status_t (*switch_io_state_run_t) (switch_core_session_t *);
typedef switch_status_t (*switch_io_read_video_frame_t) (switch_core_session_t *, switch_frame_t **, switch_io_flag_t, int);
typedef switch_status_t (*switch_io_write_video_frame_t) (switch_core_session_t *, switch_frame_t *, switch_io_flag_t, int);
typedef switch_status_t (*switch_io_read_text_frame_t) (switch_core_session_t *, switch_frame_t **, switch_io_flag_t, int);
typedef switch_status_t (*switch_io_write_text_frame_t) (switch_core_session_t *, switch_frame_t *, switch_io_flag_t, int);
typedef switch_jb_t *(*switch_io_get_jb_t) (switch_core_session_t *, switch_media_type_t);
typedef enum {
@ -132,6 +134,8 @@ typedef enum {
SWITCH_IO_STATE_CHANGE,
SWITCH_IO_READ_VIDEO_FRAME,
SWITCH_IO_WRITE_VIDEO_FRAME,
SWITCH_IO_READ_TEXT_FRAME,
SWITCH_IO_WRITE_TEXT_FRAME,
SWITCH_IO_GET_JB,
} switch_io_routine_name_t;
@ -157,6 +161,10 @@ struct switch_io_routines {
switch_io_read_video_frame_t read_video_frame;
/*! write a video frame to a session */
switch_io_write_video_frame_t write_video_frame;
/*! read a video frame from a session */
switch_io_read_text_frame_t read_text_frame;
/*! write a video frame to a session */
switch_io_write_text_frame_t write_text_frame;
/*! change a sessions channel run state */
switch_io_state_run_t state_run;
/*! get sessions jitterbuffer */

View File

@ -213,6 +213,8 @@ SWITCH_BEGIN_EXTERN_C
#define SWITCH_REMOTE_VIDEO_PORT_VARIABLE "remote_video_port"
#define SWITCH_LOCAL_VIDEO_IP_VARIABLE "local_video_ip"
#define SWITCH_LOCAL_VIDEO_PORT_VARIABLE "local_video_port"
#define SWITCH_LOCAL_TEXT_IP_VARIABLE "local_text_ip"
#define SWITCH_LOCAL_TEXT_PORT_VARIABLE "local_text_port"
#define SWITCH_HANGUP_AFTER_BRIDGE_VARIABLE "hangup_after_bridge"
#define SWITCH_PARK_AFTER_BRIDGE_VARIABLE "park_after_bridge"
#define SWITCH_PARK_AFTER_EARLY_BRIDGE_VARIABLE "park_after_early_bridge"
@ -234,6 +236,7 @@ SWITCH_BEGIN_EXTERN_C
#define SWITCH_RTCP_AUDIO_INTERVAL_MSEC "5000"
#define SWITCH_RTCP_VIDEO_INTERVAL_MSEC "2000"
#define TEXT_UNICODE_LINEFEED {0xe2, 0x80, 0xa8}
#define MAX_FMTP_LEN 256
/* Jitter */
@ -496,7 +499,8 @@ typedef enum {
SWITCH_ABC_TYPE_READ_VIDEO_PING,
SWITCH_ABC_TYPE_WRITE_VIDEO_PING,
SWITCH_ABC_TYPE_STREAM_VIDEO_PING,
SWITCH_ABC_TYPE_VIDEO_PATCH
SWITCH_ABC_TYPE_VIDEO_PATCH,
SWITCH_ABC_TYPE_READ_TEXT
} switch_abc_type_t;
typedef struct {
@ -769,6 +773,7 @@ typedef enum {
SWITCH_RTP_FLAG_TMMBR,
SWITCH_RTP_FLAG_GEN_TS_DELTA,
SWITCH_RTP_FLAG_DETECT_SSRC,
SWITCH_RTP_FLAG_TEXT,
SWITCH_RTP_FLAG_INVALID
} switch_rtp_flag_t;
@ -1369,6 +1374,8 @@ typedef enum {
CC_JITTERBUFFER,
CC_FS_RTP,
CC_QUEUEABLE_DTMF_DELAY,
CC_IO_OVERRIDE,
CC_RTP_RTT,
/* WARNING: DO NOT ADD ANY FLAGS BELOW THIS LINE */
CC_FLAG_MAX
} switch_channel_cap_t;
@ -1514,6 +1521,13 @@ typedef enum {
CF_3P_NOMEDIA_REQUESTED_BLEG,
CF_IMAGE_SDP,
CF_VIDEO_SDP_RECVD,
CF_TEXT_SDP_RECVD,
CF_TEXT,
CF_TEXT_POSSIBLE,
CF_TEXT_PASSIVE,
CF_TEXT_ECHO,
CF_TEXT_ACTIVE,
CF_TEXT_IDLE,
/* WARNING: DO NOT ADD ANY FLAGS BELOW THIS LINE */
/* IF YOU ADD NEW ONES CHECK IF THEY SHOULD PERSIST OR ZERO THEM IN switch_core_session.c switch_core_session_request_xml() */
CF_FLAG_MAX
@ -1570,7 +1584,8 @@ typedef enum {
SFF_PICTURE_RESET = (1 << 14),
SFF_SAME_IMAGE = (1 << 15),
SFF_USE_VIDEO_TIMESTAMP = (1 << 16),
SFF_ENCODED = (1 << 17)
SFF_ENCODED = (1 << 17),
SFF_TEXT_LINE_BREAK = (1 << 18)
} switch_frame_flag_enum_t;
typedef uint32_t switch_frame_flag_t;
@ -1714,9 +1729,10 @@ typedef enum {
typedef enum {
SWITCH_MEDIA_TYPE_AUDIO,
SWITCH_MEDIA_TYPE_VIDEO
SWITCH_MEDIA_TYPE_VIDEO,
SWITCH_MEDIA_TYPE_TEXT
} switch_media_type_t;
#define SWITCH_MEDIA_TYPE_TOTAL 2
#define SWITCH_MEDIA_TYPE_TOTAL 3
/*!
@ -1775,7 +1791,8 @@ typedef enum {
SMBF_VIDEO_PATCH = (1 << 21),
SMBF_SPY_VIDEO_STREAM = (1 << 22),
SMBF_SPY_VIDEO_STREAM_BLEG = (1 << 23),
SMBF_READ_VIDEO_PATCH = (1 << 24)
SMBF_READ_VIDEO_PATCH = (1 << 24),
SMBF_READ_TEXT_STREAM = (1 << 25)
} switch_media_bug_flag_enum_t;
typedef uint32_t switch_media_bug_flag_t;
@ -2021,6 +2038,7 @@ typedef enum {
SWITCH_EVENT_CALL_SETUP_RESULT,
SWITCH_EVENT_CALL_DETAIL,
SWITCH_EVENT_DEVICE_STATE,
SWITCH_EVENT_REAL_TIME_TEXT,
SWITCH_EVENT_ALL
} switch_event_types_t;
@ -2236,13 +2254,15 @@ typedef struct switch_console_callback_match switch_console_callback_match_t;
typedef void (*switch_media_bug_exec_cb_t)(switch_media_bug_t *bug, void *user_data);
typedef switch_status_t (*switch_core_video_thread_callback_func_t) (switch_core_session_t *session, switch_frame_t *frame, void *user_data);
typedef switch_status_t (*switch_core_text_thread_callback_func_t) (switch_core_session_t *session, switch_frame_t *frame, void *user_data);
typedef void (*switch_cap_callback_t) (const char *var, const char *val, void *user_data);
typedef switch_status_t (*switch_console_complete_callback_t) (const char *, const char *, switch_console_callback_match_t **matches);
typedef switch_bool_t (*switch_media_bug_callback_t) (switch_media_bug_t *, void *, switch_abc_type_t);
typedef switch_bool_t (*switch_tone_detect_callback_t) (switch_core_session_t *, const char *, const char *);
typedef struct switch_xml_binding switch_xml_binding_t;
typedef void (*switch_video_function_t) (switch_core_session_t *session, void *user_data);
typedef void (*switch_engine_function_t) (switch_core_session_t *session, void *user_data);
typedef switch_status_t (*switch_core_codec_encode_func_t) (switch_codec_t *codec,
switch_codec_t *other_codec,
@ -2609,6 +2629,10 @@ typedef enum {
SCFC_PAUSE_READ
} switch_file_command_t;
struct switch_rtp_text_factory_s;
typedef struct switch_rtp_text_factory_s switch_rtp_text_factory_t;
SWITCH_END_EXTERN_C
#endif
/* For Emacs:

View File

@ -373,6 +373,33 @@ SWITCH_DECLARE(switch_status_t) switch_b64_encode(unsigned char *in, switch_size
SWITCH_DECLARE(switch_size_t) switch_b64_decode(char *in, char *out, switch_size_t olen);
SWITCH_DECLARE(char *) switch_amp_encode(char *s, char *buf, switch_size_t len);
static inline char *switch_print_bits(const unsigned char *byte, char *buf, switch_size_t buflen)
{
int i, j = 0, k = 0, l = 0;
while(k < buflen) {
l = 0;
for (i = 7; i >= 0; i--) {
buf[j++] = (*byte & (1 << i)) ? '1' : '0';
if (++l % 4 == 0) {
buf[j++] = ' ';
}
}
k++;
byte++;
}
if (buf[j-1] == ' ') j--;
buf[j++] = '\0';
return buf;
}
static inline switch_bool_t switch_is_digit_string(const char *s)
{

View File

@ -1140,7 +1140,7 @@ SWITCH_STANDARD_APP(record_av_function)
switch_core_timer_destroy(&timer);
}
switch_core_media_end_video_function(session);
switch_core_media_end_engine_function(session, SWITCH_MEDIA_TYPE_VIDEO);
switch_core_session_set_read_codec(session, NULL);
switch_core_codec_destroy(&codec);

View File

@ -3066,6 +3066,61 @@ SWITCH_STANDARD_API(uuid_chat)
return SWITCH_STATUS_SUCCESS;
}
#define UUID_CAPTURE_TEXT_SYNTAX "<uuid> <on|off>"
SWITCH_STANDARD_API(uuid_capture_text)
{
switch_core_session_t *tsession = NULL;
char *uuid = NULL, *onoff = NULL;
if (!zstr(cmd) && (uuid = strdup(cmd))) {
if ((onoff = strchr(uuid, ' '))) {
*onoff++ = '\0';
}
}
if (zstr(uuid) || zstr(onoff)) {
stream->write_function(stream, "-USAGE: %s\n", UUID_CAPTURE_TEXT_SYNTAX);
} else {
if ((tsession = switch_core_session_locate(uuid))) {
switch_ivr_capture_text(tsession, switch_true(onoff));
} else {
stream->write_function(stream, "-ERR No such channel %s!\n", uuid);
}
}
switch_safe_free(uuid);
return SWITCH_STATUS_SUCCESS;
}
#define UUID_SEND_TEXT_SYNTAX "<uuid> <text>"
SWITCH_STANDARD_API(uuid_send_text)
{
switch_core_session_t *tsession = NULL;
char *uuid = NULL, *text = NULL;
if (!zstr(cmd) && (uuid = strdup(cmd))) {
if ((text = strchr(uuid, ' '))) {
*text++ = '\0';
}
}
if (zstr(uuid) || zstr(text)) {
stream->write_function(stream, "-USAGE: %s\n", UUID_SEND_TEXT_SYNTAX);
} else {
if ((tsession = switch_core_session_locate(uuid))) {
switch_core_session_print(tsession, text);
switch_core_session_print(tsession, "\r\n");
switch_core_session_rwunlock(tsession);
} else {
stream->write_function(stream, "-ERR No such channel %s!\n", uuid);
}
}
switch_safe_free(uuid);
return SWITCH_STATUS_SUCCESS;
}
#define UUID_DROP_DTMF_SYNTAX "<uuid> [on | off ] [ mask_digits <digits> | mask_file <file>]"
SWITCH_STANDARD_API(uuid_drop_dtmf)
{
@ -7197,6 +7252,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
SWITCH_ADD_API(commands_api_interface, "uuid_broadcast", "Execute dialplan application", uuid_broadcast_function, BROADCAST_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_buglist", "List media bugs on a session", uuid_buglist_function, BUGLIST_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_chat", "Send a chat message", uuid_chat, UUID_CHAT_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_send_text", "Send text in real-time", uuid_send_text, UUID_SEND_TEXT_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_capture_text", "start/stop capture_text", uuid_capture_text, UUID_CAPTURE_TEXT_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_codec_debug", "Send codec a debug message", uuid_codec_debug_function, CODEC_DEBUG_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_codec_param", "Send codec a param", uuid_codec_param_function, CODEC_PARAM_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_debug_media", "Debug media", uuid_debug_media_function, DEBUG_MEDIA_SYNTAX);
@ -7376,6 +7433,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
switch_console_set_complete("add uuid_broadcast ::console::list_uuid");
switch_console_set_complete("add uuid_buglist ::console::list_uuid");
switch_console_set_complete("add uuid_chat ::console::list_uuid");
switch_console_set_complete("add uuid_send_text ::console::list_uuid");
switch_console_set_complete("add uuid_capture_text ::console::list_uuid");
switch_console_set_complete("add uuid_codec_debug ::console::list_uuid audio");
switch_console_set_complete("add uuid_codec_debug ::console::list_uuid video");
switch_console_set_complete("add uuid_codec_param ::console::list_uuid audio read");

View File

@ -1148,6 +1148,13 @@ switch_status_t conference_member_del(conference_obj_t *conference, conference_m
lock_member(member);
conference_utils_member_clear_flag(member, MFLAG_INTREE);
switch_safe_free(member->text_framedata);
member->text_framesize = 0;
if (member->text_buffer) {
switch_buffer_destroy(&member->text_buffer);
}
if (member->rec) {
conference->recording_members--;
}

View File

@ -249,6 +249,42 @@ void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, void *ob
floor_holder = conference->floor_holder;
for (imember = conference->members; imember; imember = imember->next) {
if (!zstr(imember->text_framedata)) {
switch_frame_t frame = { 0 };
char *framedata;
uint32_t framedatalen;
const char *caller_id_name = switch_channel_get_variable(imember->channel, "caller_id_name");
unsigned char CR[3] = TEXT_UNICODE_LINEFEED;
switch_mutex_lock(imember->text_mutex);
framedatalen = strlen(imember->text_framedata) + strlen(caller_id_name) + 6;
switch_zmalloc(framedata, framedatalen);
switch_snprintf(framedata, framedatalen, "%s::\n%s", caller_id_name, imember->text_framedata);
memcpy(framedata + strlen(framedata), CR, sizeof(CR));
frame.data = framedata;
frame.datalen = framedatalen;
for (omember = conference->members; omember; omember = omember->next) {
if (omember != imember) {
switch_core_session_write_text_frame(omember->session, &frame, 0, 0);
}
}
free(framedata);
imember->text_framedata[0] = '\0';
switch_mutex_unlock(imember->text_mutex);
}
}
/* Read one frame of audio from each member channel and save it for redistribution */
for (imember = conference->members; imember; imember = imember->next) {
uint32_t buf_read = 0;
@ -1610,6 +1646,65 @@ SWITCH_STANDARD_APP(conference_auto_function)
}
switch_status_t conference_text_thread_callback(switch_core_session_t *session, switch_frame_t *frame, void *user_data)
{
conference_member_t *member = (conference_member_t *)user_data;
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_size_t inuse = 0;
if (!member) return SWITCH_STATUS_FALSE;
switch_mutex_lock(member->text_mutex);
if (!member->text_buffer) {
switch_buffer_create_dynamic(&member->text_buffer, 512, 1024, 0);
switch_zmalloc(member->text_framedata, 1024);
member->text_framesize = 1024;
}
if (frame->data && frame->datalen && !(frame->flags & SFF_CNG)) {
switch_buffer_write(member->text_buffer, frame->data, frame->datalen);
}
inuse = switch_buffer_inuse(member->text_buffer);
if (zstr(member->text_framedata) && inuse && (switch_channel_test_flag(channel, CF_TEXT_IDLE) || switch_test_flag(frame, SFF_TEXT_LINE_BREAK))) {
int bytes = 0, ok = 0;
char *p;
if (inuse + 1 > member->text_framesize) {
void *tmp = malloc(inuse + 1024);
memcpy(tmp, member->text_framedata, member->text_framesize);
switch_assert(tmp);
member->text_framesize = inuse + 1024;
free(member->text_framedata);
member->text_framedata = tmp;
}
bytes = switch_buffer_read(member->text_buffer, member->text_framedata, inuse);
*(member->text_framedata + bytes) = '\0';
for(p = member->text_framedata; p && *p; p++) {
if (*p > 32 && *p < 127) {
ok++;
}
}
if (!ok) {
member->text_framedata[0] = '\0';
}
}
switch_mutex_unlock(member->text_mutex);
return SWITCH_STATUS_SUCCESS;
}
/* Application interface function that is called from the dialplan to join the channel to a conference */
SWITCH_STANDARD_APP(conference_function)
{
@ -2123,6 +2218,7 @@ SWITCH_STANDARD_APP(conference_function)
switch_mutex_init(&member.fnode_mutex, SWITCH_MUTEX_NESTED, member.pool);
switch_mutex_init(&member.audio_in_mutex, SWITCH_MUTEX_NESTED, member.pool);
switch_mutex_init(&member.audio_out_mutex, SWITCH_MUTEX_NESTED, member.pool);
switch_mutex_init(&member.text_mutex, SWITCH_MUTEX_NESTED, member.pool);
switch_thread_rwlock_create(&member.rwlock, member.pool);
if (conference_member_setup_media(&member, conference)) {
@ -2197,6 +2293,7 @@ SWITCH_STANDARD_APP(conference_function)
/* Chime in the core video thread */
switch_core_session_set_video_read_callback(session, conference_video_thread_callback, (void *)&member);
switch_core_session_set_text_read_callback(session, conference_text_thread_callback, (void *)&member);
if (switch_channel_test_flag(channel, CF_VIDEO_ONLY)) {
while(conference_utils_member_test_flag((&member), MFLAG_RUNNING) && switch_channel_ready(channel)) {
@ -2211,6 +2308,7 @@ SWITCH_STANDARD_APP(conference_function)
}
switch_core_session_set_video_read_callback(session, NULL, NULL);
switch_core_session_set_text_read_callback(session, NULL, NULL);
switch_channel_set_private(channel, "_conference_autocall_list_", NULL);

View File

@ -790,6 +790,13 @@ struct conference_member {
int reset_media;
int flip;
int flip_count;
switch_mutex_t *text_mutex;
switch_buffer_t *text_buffer;
char *text_framedata;
uint32_t text_framesize;
};
typedef enum {
@ -971,6 +978,7 @@ void conference_video_fnode_check(conference_file_node_t *fnode, int canvas_id);
switch_status_t conference_video_set_canvas_bgimg(mcu_canvas_t *canvas, const char *img_path);
switch_status_t conference_al_parse_position(al_handle_t *al, const char *data);
switch_status_t conference_video_thread_callback(switch_core_session_t *session, switch_frame_t *frame, void *user_data);
switch_status_t conference_text_thread_callback(switch_core_session_t *session, switch_frame_t *frame, void *user_data);
void *SWITCH_THREAD_FUNC conference_video_muxing_write_thread_run(switch_thread_t *thread, void *obj);
void conference_member_check_agc_levels(conference_member_t *member);
void conference_member_clear_avg(conference_member_t *member);

View File

@ -1012,6 +1012,10 @@ SWITCH_STANDARD_APP(set_mute_function)
}
SWITCH_STANDARD_APP(capture_text_function)
{
switch_ivr_capture_text(session, switch_true((char *)data));
}
SWITCH_STANDARD_APP(ring_ready_function)
{
@ -6127,6 +6131,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load)
SWITCH_ADD_CHAT(chat_interface, "event", event_chat_send);
SWITCH_ADD_CHAT(chat_interface, "api", api_chat_send);
SWITCH_ADD_API(api_interface, "strepoch", "Convert a date string into epoch time", strepoch_api_function, "<string>");
SWITCH_ADD_API(api_interface, "page", "Send a file as a page", page_api_function, "(var1=val1,var2=val2)<var1=val1,var2=val2><chan1>[:_:<chanN>]");
SWITCH_ADD_API(api_interface, "strmicroepoch", "Convert a date string into micoepoch time", strmicroepoch_api_function, "<string>");
@ -6216,6 +6221,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load)
SWITCH_ADD_APP(app_interface, "multiunset", "Unset many channel variables", SET_LONG_DESC, multiunset_function, "[^^<delim>]<varname> <var2> <var3>",
SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
SWITCH_ADD_APP(app_interface, "capture_text", "capture text", "capture text", capture_text_function, "", SAF_NONE);
SWITCH_ADD_APP(app_interface, "ring_ready", "Indicate Ring_Ready", "Indicate Ring_Ready on a channel.", ring_ready_function, "", SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "remove_bugs", "Remove media bugs", "Remove all media bugs from a channel.", remove_bugs_function, "[<function>]", SAF_NONE);
SWITCH_ADD_APP(app_interface, "break", "Break", "Set the break flag.", break_function, "", SAF_SUPPORT_NOMEDIA);

View File

@ -183,7 +183,7 @@ SWITCH_STANDARD_APP(record_fsv_function)
switch_mutex_init(&mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
eh.mutex = mutex;
eh.fd = fd;
switch_core_media_start_video_function(session, record_video_thread, &eh);
switch_core_media_start_engine_function(session, SWITCH_MEDIA_TYPE_VIDEO, record_video_thread, &eh);
}
@ -257,7 +257,7 @@ SWITCH_STANDARD_APP(record_fsv_function)
close(fd);
}
switch_core_media_end_video_function(session);
switch_core_media_end_engine_function(session, SWITCH_MEDIA_TYPE_VIDEO);
switch_core_session_set_read_codec(session, NULL);
switch_core_codec_destroy(&codec);
@ -751,7 +751,7 @@ SWITCH_STANDARD_APP(decode_video_function)
switch_channel_set_flag(channel, CF_VIDEO_DECODED_READ);
switch_core_media_start_video_function(session, decode_video_thread, &max_pictures);
switch_core_media_start_engine_function(session, SWITCH_MEDIA_TYPE_VIDEO, decode_video_thread, &max_pictures);
switch_ivr_play_file(session, NULL, moh, NULL);
@ -762,7 +762,7 @@ SWITCH_STANDARD_APP(decode_video_function)
switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "OK");
switch_core_media_end_video_function(session);
switch_core_media_end_engine_function(session, SWITCH_MEDIA_TYPE_VIDEO);
switch_core_session_video_reset(session);
}

View File

@ -287,6 +287,8 @@ switch_io_routines_t rtc_io_routines = {
/*.state_change */ NULL,
/*.read_video_frame */ rtc_read_video_frame,
/*.write_video_frame */ rtc_write_video_frame,
/*.read_text_frame */ NULL,
/*.write_text_frame */ NULL,
/*.state_run*/ NULL,
/*.get_jb*/ rtc_get_jb
};
@ -330,6 +332,7 @@ void rtc_attach_private(switch_core_session_t *session, private_object_t *tech_p
switch_core_media_check_dtmf_type(session);
switch_channel_set_cap(tech_pvt->channel, CC_JITTERBUFFER);
switch_channel_set_cap(tech_pvt->channel, CC_FS_RTP);
switch_channel_set_cap(tech_pvt->channel, CC_IO_OVERRIDE);
switch_media_handle_create(&tech_pvt->media_handle, session, &tech_pvt->mparams);
switch_core_session_set_private(session, tech_pvt);

View File

@ -62,6 +62,8 @@ static switch_status_t sofia_read_frame(switch_core_session_t *session, switch_f
static switch_status_t sofia_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id);
static switch_status_t sofia_read_video_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id);
static switch_status_t sofia_write_video_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id);
static switch_status_t sofia_read_text_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id);
static switch_status_t sofia_write_text_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id);
static switch_status_t sofia_kill_channel(switch_core_session_t *session, int sig);
/* BODY OF THE MODULE */
@ -918,6 +920,16 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t sofia_read_text_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id)
{
return switch_core_media_read_frame(session, frame, flags, stream_id, SWITCH_MEDIA_TYPE_TEXT);
}
static switch_status_t sofia_write_text_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id)
{
return switch_core_media_write_frame(session, frame, flags, stream_id, SWITCH_MEDIA_TYPE_TEXT);
}
static switch_status_t sofia_read_video_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id)
{
private_object_t *tech_pvt = (private_object_t *) switch_core_session_get_private(session);
@ -4279,6 +4291,8 @@ switch_io_routines_t sofia_io_routines = {
/*.state_change */ NULL,
/*.read_video_frame */ sofia_read_video_frame,
/*.write_video_frame */ sofia_write_video_frame,
/*.read_text_frame */ sofia_read_text_frame,
/*.write_text_frame */ sofia_write_text_frame,
/*.state_run*/ NULL,
/*.get_jb*/ sofia_get_jb
};

View File

@ -122,6 +122,8 @@ switch_io_routines_t crtp_io_routines = {
/*state_change*/ NULL,
/*read_video_frame*/ NULL,
/*write_video_frame*/ NULL,
/*read_text_frame*/ NULL,
/*write_text_frame*/ NULL,
/*state_run*/ NULL

View File

@ -159,6 +159,7 @@ void sofia_glue_attach_private(switch_core_session_t *session, sofia_profile_t *
switch_channel_set_cap(tech_pvt->channel, CC_PROXY_MEDIA);
switch_channel_set_cap(tech_pvt->channel, CC_JITTERBUFFER);
switch_channel_set_cap(tech_pvt->channel, CC_FS_RTP);
switch_channel_set_cap(tech_pvt->channel, CC_RTP_RTT);
switch_channel_set_cap(tech_pvt->channel, CC_QUEUEABLE_DTMF_DELAY);

View File

@ -53,7 +53,7 @@
#include <poll.h>
#define closesocket(x) close(x)
#endif
#include <switch_utils.h>
#include <switch.h>
#include "mcast.h"

View File

@ -130,6 +130,10 @@ static switch_bool_t check_name(const char *name)
}
static switch_status_t verto_read_text_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id);
static switch_status_t verto_write_text_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id);
static void set_text_funcs(switch_core_session_t *session);
static verto_profile_t *find_profile(const char *name);
static jsock_t *get_jsock(const char *uuid);
@ -2116,6 +2120,11 @@ switch_endpoint_interface_t *verto_endpoint_interface = NULL;
static switch_status_t verto_on_destroy(switch_core_session_t *session)
{
verto_pvt_t *tech_pvt = switch_core_session_get_private_class(session, SWITCH_PVT_SECONDARY);
switch_buffer_destroy(&tech_pvt->text_read_buffer);
switch_buffer_destroy(&tech_pvt->text_write_buffer);
UNPROTECT_INTERFACE(verto_endpoint_interface);
return SWITCH_STATUS_SUCCESS;
}
@ -2576,6 +2585,7 @@ static int verto_recover_callback(switch_core_session_t *session)
}
tech_pvt = switch_core_session_alloc(session, sizeof(*tech_pvt));
tech_pvt->pool = switch_core_session_get_pool(session);
tech_pvt->session = session;
tech_pvt->channel = channel;
tech_pvt->jsock_uuid = (char *) jsock_uuid_str;
@ -3261,7 +3271,7 @@ static void parse_user_vars(cJSON *obj, switch_core_session_t *session)
static switch_bool_t verto__info_func(const char *method, cJSON *params, jsock_t *jsock, cJSON **response)
{
cJSON *msg = NULL, *dialog = NULL;
cJSON *msg = NULL, *dialog = NULL, *txt = NULL;
const char *call_id = NULL, *dtmf = NULL;
switch_bool_t r = SWITCH_TRUE;
char *proto = VERTO_CHAT_PROTO;
@ -3298,6 +3308,43 @@ static switch_bool_t verto__info_func(const char *method, cJSON *params, jsock_t
}
}
if ((txt = cJSON_GetObjectItem(params, "txt"))) {
switch_core_session_t *session;
if ((session = switch_core_session_locate(call_id))) {
verto_pvt_t *tech_pvt = switch_core_session_get_private_class(session, SWITCH_PVT_SECONDARY);
char charbuf[2] = "";
char *chardata = NULL;
cJSON *data;
if ((data = cJSON_GetObjectItem(txt, "code"))) {
charbuf[0] = data->valueint;
chardata = charbuf;
} else if ((data = cJSON_GetObjectItem(txt, "chars"))) {
if (data->valuestring) {
chardata = data->valuestring;
} else if (data->valueint) {
charbuf[0] = data->valueint;
chardata = charbuf;
}
}
if (chardata) {
switch_mutex_lock(tech_pvt->text_read_mutex);
switch_buffer_write(tech_pvt->text_read_buffer, chardata, strlen(chardata));
switch_mutex_unlock(tech_pvt->text_read_mutex);
if ((switch_mutex_trylock(tech_pvt->text_cond_mutex) == SWITCH_STATUS_SUCCESS)) {
switch_thread_cond_signal(tech_pvt->text_cond);
switch_mutex_unlock(tech_pvt->text_cond_mutex);
}
}
switch_core_session_rwunlock(session);
}
}
if ((msg = cJSON_GetObjectItem(params, "msg"))) {
switch_event_t *event;
char *to = (char *) cJSON_GetObjectCstr(msg, "to");
@ -3380,6 +3427,8 @@ static switch_bool_t verto__info_func(const char *method, cJSON *params, jsock_t
return r;
}
static switch_bool_t verto__invite_func(const char *method, cJSON *params, jsock_t *jsock, cJSON **response)
{
cJSON *obj = cJSON_CreateObject(), *screenShare = NULL, *dedEnc = NULL, *mirrorInput, *bandwidth = NULL, *canvas = NULL;
@ -3431,12 +3480,13 @@ static switch_bool_t verto__invite_func(const char *method, cJSON *params, jsock
tech_pvt = switch_core_session_alloc(session, sizeof(*tech_pvt));
tech_pvt->session = session;
tech_pvt->pool = switch_core_session_get_pool(session);
tech_pvt->channel = channel;
tech_pvt->jsock_uuid = switch_core_session_strdup(session, jsock->uuid_str);
tech_pvt->r_sdp = switch_core_session_strdup(session, sdp);
switch_core_media_set_sdp_codec_string(session, sdp, SDP_TYPE_REQUEST);
switch_core_session_set_private_class(session, tech_pvt, SWITCH_PVT_SECONDARY);
set_text_funcs(session);
tech_pvt->call_id = switch_core_session_strdup(session, call_id);
if ((tech_pvt->smh = switch_core_session_get_media_handle(session))) {
@ -5042,6 +5092,115 @@ switch_io_routines_t verto_io_routines = {
/*.outgoing_channel */ verto_outgoing_channel
};
switch_io_routines_t verto_io_override = {
/*.outgoing_channel */ NULL,
/*.read_frame */ NULL,
/*.write_frame */ NULL,
/*.kill_channel */ NULL,
/*.send_dtmf */ NULL,
/*.receive_message */ NULL,
/*.receive_event */ NULL,
/*.state_change */ NULL,
/*.read_video_frame */ NULL,
/*.write_video_frame */ NULL,
/*.read_text_frame */ verto_read_text_frame,
/*.write_text_frame */ verto_write_text_frame,
/*.state_run*/ NULL,
/*.get_jb*/ NULL
};
static switch_status_t verto_read_text_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id)
{
verto_pvt_t *tech_pvt = switch_core_session_get_private_class(session, SWITCH_PVT_SECONDARY);
switch_status_t status;
switch_mutex_lock(tech_pvt->text_cond_mutex);
status = switch_thread_cond_timedwait(tech_pvt->text_cond, tech_pvt->text_cond_mutex, 100000);
switch_mutex_unlock(tech_pvt->text_cond_mutex);
*frame = &tech_pvt->text_read_frame;
(*frame)->flags = 0;
switch_mutex_lock(tech_pvt->text_read_mutex);
if (switch_buffer_inuse(tech_pvt->text_read_buffer)) {
status = SWITCH_STATUS_SUCCESS;
tech_pvt->text_read_frame.datalen = switch_buffer_read(tech_pvt->text_read_buffer, tech_pvt->text_read_frame.data, 100);
} else {
(*frame)->flags |= SFF_CNG;
tech_pvt->text_read_frame.datalen = 2;
status = SWITCH_STATUS_BREAK;
}
switch_mutex_unlock(tech_pvt->text_read_mutex);
return status;
}
static switch_status_t verto_write_text_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id)
{
verto_pvt_t *tech_pvt = switch_core_session_get_private_class(session, SWITCH_PVT_SECONDARY);
switch_mutex_lock(tech_pvt->text_write_mutex);
if (frame) {
switch_buffer_write(tech_pvt->text_write_buffer, frame->data, frame->datalen);
}
if (switch_buffer_inuse(tech_pvt->text_write_buffer)) {
uint32_t datalen;
switch_byte_t data[SWITCH_RTP_MAX_BUF_LEN] = "";
if ((datalen = switch_buffer_read(tech_pvt->text_write_buffer, data, 100))) {
cJSON *obj = NULL, *txt = NULL, *params = NULL;
jsock_t *jsock;
obj = jrpc_new_req("verto.info", tech_pvt->call_id, &params);
txt = json_add_child_obj(params, "txt", NULL);
cJSON_AddItemToObject(txt, "chars", cJSON_CreateString((char *)data));
if ((jsock = get_jsock(tech_pvt->jsock_uuid))) {
jsock_queue_event(jsock, &obj, SWITCH_TRUE);
switch_thread_rwlock_unlock(jsock->rwlock);
} else {
cJSON_Delete(obj);
}
}
}
switch_mutex_unlock(tech_pvt->text_write_mutex);
return SWITCH_STATUS_SUCCESS;
}
static void set_text_funcs(switch_core_session_t *session)
{
if ((switch_core_session_override_io_routines(session, &verto_io_override) == SWITCH_STATUS_SUCCESS)) {
verto_pvt_t *tech_pvt = switch_core_session_get_private_class(session, SWITCH_PVT_SECONDARY);
tech_pvt->text_read_frame.data = tech_pvt->text_read_frame_data;
switch_mutex_init(&tech_pvt->text_read_mutex, SWITCH_MUTEX_NESTED, tech_pvt->pool);
switch_mutex_init(&tech_pvt->text_write_mutex, SWITCH_MUTEX_NESTED, tech_pvt->pool);
switch_mutex_init(&tech_pvt->text_cond_mutex, SWITCH_MUTEX_NESTED, tech_pvt->pool);
switch_thread_cond_create(&tech_pvt->text_cond, tech_pvt->pool);
switch_buffer_create_dynamic(&tech_pvt->text_read_buffer, 512, 1024, 0);
switch_buffer_create_dynamic(&tech_pvt->text_write_buffer, 512, 1024, 0);
switch_channel_set_flag(switch_core_session_get_channel(session), CF_TEXT);
switch_core_session_start_text_thread(session);
}
}
static char *verto_get_dial_string(const char *uid, switch_stream_handle_t *rstream)
{
jsock_t *jsock;
@ -5187,11 +5346,14 @@ static switch_call_cause_t verto_outgoing_channel(switch_core_session_t *session
char name[512];
tech_pvt = switch_core_session_alloc(*new_session, sizeof(*tech_pvt));
tech_pvt->pool = switch_core_session_get_pool(*new_session);
tech_pvt->session = *new_session;
tech_pvt->channel = channel;
tech_pvt->jsock_uuid = switch_core_session_strdup(*new_session, jsock_uuid_str);
switch_core_session_set_private_class(*new_session, tech_pvt, SWITCH_PVT_SECONDARY);
set_text_funcs(*new_session);
if (session) {
switch_channel_t *ochannel = switch_core_session_get_channel(session);

View File

@ -173,6 +173,7 @@ typedef enum {
} tflag_t;
typedef struct verto_pvt_s {
switch_memory_pool_t *pool;
char *jsock_uuid;
char *call_id;
char *r_sdp;
@ -184,6 +185,17 @@ typedef struct verto_pvt_s {
switch_call_cause_t remote_hangup_cause;
time_t detach_time;
struct verto_pvt_s *next;
switch_byte_t text_read_frame_data[SWITCH_RTP_MAX_BUF_LEN];
switch_frame_t text_read_frame;
switch_thread_cond_t *text_cond;
switch_mutex_t *text_cond_mutex;
switch_mutex_t *text_read_mutex;
switch_mutex_t *text_write_mutex;
switch_buffer_t *text_read_buffer;
switch_buffer_t *text_write_buffer;
} verto_pvt_t;
typedef struct verto_vhost_s {

View File

@ -53,6 +53,12 @@ struct switch_buffer {
int32_t loops;
};
SWITCH_DECLARE(void *) switch_buffer_get_head_pointer(switch_buffer_t *buffer)
{
return buffer->head;
}
SWITCH_DECLARE(switch_status_t) switch_buffer_reset_partition_data(switch_buffer_t *buffer)
{
if (!switch_test_flag(buffer, SWITCH_BUFFER_FLAG_PARTITION)) {

File diff suppressed because it is too large Load Diff

View File

@ -88,6 +88,11 @@ SWITCH_DECLARE(switch_core_session_t *) switch_core_media_bug_get_session(switch
return bug->session;
}
SWITCH_DECLARE(const char *) switch_core_media_bug_get_text(switch_media_bug_t *bug)
{
return bug->text_framedata;
}
SWITCH_DECLARE(switch_frame_t *) switch_core_media_bug_get_video_ping_frame(switch_media_bug_t *bug)
{
return bug->video_ping_frame;
@ -791,6 +796,14 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_bug_add(switch_core_session_t
switch_queue_create(&bug->spy_video_queue[1], SWITCH_CORE_QUEUE_LEN, switch_core_session_get_pool(session));
}
if ((switch_test_flag(bug, SMBF_READ_TEXT_STREAM))) {
switch_buffer_create_dynamic(&bug->text_buffer, 512, 1024, 0);
switch_zmalloc(bug->text_framedata, 1024);
bug->text_framesize = 1024;
}
if ((switch_test_flag(bug, SMBF_READ_VIDEO_STREAM) || switch_test_flag(bug, SMBF_WRITE_VIDEO_STREAM))) {
switch_memory_pool_t *pool = switch_core_session_get_pool(session);
@ -1150,6 +1163,11 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_bug_close(switch_media_bug_t *
bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_CLOSE);
}
if (bp->text_buffer) {
switch_buffer_destroy(&bp->text_buffer);
switch_safe_free(bp->text_framedata);
}
if (switch_test_flag(bp, SMBF_READ_VIDEO_STREAM) || switch_test_flag(bp, SMBF_WRITE_VIDEO_STREAM) || switch_test_flag(bp, SMBF_READ_VIDEO_PING) || switch_test_flag(bp, SMBF_WRITE_VIDEO_PING)) {
switch_channel_clear_flag_recursive(bp->session->channel, CF_VIDEO_DECODED_READ);
}

View File

@ -1469,6 +1469,10 @@ SWITCH_DECLARE(void) switch_core_session_perform_destroy(switch_core_session_t *
switch_channel_get_name((*session)->channel), switch_channel_state_name(switch_channel_get_state((*session)->channel)));
if ((*session)->text_buffer) {
switch_buffer_destroy(&(*session)->text_buffer);
}
switch_core_session_reset(*session, SWITCH_TRUE, SWITCH_TRUE);
switch_core_media_bug_remove_all(*session);
@ -1880,6 +1884,19 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_thread_launch(switch_core_se
return status;
}
SWITCH_DECLARE(const char *) switch_core_session_get_text_buffer(switch_core_session_t *session)
{
const char *buf = NULL;
if (session->text_buffer) {
switch_mutex_lock(session->text_mutex);
buf = (const char *)switch_core_session_strdup(session, (const char *) switch_buffer_get_head_pointer(session->text_buffer));
switch_mutex_unlock(session->text_mutex);
}
return buf;
}
SWITCH_DECLARE(void) switch_core_session_launch_thread(switch_core_session_t *session, switch_thread_start_t func, void *obj)
{
switch_thread_t *thread;
@ -2945,6 +2962,17 @@ SWITCH_DECLARE(void) switch_core_session_raw_read(switch_core_session_t *session
switch_core_session_set_codec_slin(session, session->sdata);
}
SWITCH_DECLARE(switch_status_t) switch_core_session_override_io_routines(switch_core_session_t *session, switch_io_routines_t *ior)
{
if (session->endpoint_interface && switch_channel_test_cap(session->channel, CC_IO_OVERRIDE)) {
session->io_override = ior;
return SWITCH_STATUS_SUCCESS;
}
return SWITCH_STATUS_FALSE;
}
/* For Emacs:
* Local Variables:
* mode:c

View File

@ -219,6 +219,7 @@ static char *EVENT_NAMES[] = {
"CALL_SETUP_RESULT",
"CALL_DETAIL",
"DEVICE_STATE",
"REAL_TIME_TEXT",
"ALL"
};

View File

@ -2728,7 +2728,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_generate_xml_cdr(switch_core_session_
char tmp[512], *f;
int cdr_off = 0, v_off = 0, cd_off = 0;
switch_hold_record_t *hold_record = switch_channel_get_hold_record(channel), *hr;
const char *text_buffer = NULL;
if (*xml_cdr) {
cdr = *xml_cdr;
} else {
@ -2750,6 +2751,12 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_generate_xml_cdr(switch_core_session_
x_field = switch_xml_add_child_d(x_channel_data, "direction", cd_off++);
switch_xml_set_txt_d(x_field, switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound");
if ((text_buffer = switch_core_session_get_text_buffer(session))) {
x_field = switch_xml_add_child_d(x_channel_data, "textlog", cd_off++);
switch_xml_set_txt_d(x_field, text_buffer);
}
x_field = switch_xml_add_child_d(x_channel_data, "state_number", cd_off++);
switch_snprintf(tmp, sizeof(tmp), "%d", switch_channel_get_state(channel));
switch_xml_set_txt_d(x_field, tmp);

View File

@ -663,6 +663,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_session_echo(switch_core_session_t *s
}
switch_channel_set_flag(channel, CF_VIDEO_ECHO);
switch_channel_set_flag(channel, CF_TEXT_ECHO);
while (switch_channel_ready(channel)) {
status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
@ -717,6 +718,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_session_echo(switch_core_session_t *s
switch_core_session_video_reset(session);
switch_core_session_reset(session, SWITCH_TRUE, SWITCH_TRUE);
switch_channel_clear_flag(channel, CF_TEXT_ECHO);
return SWITCH_STATUS_SUCCESS;
}
@ -1525,6 +1527,84 @@ static switch_bool_t record_callback(switch_media_bug_t *bug, void *user_data, s
return SWITCH_TRUE;
}
static switch_bool_t text_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type)
{
switch (type) {
case SWITCH_ABC_TYPE_READ_TEXT:
{
const char *text = switch_core_media_bug_get_text(bug);
if (!zstr(text)) {
switch_event_t *event = NULL;
switch_core_session_t *session = switch_core_media_bug_get_session(bug);
//switch_channel_t *channel = switch_core_session_get_channel(session);
if (switch_event_create(&event, SWITCH_EVENT_REAL_TIME_TEXT) == SWITCH_STATUS_SUCCESS) {
switch_event_add_body(event, text, SWITCH_VA_NONE);
if (switch_true(switch_core_get_variable("fire_text_events"))) {
switch_event_t *clone = NULL;
switch_event_dup(&clone, event);
switch_event_fire(&clone);
}
switch_core_session_queue_event(session, &event);
}
}
}
break;
default:
break;
}
return SWITCH_TRUE;
}
SWITCH_DECLARE(switch_status_t) switch_ivr_capture_text(switch_core_session_t *session, switch_bool_t on)
{
switch_media_bug_t *bug;
switch_channel_t *channel = switch_core_session_get_channel(session);
bug = (switch_media_bug_t *) switch_channel_get_private(channel, "capture_text");
if (on) {
if (bug) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "text bug already attached\n");
return SWITCH_STATUS_FALSE;
}
if (switch_core_media_bug_add(session, "capture_text", switch_core_session_get_uuid(session),
text_callback, NULL, 0,
SMBF_READ_TEXT_STREAM,
&bug) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot attach bug\n");
return SWITCH_STATUS_FALSE;
}
switch_channel_set_private(channel, "capture_text", bug);
return SWITCH_STATUS_SUCCESS;
} else {
if (bug) {
switch_channel_set_private(channel, "capture_text", NULL);
switch_core_media_bug_remove(session, &bug);
return SWITCH_STATUS_SUCCESS;
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "text bug not attached\n");
return SWITCH_STATUS_FALSE;
}
}
}
SWITCH_DECLARE(switch_status_t) switch_ivr_record_session_mask(switch_core_session_t *session, const char *file, switch_bool_t on)
{
switch_media_bug_t *bug;

View File

@ -39,13 +39,39 @@ static void cleanup_proxy_mode_b(switch_core_session_t *session);
/* Bridge Related Stuff*/
/*********************************************************************************/
#ifdef SWITCH_VIDEO_IN_THREADS
struct vid_helper {
switch_core_session_t *session_a;
switch_core_session_t *session_b;
int up;
};
static void text_bridge_thread(switch_core_session_t *session, void *obj)
{
struct vid_helper *vh = obj;
switch_status_t status;
switch_frame_t *read_frame = 0;
switch_channel_t *channel = switch_core_session_get_channel(vh->session_a);
switch_channel_t *b_channel = switch_core_session_get_channel(vh->session_b);
vh->up = 1;
while (switch_channel_up_nosig(channel) && switch_channel_up_nosig(b_channel) && vh->up == 1) {
status = switch_core_session_read_text_frame(vh->session_a, &read_frame, SWITCH_IO_FLAG_NONE, 0);
if (SWITCH_READ_ACCEPTABLE(status) && !switch_test_flag(read_frame, SFF_CNG)) {
switch_core_session_write_text_frame(vh->session_b, read_frame, 0, 0);
}
switch_core_session_write_text_frame(vh->session_a, NULL, 0, 0);
}
vh->up = 0;
}
#ifdef SWITCH_VIDEO_IN_THREADS
static void video_bridge_thread(switch_core_session_t *session, void *obj)
{
struct vid_helper *vh = obj;
@ -223,7 +249,7 @@ static void video_bridge_thread(switch_core_session_t *session, void *obj)
static void launch_video(struct vid_helper *vh)
{
switch_core_media_start_video_function(vh->session_a, video_bridge_thread, vh);
switch_core_media_start_engine_function(vh->session_a, SWITCH_MEDIA_TYPE_VIDEO, video_bridge_thread, vh);
}
#endif
@ -334,6 +360,8 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj)
const char *exec_app = NULL;
const char *exec_data = NULL;
switch_codec_implementation_t read_impl = { 0 };
uint32_t txt_launch = 0;
struct vid_helper th = { 0 };
#ifdef SWITCH_VIDEO_IN_THREADS
struct vid_helper vh = { 0 };
@ -449,6 +477,7 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj)
bridge_filter_dtmf = switch_true(switch_channel_get_variable(chan_a, "bridge_filter_dtmf"));
for (;;) {
switch_channel_state_t b_state;
switch_status_t status;
@ -512,6 +541,16 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj)
}
continue;
}
if (switch_channel_test_flag(chan_a, CF_TEXT) && switch_channel_test_flag(chan_b, CF_TEXT) && !txt_launch) {
txt_launch++;
th.session_a = session_a;
th.session_b = session_b;
switch_core_media_start_engine_function(th.session_a, SWITCH_MEDIA_TYPE_TEXT, text_bridge_thread, &th);
}
#ifdef SWITCH_VIDEO_IN_THREADS
if (switch_channel_test_flag(chan_a, CF_VIDEO) && switch_channel_test_flag(chan_b, CF_VIDEO) && !vid_launch) {
vid_launch++;
@ -716,6 +755,7 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj)
end_of_bridge_loop:
#ifdef SWITCH_VIDEO_IN_THREADS
if (vh.up > 0) {
vh.up = -1;
@ -760,8 +800,18 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj)
end:
if (switch_core_media_check_engine_function(session_a, SWITCH_MEDIA_TYPE_TEXT)) {
if (th.up == 1) {
th.up = -1;
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session_a), SWITCH_LOG_DEBUG, "Ending text thread.\n");
switch_core_media_end_engine_function(session_a, SWITCH_MEDIA_TYPE_TEXT);
}
#ifdef SWITCH_VIDEO_IN_THREADS
if (switch_core_media_check_video_function(session_a)) {
if (switch_core_media_check_engine_function(session_a, SWITCH_MEDIA_TYPE_VIDEO)) {
if (vh.up == 1) {
vh.up = -1;
}
@ -772,7 +822,7 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj)
switch_core_session_kill_channel(session_b, SWITCH_SIG_BREAK);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session_a), SWITCH_LOG_DEBUG, "Ending video thread.\n");
switch_core_media_end_video_function(session_a);
switch_core_media_end_engine_function(session_a, SWITCH_MEDIA_TYPE_VIDEO);
switch_channel_clear_flag(chan_a, CF_NOT_READY);
switch_channel_clear_flag(chan_b, CF_NOT_READY);
}

View File

@ -37,7 +37,7 @@
#define PERIOD_LEN 250
#define MAX_FRAME_PADDING 2
#define MAX_MISSING_SEQ 20
#define jb_debug(_jb, _level, _format, ...) if (_jb->debug_level >= _level) switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(_jb->session), SWITCH_LOG_ALERT, "JB:%p:%s lv:%d ln:%.4d sz:%.3u/%.3u/%.3u/%.3u c:%.3u %.3u/%.3u/%.3u/%.3u %.2f%% ->" _format, (void *) _jb, (jb->type == SJB_AUDIO ? "aud" : "vid"), _level, __LINE__, _jb->min_frame_len, _jb->max_frame_len, _jb->frame_len, _jb->complete_frames, _jb->period_count, _jb->consec_good_count, _jb->period_good_count, _jb->consec_miss_count, _jb->period_miss_count, _jb->period_miss_pct, __VA_ARGS__)
#define jb_debug(_jb, _level, _format, ...) if (_jb->debug_level >= _level) switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(_jb->session), SWITCH_LOG_ALERT, "JB:%p:%s lv:%d ln:%.4d sz:%.3u/%.3u/%.3u/%.3u c:%.3u %.3u/%.3u/%.3u/%.3u %.2f%% ->" _format, (void *) _jb, (jb->type == SJB_TEXT ? "txt" : (jb->type == SJB_AUDIO ? "aud" : "vid")), _level, __LINE__, _jb->min_frame_len, _jb->max_frame_len, _jb->frame_len, _jb->complete_frames, _jb->period_count, _jb->consec_good_count, _jb->period_good_count, _jb->consec_miss_count, _jb->period_miss_count, _jb->period_miss_pct, __VA_ARGS__)
//const char *TOKEN_1 = "ONE";
//const char *TOKEN_2 = "TWO";
@ -101,6 +101,8 @@ struct switch_jb_s {
switch_jb_type_t type;
switch_core_session_t *session;
switch_channel_t *channel;
uint32_t buffer_lag;
uint32_t flush;
};
@ -1117,7 +1119,7 @@ SWITCH_DECLARE(switch_status_t) switch_jb_put_packet(switch_jb_t *jb, switch_rtp
if (!want) want = got;
if (switch_test_flag(jb, SJB_QUEUE_ONLY) || jb->type == SJB_AUDIO) {
if (switch_test_flag(jb, SJB_QUEUE_ONLY) || jb->type == SJB_AUDIO || jb->type == SJB_TEXT) {
jb->next_seq = htons(got + 1);
} else {
@ -1203,12 +1205,26 @@ SWITCH_DECLARE(switch_status_t) switch_jb_get_packet(switch_jb_t *jb, switch_rtp
switch_mutex_lock(jb->mutex);
if (jb->complete_frames == 0) {
jb->flush = 0;
switch_goto_status(SWITCH_STATUS_BREAK, end);
}
if (jb->complete_frames < jb->frame_len) {
jb_debug(jb, 2, "BUFFERING %u/%u\n", jb->complete_frames , jb->frame_len);
switch_goto_status(SWITCH_STATUS_MORE_DATA, end);
if (jb->type == SJB_TEXT) {
if (jb->complete_frames && !jb->buffer_lag) {
jb->buffer_lag = 10;
}
if (jb->buffer_lag && --jb->buffer_lag == 0) {
jb->flush = 1;
}
}
if (!jb->flush) {
jb_debug(jb, 2, "BUFFERING %u/%u\n", jb->complete_frames , jb->frame_len);
switch_goto_status(SWITCH_STATUS_MORE_DATA, end);
}
}
jb_debug(jb, 2, "GET PACKET %u/%u n:%d\n", jb->complete_frames , jb->frame_len, jb->visible_nodes);
@ -1254,8 +1270,8 @@ SWITCH_DECLARE(switch_status_t) switch_jb_get_packet(switch_jb_t *jb, switch_rtp
}
}
}
}
jb->period_miss_pct = ((double)jb->period_miss_count / jb->period_count) * 100;
@ -1263,7 +1279,7 @@ SWITCH_DECLARE(switch_status_t) switch_jb_get_packet(switch_jb_t *jb, switch_rtp
jb_debug(jb, 2, "Miss percent %02f too high, resetting buffer.\n", jb->period_miss_pct);
switch_jb_reset(jb);
}
if ((status = jb_next_packet(jb, &node)) == SWITCH_STATUS_SUCCESS) {
jb_debug(jb, 2, "Found next frame cur ts: %u seq: %u\n", htonl(node->packet.header.ts), htons(node->packet.header.seq));
@ -1272,7 +1288,7 @@ SWITCH_DECLARE(switch_status_t) switch_jb_get_packet(switch_jb_t *jb, switch_rtp
jb->highest_read_seq = node->packet.header.seq;
}
if (jb->read_init && htons(node->packet.header.seq) >= htons(jb->highest_read_seq) && (ntohl(node->packet.header.ts) > ntohl(jb->highest_read_ts))) {
if (jb->type == SJB_TEXT || (jb->read_init && htons(node->packet.header.seq) >= htons(jb->highest_read_seq) && (ntohl(node->packet.header.ts) > ntohl(jb->highest_read_ts)))) {
jb->complete_frames--;
jb_debug(jb, 2, "READ frame ts: %u complete=%u/%u n:%u\n", ntohl(node->packet.header.ts), jb->complete_frames , jb->frame_len, jb->visible_nodes);
jb->highest_read_ts = node->packet.header.ts;

View File

@ -511,7 +511,7 @@ typedef enum {
static void do_2833(switch_rtp_t *rtp_session);
#define rtp_type(rtp_session) rtp_session->flags[SWITCH_RTP_FLAG_VIDEO] ? "video" : "audio"
#define rtp_type(rtp_session) rtp_session->flags[SWITCH_RTP_FLAG_TEXT] ? "text" : (rtp_session->flags[SWITCH_RTP_FLAG_VIDEO] ? "video" : "audio")
static void switch_rtp_change_ice_dest(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, const char *host, switch_port_t port)
@ -1278,7 +1278,7 @@ static void handle_ice(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, void *d
msg.message_id = SWITCH_MESSAGE_INDICATE_STUN_ERROR;
switch_core_session_receive_message(rtp_session->session, &msg);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG,
"STUN/ICE binding error received on %s channel\n", rtp_session->flags[SWITCH_RTP_FLAG_VIDEO] ? "video" : "audio");
"STUN/ICE binding error received on %s channel\n", rtp_type(rtp_session));
}
}
@ -3626,7 +3626,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_add_crypto_key(switch_rtp_t *rtp_sess
if (status == SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_INFO, "Activating %s Secure %s RECV\n",
rtp_session->flags[SWITCH_RTP_FLAG_VIDEO] ? "Video" : "Audio", idx ? "RTCP" : "RTP");
rtp_type(rtp_session), idx ? "RTCP" : "RTP");
rtp_session->flags[SWITCH_RTP_FLAG_SECURE_RECV] = 1;
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "Error allocating srtp [%d]\n", stat);
@ -3648,7 +3648,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_add_crypto_key(switch_rtp_t *rtp_sess
if (status == SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_INFO, "Activating %s Secure %s SEND\n",
rtp_session->flags[SWITCH_RTP_FLAG_VIDEO] ? "Video" : "Audio", idx ? "RTCP" : "RTP");
rtp_type(rtp_session), idx ? "RTCP" : "RTP");
rtp_session->flags[SWITCH_RTP_FLAG_SECURE_SEND] = 1;
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "Error allocating SRTP [%d]\n", stat);
@ -4057,11 +4057,11 @@ SWITCH_DECLARE(switch_timer_t *) switch_rtp_get_media_timer(switch_rtp_t *rtp_se
SWITCH_DECLARE(switch_jb_t *) switch_rtp_get_jitter_buffer(switch_rtp_t *rtp_session)
{
if (!switch_rtp_ready(rtp_session) || !rtp_session->jb) {
if (!switch_rtp_ready(rtp_session)) {
return NULL;
}
return rtp_session->jb;
return rtp_session->jb ? rtp_session->jb : rtp_session->vb;
}
SWITCH_DECLARE(switch_status_t) switch_rtp_pause_jitter_buffer(switch_rtp_t *rtp_session, switch_bool_t pause)
@ -4123,7 +4123,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_set_video_buffer_size(switch_rtp_t *r
rtp_session->last_max_vb_frames = max_frames;
if (!rtp_session->vb) {
switch_jb_create(&rtp_session->vb, SJB_VIDEO, frames, max_frames, rtp_session->pool);
switch_jb_create(&rtp_session->vb, rtp_session->flags[SWITCH_RTP_FLAG_TEXT] ? SJB_TEXT : SJB_VIDEO, frames, max_frames, rtp_session->pool);
switch_jb_set_session(rtp_session->vb, rtp_session->session);
} else {
switch_jb_set_frames(rtp_session->vb, frames, max_frames);
@ -5659,7 +5659,7 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
switch_jb_destroy(&rtp_session->vb);
}
}
if (rtp_session->has_rtp && *bytes) {
uint32_t read_ssrc = ntohl(rtp_session->last_rtp_hdr.ssrc);
@ -5718,7 +5718,7 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
}
if (!*bytes || rtp_session->has_rtp) {
if (rtp_session->jb && !rtp_session->pause_jb && jb_valid(rtp_session)) {
switch_status_t jstatus = switch_jb_get_packet(rtp_session->jb, (switch_rtp_packet_t *) &rtp_session->recv_msg, bytes);
@ -5778,9 +5778,21 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
default:
break;
}
if (vstatus == SWITCH_STATUS_NOTFOUND && rtp_session->flags[SWITCH_RTP_FLAG_TEXT]) {
int pt = get_recv_payload(rtp_session);
(*flags) |= SFF_PLC;
status = SWITCH_STATUS_SUCCESS;
*bytes = switch_jb_get_last_read_len(rtp_session->vb);
rtp_session->last_rtp_hdr = rtp_session->recv_msg.header;
if (pt > -1) {
rtp_session->last_rtp_hdr.pt = pt;
}
}
if (vstatus == SWITCH_STATUS_SUCCESS) {
rtp_session->last_rtp_hdr = rtp_session->recv_msg.header;
if (!xcheck_jitter) {
check_jitter(rtp_session);
xcheck_jitter = *bytes;
@ -5854,6 +5866,7 @@ static void handle_nack(switch_rtp_t *rtp_session, uint32_t nack)
}
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "RE----SEND %u\n", ntohs(send_msg->header.seq));
switch_rtp_write_raw(rtp_session, (void *) &send_msg, &bytes, SWITCH_FALSE);
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG1, "Cannot send NACK for seq %u\n", ntohs(seq) + i);
@ -6281,7 +6294,9 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
}
}
if (hot_socket && (rtp_session->hot_hits % 10) != 0) {
if (rtp_session->flags[SWITCH_RTP_FLAG_TEXT]) {
///NOOP
} else if (hot_socket && (rtp_session->hot_hits % 10) != 0) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG10, "%s timer while HOT\n", rtp_session_name(rtp_session));
switch_core_timer_next(&rtp_session->timer);
} else if (hot_socket) {
@ -6368,10 +6383,6 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
poll_status = switch_poll(rtp_session->read_pollfd, 1, &fdr, pt);
//if (rtp_session->flags[SWITCH_RTP_FLAG_VIDEO]) {
// switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_WARNING, "WTF Poll %d\n", poll_status);
//}
if (!rtp_session->flags[SWITCH_RTP_FLAG_VIDEO] && rtp_session->dtmf_data.out_digit_dur > 0) {
return_cng_frame();
}
@ -6393,7 +6404,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
if (read_pretriggered) {
read_pretriggered = 0;
} else {
status = read_rtp_packet(rtp_session, &bytes, flags, poll_status, SWITCH_TRUE);
if (status == SWITCH_STATUS_GENERR) {
@ -6665,11 +6676,11 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
if (bytes && rtp_session->last_rtp_hdr.m && rtp_session->last_rtp_hdr.pt != rtp_session->recv_te &&
!rtp_session->flags[SWITCH_RTP_FLAG_VIDEO] &&
!rtp_session->flags[SWITCH_RTP_FLAG_TEXT] &&
!(rtp_session->rtp_bugs & RTP_BUG_IGNORE_MARK_BIT)) {
rtp_flush_read_buffer(rtp_session, SWITCH_RTP_FLUSH_ONCE);
}
if (rtp_session->last_rtp_hdr.pt == rtp_session->cng_pt || rtp_session->last_rtp_hdr.pt == 13) {
*flags |= SFF_NOT_AUDIO;
} else {
@ -6752,6 +6763,19 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
}
}
if (rtp_session->flags[SWITCH_RTP_FLAG_TEXT]) {
if (!bytes) {
if (rtp_session->flags[SWITCH_RTP_FLAG_USE_TIMER]) {
switch_core_timer_next(&rtp_session->timer);
}
return_cng_frame();
} else {
*payload_type = rtp_session->last_rtp_hdr.pt;
ret = (int) bytes;
goto end;
}
}
if (bytes && (rtp_session->flags[SWITCH_RTP_FLAG_PROXY_MEDIA] || rtp_session->flags[SWITCH_RTP_FLAG_UDPTL])) {
/* Fast PASS! */
*flags |= SFF_PROXY_PACKET;
@ -7923,14 +7947,19 @@ SWITCH_DECLARE(int) switch_rtp_write_frame(switch_rtp_t *rtp_session, switch_fra
#endif
}
if (switch_test_flag(frame, SFF_RTP_HEADER)) {
switch_size_t wrote = switch_rtp_write_manual(rtp_session, frame->data, frame->datalen,
frame->m, frame->payload, (uint32_t) (frame->timestamp), &frame->flags);
if (switch_test_flag(frame, SFF_RTP_HEADER) || rtp_session->flags[SWITCH_RTP_FLAG_TEXT]) {
switch_size_t wrote;
wrote = switch_rtp_write_manual(rtp_session, frame->data, frame->datalen,
frame->m, frame->payload, (uint32_t) (frame->timestamp), &frame->flags);
rtp_session->stats.outbound.raw_bytes += wrote;
rtp_session->stats.outbound.media_bytes += wrote;
rtp_session->stats.outbound.media_packet_count++;
rtp_session->stats.outbound.packet_count++;
return wrote;
}
if (frame->pmap && rtp_session->pmaps && *rtp_session->pmaps) {