From 1388ed811a2369b26778c4cce158691f285c45b4 Mon Sep 17 00:00:00 2001 From: Leon de Rooij Date: Thu, 27 Jan 2011 18:52:14 +0100 Subject: [PATCH 01/36] enter --- src/mod/languages/mod_lua/mod_lua_extra.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/mod/languages/mod_lua/mod_lua_extra.h b/src/mod/languages/mod_lua/mod_lua_extra.h index b96adc39cd..3fca99440c 100644 --- a/src/mod/languages/mod_lua/mod_lua_extra.h +++ b/src/mod/languages/mod_lua/mod_lua_extra.h @@ -1,6 +1,8 @@ #ifndef MOD_LUA_EXTRA #define MOD_LUA_EXTRA -SWITCH_BEGIN_EXTERN_C void mod_lua_conjure_event(lua_State * L, switch_event_t *event, const char *name, int destroy_me); +SWITCH_BEGIN_EXTERN_C + +void mod_lua_conjure_event(lua_State * L, switch_event_t *event, const char *name, int destroy_me); void mod_lua_conjure_stream(lua_State * L, switch_stream_handle_t *stream, const char *name, int destroy_me); void mod_lua_conjure_session(lua_State * L, switch_core_session_t *session, const char *name, int destroy_me); From f37390f0a7f1ca636d54c23d6873510fcf26e91e Mon Sep 17 00:00:00 2001 From: Leon de Rooij Date: Thu, 27 Jan 2011 18:53:21 +0100 Subject: [PATCH 02/36] enter --- src/mod/languages/mod_lua/mod_lua_extra.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/mod/languages/mod_lua/mod_lua_extra.c b/src/mod/languages/mod_lua/mod_lua_extra.c index 38776f93d7..821cc609e9 100644 --- a/src/mod/languages/mod_lua/mod_lua_extra.c +++ b/src/mod/languages/mod_lua/mod_lua_extra.c @@ -1,6 +1,8 @@ using namespace LUA; -SWITCH_BEGIN_EXTERN_C void mod_lua_conjure_event(lua_State * L, switch_event_t *event, const char *name, int destroy_me) +SWITCH_BEGIN_EXTERN_C + +void mod_lua_conjure_event(lua_State * L, switch_event_t *event, const char *name, int destroy_me) { Event *result = new Event(event); SWIG_NewPointerObj(L, result, SWIGTYPE_p_Event, destroy_me); From 68d08547f36777e2c091008b5e1207ca5b15e9e2 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 3 Feb 2011 16:27:22 -0600 Subject: [PATCH 03/36] try to improve iLBC compat --- src/mod/endpoints/mod_sofia/sofia_glue.c | 2 +- src/switch_core.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 8b2f470980..a0b7fca2ff 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -4480,7 +4480,7 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s match = strcasecmp(rm_encoding, imp->iananame) ? 0 : 1; } - if (match && bit_rate && map_bit_rate && map_bit_rate != bit_rate) { + if (match && bit_rate && map_bit_rate && map_bit_rate != bit_rate && strcasecmp(map->rm_encoding, "ilbc")) { /* nevermind */ match = 0; } diff --git a/src/switch_core.c b/src/switch_core.c index 87543050b2..0eb51ccab3 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -1486,7 +1486,7 @@ static void switch_load_core_config(const char *file) { switch_xml_t xml = NULL, cfg = NULL; - //switch_core_hash_insert(runtime.ptimes, "ilbc", &d_30); + switch_core_hash_insert(runtime.ptimes, "ilbc", &d_30); switch_core_hash_insert(runtime.ptimes, "G723", &d_30); if ((xml = switch_xml_open_cfg(file, &cfg, NULL))) { From 33b74ca8c710a58d245ea8903f98e0e86cffe164 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 3 Feb 2011 17:06:18 -0600 Subject: [PATCH 04/36] FS-3006 --- .../endpoints/mod_portaudio/mod_portaudio.c | 1054 +++++++++++------ 1 file changed, 716 insertions(+), 338 deletions(-) diff --git a/src/mod/endpoints/mod_portaudio/mod_portaudio.c b/src/mod/endpoints/mod_portaudio/mod_portaudio.c index 8978b85fc2..baa33d456e 100644 --- a/src/mod/endpoints/mod_portaudio/mod_portaudio.c +++ b/src/mod/endpoints/mod_portaudio/mod_portaudio.c @@ -40,6 +40,8 @@ #define MY_EVENT_RINGING "portaudio::ringing" #define MY_EVENT_MAKE_CALL "portaudio::makecall" +#define MY_EVENT_CALL_HELD "portaudio::callheld" +#define MY_EVENT_CALL_RESUMED "portaudio::callresumed" #define MY_EVENT_ERROR_AUDIO_DEV "portaudio::audio_dev_error" #define SWITCH_PA_CALL_ID_VARIABLE "pa_call_id" @@ -90,12 +92,20 @@ struct private_object { switch_file_handle_t *hfh; switch_frame_t hold_frame; unsigned char holdbuf[SWITCH_RECOMMENDED_BUFFER_SIZE]; - switch_codec_t write_codec; struct private_object *next; }; typedef struct private_object private_t; +struct audio_stream { + int indev; + int outdev; + PABLIO_Stream *stream; + switch_timer_t write_timer; + struct audio_stream *next; +}; +typedef struct audio_stream audio_stream_t; + static struct { int debug; int port; @@ -113,12 +123,13 @@ static struct { switch_hash_t *call_hash; switch_mutex_t *device_lock; switch_mutex_t *pvt_lock; + switch_mutex_t *streams_lock; switch_mutex_t *flag_mutex; switch_mutex_t *pa_mutex; int sample_rate; int codec_ms; - PABLIO_Stream *audio_stream; - PABLIO_Stream *ring_stream; + audio_stream_t *main_stream; + audio_stream_t *ring_stream; switch_codec_t read_codec; switch_codec_t write_codec; switch_frame_t read_frame; @@ -126,13 +137,20 @@ static struct { unsigned char databuf[SWITCH_RECOMMENDED_BUFFER_SIZE]; unsigned char cngbuf[SWITCH_RECOMMENDED_BUFFER_SIZE]; private_t *call_list; + audio_stream_t *stream_list; int ring_interval; GFLAGS flags; switch_timer_t read_timer; - switch_timer_t write_timer; + switch_timer_t readfile_timer; switch_timer_t hold_timer; int dual_streams; time_t deactivate_timer; + int live_stream_switch; + int no_auto_resume_call; + int no_ring_during_call; + int codecs_inited; + int stream_in_use; //only really used by playdev + int destroying_streams; } globals; @@ -164,9 +182,22 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi static switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id); static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id); static switch_status_t channel_kill_channel(switch_core_session_t *session, int sig); -static switch_status_t engage_device(int restart); -static switch_status_t engage_ring_device(void); -static void deactivate_ring_device(void); + +static switch_status_t create_codecs(int restart); +static void create_hold_event(private_t *tech_pvt, int unhold); +static audio_stream_t * find_audio_stream(int indev, int outdev, int already_locked); +static audio_stream_t * get_audio_stream(int indev, int outdev); +static audio_stream_t * create_audio_stream(int indev, int outdev); +PaError open_audio_stream(PABLIO_Stream **stream, const PaStreamParameters * inputParameters, const PaStreamParameters * outputParameters); +static switch_status_t switch_audio_stream(); +static void add_stream(audio_stream_t *stream, int already_locked); +static void remove_stream(audio_stream_t *stream, int already_locked); +static switch_status_t destroy_audio_stream(int indev, int outdev); +static switch_status_t destroy_actual_stream(audio_stream_t *stream); +static void destroy_audio_streams(); +static switch_status_t validate_main_audio_stream(); +static switch_status_t validate_ring_audio_stream(); + static int dump_info(int verbose); static switch_status_t load_config(void); static int get_dev_by_name(char *name, int in); @@ -212,9 +243,8 @@ static switch_status_t channel_on_routing(switch_core_session_t *session) if (hold_file) { tech_pvt->hold_file = switch_core_session_strdup(session, hold_file); } - - if (switch_test_flag(tech_pvt, TFLAG_OUTBOUND)) { - if (engage_device(0) != SWITCH_STATUS_SUCCESS) { + if (switch_test_flag(tech_pvt, TFLAG_OUTBOUND)) { + if (validate_main_audio_stream() != SWITCH_STATUS_SUCCESS) { switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); return SWITCH_STATUS_FALSE; } @@ -238,7 +268,7 @@ static switch_status_t channel_on_routing(switch_core_session_t *session) globals.read_codec.implementation->actual_samples_per_second, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) == SWITCH_STATUS_SUCCESS) { - if (engage_ring_device() != SWITCH_STATUS_SUCCESS) { + if (validate_ring_audio_stream() != SWITCH_STATUS_SUCCESS) { switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Ring Error!\n"); switch_core_file_close(&fh); @@ -263,7 +293,7 @@ static switch_status_t channel_on_routing(switch_core_session_t *session) } while (switch_channel_get_state(channel) == CS_ROUTING && !switch_test_flag(tech_pvt, TFLAG_ANSWER)) { - switch_size_t olen = globals.read_timer.samples; + switch_size_t olen = globals.readfile_timer.samples; if (switch_micro_time_now() - last >= waitsec) { char buf[512]; @@ -273,7 +303,8 @@ static switch_status_t channel_on_routing(switch_core_session_t *session) if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_RINGING) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_info", buf); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call_id", tech_pvt->call_id); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call_id", tech_pvt->call_id); /* left behind for backwards compatability */ + switch_channel_set_variable(channel, SWITCH_PA_CALL_ID_VARIABLE, tech_pvt->call_id); switch_channel_event_set_data(channel, event); switch_event_fire(&event); } @@ -282,7 +313,7 @@ static switch_status_t channel_on_routing(switch_core_session_t *session) } if (ring_file) { - if (switch_core_timer_next(&globals.read_timer) != SWITCH_STATUS_SUCCESS) { + if (switch_core_timer_next(&globals.readfile_timer) != SWITCH_STATUS_SUCCESS) { switch_core_file_close(&fh); break; } @@ -292,8 +323,9 @@ static switch_status_t channel_on_routing(switch_core_session_t *session) switch_core_file_seek(&fh, &pos, 0, SEEK_SET); } - if (globals.ring_stream) { - WriteAudioStream(globals.ring_stream, abuf, (long) olen, &globals.write_timer); + if (globals.ring_stream && (! switch_test_flag(globals.call_list, TFLAG_MASTER) || + ( !globals.no_ring_during_call && globals.main_stream != globals.ring_stream)) ) { //if there is a ring stream and not an active call or if there is an active call and we are allowed to ring during it AND the ring stream is not the main stream + WriteAudioStream(globals.ring_stream->stream, abuf, (long) olen, &globals.ring_stream->write_timer); } } else { switch_yield(10000); @@ -303,7 +335,6 @@ static switch_status_t channel_on_routing(switch_core_session_t *session) } if (ring_file) { - deactivate_ring_device(); switch_core_file_close(&fh); } @@ -329,27 +360,130 @@ static switch_status_t channel_on_execute(switch_core_session_t *session) return SWITCH_STATUS_SUCCESS; } -static void deactivate_audio_device(void) +static audio_stream_t* find_audio_stream(int indev, int outdev, int already_locked) { - if (!globals.audio_stream) { - return; + audio_stream_t *cur_stream; + + if (! globals.stream_list) { + return NULL; } - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Stop audio device.\n"); + if (! already_locked) { + switch_mutex_lock(globals.streams_lock); + } + cur_stream = globals.stream_list; - switch_mutex_lock(globals.device_lock); - /* LOCKED ************************************************************************************************** */ - - if (globals.audio_stream) { - if (globals.ring_stream == globals.audio_stream) { - globals.ring_stream = NULL; + while (cur_stream != NULL) { + if (cur_stream->outdev == outdev) { + if (indev == -1 || cur_stream->indev == indev) { + if (! already_locked) { + switch_mutex_unlock(globals.streams_lock); + } + return cur_stream; + } } - CloseAudioStream(globals.audio_stream); - globals.audio_stream = NULL; + cur_stream = cur_stream->next; + } + if (! already_locked) { + switch_mutex_unlock(globals.streams_lock); + } + return NULL; +} +static void destroy_audio_streams() +{ + int close_wait = 4; + globals.destroying_streams = 1; + + while (globals.stream_in_use && close_wait--) { + switch_yield(250000); + } + while (globals.stream_list != NULL) { + destroy_audio_stream(globals.stream_list->indev, globals.stream_list->outdev); + } + globals.destroying_streams = 0; +} +static switch_status_t validate_main_audio_stream() +{ + if (globals.read_timer.timer_interface) { + switch_core_timer_sync(&globals.read_timer); } - /* UNLOCKED ************************************************************************************************* */ - switch_mutex_unlock(globals.device_lock); + if (globals.main_stream) { + if (globals.main_stream->write_timer.timer_interface) { + switch_core_timer_sync(&(globals.main_stream->write_timer)); + } + + return SWITCH_STATUS_SUCCESS; + } + + globals.main_stream = get_audio_stream(globals.indev, globals.outdev); + + if (globals.main_stream) { + return SWITCH_STATUS_SUCCESS; + } + + return SWITCH_STATUS_FALSE; +} + +static switch_status_t validate_ring_audio_stream() +{ + if (globals.ringdev == -1) { + return SWITCH_STATUS_SUCCESS; + } + if (globals.ring_stream) { + if (globals.ring_stream->write_timer.timer_interface) { + switch_core_timer_sync(&(globals.ring_stream->write_timer)); + } + return SWITCH_STATUS_SUCCESS; + } + globals.ring_stream = get_audio_stream(-1, globals.ringdev); + if (globals.ring_stream) { + return SWITCH_STATUS_SUCCESS; + } + + return SWITCH_STATUS_FALSE; +} + +static switch_status_t destroy_actual_stream(audio_stream_t *stream) +{ + if (stream == NULL) { + return SWITCH_STATUS_FALSE; + } + + if (globals.main_stream == stream) { + globals.main_stream = NULL; + } + + if (globals.ring_stream == stream) { + globals.ring_stream = NULL; + } + + CloseAudioStream(stream->stream); + stream->stream = NULL; + + if (stream->write_timer.timer_interface) { + switch_core_timer_destroy(&stream->write_timer); + } + + switch_safe_free(stream); + return SWITCH_STATUS_SUCCESS; +} +static switch_status_t destroy_audio_stream(int indev, int outdev) +{ + audio_stream_t *stream; + + switch_mutex_lock(globals.streams_lock); + stream = find_audio_stream(indev, outdev,1); + if (stream == NULL) { + switch_mutex_unlock(globals.streams_lock); + return SWITCH_STATUS_FALSE; + } + + remove_stream(stream, 1); + switch_mutex_unlock(globals.streams_lock); + + destroy_actual_stream(stream); + return SWITCH_STATUS_SUCCESS; } @@ -368,34 +502,69 @@ static void destroy_codecs(void) switch_core_timer_destroy(&globals.read_timer); } - if (globals.write_timer.timer_interface) { - switch_core_timer_destroy(&globals.write_timer); + if (globals.readfile_timer.timer_interface) { + switch_core_timer_destroy(&globals.readfile_timer); } if (globals.hold_timer.timer_interface) { switch_core_timer_destroy(&globals.hold_timer); } - - + globals.codecs_inited = 0; } -static void deactivate_ring_device(void) +static void create_hold_event(private_t *tech_pvt, int unhold) { - if (!globals.ring_stream) { - return; + switch_event_t *event; + char * event_id; + + if (unhold) { + event_id = MY_EVENT_CALL_RESUMED; + } else { + event_id = MY_EVENT_CALL_HELD; } - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Stop ring device.\n"); - switch_mutex_lock(globals.device_lock); - if (globals.ring_stream && globals.ring_stream != globals.audio_stream) { - CloseAudioStream(globals.ring_stream); + if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, event_id) == SWITCH_STATUS_SUCCESS) { + switch_channel_event_set_data(switch_core_session_get_channel(tech_pvt->session), event); + switch_event_fire(&event); } - globals.ring_stream = NULL; - switch_mutex_unlock(globals.device_lock); } +static void add_stream(audio_stream_t * stream, int already_locked) +{ + audio_stream_t *last; + if (! already_locked) { + switch_mutex_lock(globals.streams_lock); + } + for (last = globals.stream_list; last && last->next; last = last->next); + if (last == NULL) { + globals.stream_list = stream; + } else { + last->next = stream; + } + if (! already_locked) { + switch_mutex_unlock(globals.streams_lock); + } +} +static void remove_stream(audio_stream_t * stream, int already_locked) +{ + audio_stream_t *previous; + if (! already_locked) { + switch_mutex_lock(globals.streams_lock); + } + if (globals.stream_list == stream) { + globals.stream_list = stream->next; + } else { + for (previous = globals.stream_list; previous && previous->next && previous->next != stream; previous = previous->next) { + ; + } + previous->next = stream->next; + } + if (! already_locked) { + switch_mutex_unlock(globals.streams_lock); + } +} static void add_pvt(private_t *tech_pvt, int master) { @@ -418,8 +587,9 @@ static void add_pvt(private_t *tech_pvt, int master) if (tp == tech_pvt) { in_list = 1; } - if (master) { + if (master && switch_test_flag(tp, TFLAG_MASTER) ) { switch_clear_flag_locked(tp, TFLAG_MASTER); + create_hold_event(tp,0); } } @@ -446,11 +616,16 @@ static void add_pvt(private_t *tech_pvt, int master) static void remove_pvt(private_t *tech_pvt) { private_t *tp, *last = NULL; + int was_master = 0; switch_mutex_lock(globals.pvt_lock); for (tp = globals.call_list; tp; tp = tp->next) { - switch_clear_flag_locked(tp, TFLAG_MASTER); + if (tp == tech_pvt) { + if (switch_test_flag(tp, TFLAG_MASTER)) { + switch_clear_flag_locked(tp, TFLAG_MASTER); + was_master = 1; + } if (last) { last->next = tp->next; } else { @@ -461,10 +636,13 @@ static void remove_pvt(private_t *tech_pvt) } if (globals.call_list) { - switch_set_flag_locked(globals.call_list, TFLAG_MASTER); + if (was_master && ! globals.no_auto_resume_call) { + switch_set_flag_locked(globals.call_list, TFLAG_MASTER); + create_hold_event(globals.call_list, 1); + } } else { globals.deactivate_timer = switch_epoch_time_now(NULL) + 2; - deactivate_audio_device(); + destroy_audio_streams(); } switch_mutex_unlock(globals.pvt_lock); @@ -555,8 +733,8 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch int samples = 0; switch_status_t status = SWITCH_STATUS_FALSE; switch_assert(tech_pvt != NULL); - - if (!globals.audio_stream) { + + if (!globals.main_stream) { goto normal_return; } @@ -618,7 +796,7 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch } switch_mutex_lock(globals.device_lock); - samples = ReadAudioStream(globals.audio_stream, globals.read_frame.data, globals.read_codec.implementation->samples_per_packet, &globals.read_timer); + samples = ReadAudioStream(globals.main_stream->stream, globals.read_frame.data, globals.read_codec.implementation->samples_per_packet, &globals.read_timer); switch_mutex_unlock(globals.device_lock); if (samples) { @@ -635,7 +813,7 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch goto cng_nowait; } - normal_return: +normal_return: return status; cng_nowait: @@ -655,7 +833,7 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc private_t *tech_pvt = switch_core_session_get_private(session); switch_assert(tech_pvt != NULL); - if (!globals.audio_stream) { + if (!globals.main_stream) { return SWITCH_STATUS_FALSE; } @@ -667,9 +845,9 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc return SWITCH_STATUS_SUCCESS; } - if (globals.audio_stream) { + if (globals.main_stream) { if (switch_test_flag((&globals), GFLAG_EAR)) { - WriteAudioStream(globals.audio_stream, (short *) frame->data, (int) (frame->datalen / sizeof(SAMPLE)), &globals.write_timer); + WriteAudioStream(globals.main_stream->stream, (short *) frame->data, (int) (frame->datalen / sizeof(SAMPLE)), &(globals.main_stream->write_timer)); } status = SWITCH_STATUS_SUCCESS; } @@ -747,7 +925,6 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi channel = switch_core_session_get_channel(*new_session); switch_core_session_set_private(*new_session, tech_pvt); tech_pvt->session = *new_session; - globals.flags = GFLAG_EAR | GFLAG_MOUTH; } else { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(*new_session), SWITCH_LOG_CRIT, "Hey where is my memory pool?\n"); switch_core_session_destroy(new_session); @@ -796,16 +973,17 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_portaudio_load) switch_core_hash_init(&globals.call_hash, module_pool); switch_mutex_init(&globals.device_lock, SWITCH_MUTEX_NESTED, module_pool); switch_mutex_init(&globals.pvt_lock, SWITCH_MUTEX_NESTED, module_pool); + switch_mutex_init(&globals.streams_lock, SWITCH_MUTEX_NESTED, module_pool); switch_mutex_init(&globals.flag_mutex, SWITCH_MUTEX_NESTED, module_pool); switch_mutex_init(&globals.pa_mutex, SWITCH_MUTEX_NESTED, module_pool); - + globals.codecs_inited=0; globals.read_frame.data = globals.databuf; globals.read_frame.buflen = sizeof(globals.databuf); globals.cng_frame.data = globals.cngbuf; globals.cng_frame.buflen = sizeof(globals.cngbuf); globals.cng_frame.datalen = switch_samples_per_packet(globals.sample_rate, globals.codec_ms) * 2; switch_set_flag((&globals.cng_frame), SFF_CNG); - + globals.flags = GFLAG_EAR | GFLAG_MOUTH; /* dual streams makes portaudio on solaris choke */ #if defined(sun) || defined(__sun) globals.dual_streams = 0; @@ -834,6 +1012,14 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_portaudio_load) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass!\n"); return SWITCH_STATUS_GENERR; } + if (switch_event_reserve_subclass(MY_EVENT_CALL_HELD) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass!\n"); + return SWITCH_STATUS_GENERR; + } + if (switch_event_reserve_subclass(MY_EVENT_CALL_RESUMED) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass!\n"); + return SWITCH_STATUS_GENERR; + } if (switch_event_reserve_subclass(MY_EVENT_ERROR_AUDIO_DEV) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass!\n"); @@ -861,9 +1047,13 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_portaudio_load) switch_console_set_complete("add pa devlist"); switch_console_set_complete("add pa indev"); switch_console_set_complete("add pa outdev"); + switch_console_set_complete("add pa preparestream"); + switch_console_set_complete("add pa switchstream"); + switch_console_set_complete("add pa closestreams"); switch_console_set_complete("add pa ringdev"); switch_console_set_complete("add pa ringfile"); switch_console_set_complete("add pa play"); + switch_console_set_complete("add pa playdev"); switch_console_set_complete("add pa looptest"); /* indicate that the module should continue to be loaded */ @@ -881,9 +1071,12 @@ static switch_status_t load_config(void) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", cf); return SWITCH_STATUS_TERM; } - + destroy_audio_streams(); + destroy_codecs(); globals.dual_streams = 0; - + globals.live_stream_switch = 0; + globals.no_auto_resume_call = 0; + globals.no_ring_during_call = 0; globals.indev = globals.outdev = globals.ringdev = -1; globals.sample_rate = 8000; @@ -896,6 +1089,24 @@ static switch_status_t load_config(void) globals.debug = atoi(val); } else if (!strcmp(var, "ring-interval")) { globals.ring_interval = atoi(val); + } else if (!strcmp(var, "no-auto-resume-call")) { + if (switch_true(val)) { + globals.no_auto_resume_call = 1; + } else { + globals.no_auto_resume_call = 0; + } + } else if (!strcmp(var, "no-ring-during-call")) { + if (switch_true(val)) { + globals.no_ring_during_call = 1; + } else { + globals.no_ring_during_call = 0; + } + } else if (!strcmp(var, "live-stream-switch")) { + if (switch_true(val)) { + globals.live_stream_switch = 1; + } else { + globals.live_stream_switch = 0; + } } else if (!strcmp(var, "ring-file")) { set_global_ring_file(val); } else if (!strcmp(var, "hold-file")) { @@ -1007,8 +1218,7 @@ static switch_status_t load_config(void) SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_portaudio_shutdown) { - deactivate_audio_device(); - deactivate_ring_device(); + destroy_audio_streams(); destroy_codecs(); Pa_Terminate(); @@ -1017,6 +1227,9 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_portaudio_shutdown) switch_event_free_subclass(MY_EVENT_RINGING); switch_event_free_subclass(MY_EVENT_MAKE_CALL); switch_event_free_subclass(MY_EVENT_ERROR_AUDIO_DEV); + switch_event_free_subclass(MY_EVENT_CALL_HELD); + switch_event_free_subclass(MY_EVENT_CALL_RESUMED); + switch_safe_free(globals.dialplan); switch_safe_free(globals.context); @@ -1118,7 +1331,99 @@ static void PrintSupportedStandardSampleRates(const PaStreamParameters * inputPa } /*******************************************************************/ +static switch_status_t play_dev(switch_stream_handle_t *stream, int outdev, char * file, const char * max_seconds, const char * no_close) +{ + switch_file_handle_t fh = { 0 }; + int samples = 0; + int seconds = 5; + audio_stream_t * audio_stream; + int created_stream = 0; + int wrote = 0; + switch_size_t olen; + int16_t abuf[2048]; + + if (!strcasecmp(file, "ringtest")) { + file = globals.ring_file; + } + if (outdev == -1) { + stream->write_function(stream, "Invalid output audio device\n"); + return SWITCH_STATUS_FALSE; + } + audio_stream = get_audio_stream(-1, outdev); + + fh.pre_buffer_datalen = SWITCH_DEFAULT_FILE_BUFFER_LEN; + + if (switch_core_file_open(&fh, file, + globals.read_codec.implementation->number_of_channels, + globals.read_codec.implementation->actual_samples_per_second, + SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) { + stream->write_function(stream, "Cannot play requested file %s\n", file); + return SWITCH_STATUS_FALSE; + } + + olen = globals.read_codec.implementation->samples_per_packet; + + if (max_seconds) { + int i = atoi(max_seconds); + if (i >= 0) { + seconds = i; + } + } + + if (globals.call_list) { + switch_mutex_lock(globals.pvt_lock); + if (!globals.main_stream) { + switch_mutex_unlock(globals.pvt_lock); + return SWITCH_STATUS_FALSE; + } + + if ( switch_test_flag(globals.call_list, TFLAG_MASTER) && globals.main_stream->outdev == outdev) { /*so we are the active stream so we need to dupe it basically */ + audio_stream = create_audio_stream(-1,outdev); + created_stream=1; + } + switch_mutex_unlock(globals.pvt_lock); + } + + if (! audio_stream) { + stream->write_function(stream, "Failed to engage audio device\n"); + return SWITCH_STATUS_FALSE; + } + + + + samples = globals.read_codec.implementation->actual_samples_per_second * seconds; + globals.stream_in_use=1; + while (switch_core_file_read(&fh, abuf, &olen) == SWITCH_STATUS_SUCCESS) { + if (globals.destroying_streams || ! audio_stream->stream) { + break; + } + + WriteAudioStream(audio_stream->stream, abuf, (long) olen, &(audio_stream->write_timer)); + wrote += (int) olen; + if (samples) { + samples -= (int) olen; + if (samples <= 0) { + break; + } + } + olen = globals.read_codec.implementation->samples_per_packet; + } + globals.stream_in_use = 0; + + switch_core_file_close(&fh); + if (! globals.call_list && ( ! no_close || strcasecmp(no_close, "no_close"))) { + destroy_audio_streams(); + } + + seconds = wrote / globals.read_codec.implementation->actual_samples_per_second; + stream->write_function(stream, "playback test [%s] %d second(s) %d samples @%dkhz", + file, seconds, wrote, globals.read_codec.implementation->actual_samples_per_second); + if (created_stream) { /*still need this as not added to the global pool */ + destroy_actual_stream(audio_stream); + } + return SWITCH_STATUS_SUCCESS; +} static switch_status_t devlist(char **argv, int argc, switch_stream_handle_t *stream) { int i, numDevices, prev; @@ -1200,8 +1505,7 @@ static int dump_info(int verbose) } if (verbose < 0) { - deactivate_audio_device(); - deactivate_ring_device(); + destroy_audio_streams(); destroy_codecs(); Pa_Terminate(); Pa_Initialize(); @@ -1309,36 +1613,15 @@ static int dump_info(int verbose) return err; } -static switch_status_t engage_device(int restart) +static switch_status_t create_codecs(int restart) { - PaStreamParameters inputParameters, outputParameters; - PaError err; int sample_rate = globals.sample_rate; int codec_ms = globals.codec_ms; - switch_event_t *event; - - switch_mutex_lock(globals.device_lock); - while (globals.deactivate_timer > switch_epoch_time_now(NULL)) { - switch_yield(1000000); - } - switch_mutex_unlock(globals.device_lock); - if (restart) { - deactivate_audio_device(); - deactivate_ring_device(); destroy_codecs(); } - - if (globals.read_timer.timer_interface) { - switch_core_timer_sync(&globals.read_timer); - } - - if (globals.write_timer.timer_interface) { - switch_core_timer_sync(&globals.write_timer); - } - - if (globals.audio_stream) { + if (globals.codecs_inited) { return SWITCH_STATUS_SUCCESS; } @@ -1375,20 +1658,18 @@ static switch_status_t engage_device(int restart) return SWITCH_STATUS_FALSE; } } - - - if (!globals.write_timer.timer_interface) { - if (switch_core_timer_init(&globals.write_timer, + if (!globals.readfile_timer.timer_interface) { + if (switch_core_timer_init(&globals.readfile_timer, globals.timer_name, codec_ms, globals.read_codec.implementation->samples_per_packet, module_pool) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "setup timer failed!\n"); switch_core_codec_destroy(&globals.read_codec); switch_core_codec_destroy(&globals.write_codec); - switch_core_timer_destroy(&globals.read_timer); return SWITCH_STATUS_FALSE; } } + if (!globals.hold_timer.timer_interface) { if (switch_core_timer_init(&globals.hold_timer, globals.timer_name, codec_ms, globals.read_codec.implementation->samples_per_packet, @@ -1397,106 +1678,119 @@ static switch_status_t engage_device(int restart) switch_core_codec_destroy(&globals.read_codec); switch_core_codec_destroy(&globals.write_codec); switch_core_timer_destroy(&globals.read_timer); - switch_core_timer_destroy(&globals.write_timer); + switch_core_timer_destroy(&globals.readfile_timer); + return SWITCH_STATUS_FALSE; } } - globals.read_frame.rate = sample_rate; - globals.read_frame.codec = &globals.read_codec; + globals.cng_frame.rate = globals.read_frame.rate = sample_rate; + globals.cng_frame.codec = globals.read_frame.codec = &globals.read_codec; - switch_mutex_lock(globals.device_lock); - /* LOCKED ************************************************************************************************** */ - inputParameters.device = globals.indev; - inputParameters.channelCount = 1; - inputParameters.sampleFormat = SAMPLE_TYPE; - inputParameters.suggestedLatency = Pa_GetDeviceInfo(inputParameters.device)->defaultLowInputLatency; - inputParameters.hostApiSpecificStreamInfo = NULL; - outputParameters.device = globals.outdev; + globals.codecs_inited=1; + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t switch_audio_stream() +{ + audio_stream_t *stream; + if (! globals.call_list) { /* If no active calls then it will automatically switch over on next call */ + return SWITCH_STATUS_SUCCESS; + } + stream = get_audio_stream(globals.indev, globals.outdev); + if (stream == NULL) { + return SWITCH_STATUS_FALSE; + } + + globals.main_stream = stream;//TODO: need locks around here?? + + return SWITCH_STATUS_SUCCESS; +} +PaError open_audio_stream(PABLIO_Stream **stream, const PaStreamParameters * inputParameters, const PaStreamParameters * outputParameters) +{ + if (inputParameters->device != -1) { + return OpenAudioStream(stream, inputParameters, outputParameters, globals.sample_rate, paClipOff, globals.read_codec.implementation->samples_per_packet, globals.dual_streams); + } + return OpenAudioStream(stream, NULL, outputParameters, globals.sample_rate, paClipOff, globals.read_codec.implementation->samples_per_packet, 0); +} + +static audio_stream_t *create_audio_stream(int indev, int outdev) +{ + PaStreamParameters inputParameters, outputParameters; + PaError err; + switch_event_t *event; + audio_stream_t *stream; + + stream = malloc(sizeof(audio_stream_t)); + if (stream == NULL) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Unable to alloc memory\n"); + return NULL; + } + memset(stream, 0, sizeof(audio_stream_t)); + stream->next = NULL; + stream->stream = NULL; + stream->indev = indev; + stream->outdev = outdev; + if (!stream->write_timer.timer_interface) { + if (switch_core_timer_init(&(stream->write_timer), + globals.timer_name, globals.codec_ms, globals.read_codec.implementation->samples_per_packet, + module_pool) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "setup timer failed!\n"); + switch_safe_free(stream); + return NULL; + } + } + inputParameters.device = indev; + if (indev != -1) { + inputParameters.channelCount = 1; + inputParameters.sampleFormat = SAMPLE_TYPE; + inputParameters.suggestedLatency = Pa_GetDeviceInfo(inputParameters.device)->defaultLowInputLatency; + inputParameters.hostApiSpecificStreamInfo = NULL; + } + outputParameters.device = outdev; outputParameters.channelCount = 1; outputParameters.sampleFormat = SAMPLE_TYPE; outputParameters.suggestedLatency = Pa_GetDeviceInfo(outputParameters.device)->defaultLowOutputLatency; outputParameters.hostApiSpecificStreamInfo = NULL; - //err = OpenAudioStream(&globals.audio_stream, NULL/*&inputParameters*/, &outputParameters, sample_rate, paClipOff, - //globals.read_codec.implementation->samples_per_packet); - err = OpenAudioStream(&globals.audio_stream, &inputParameters, &outputParameters, sample_rate, paClipOff, - globals.read_codec.implementation->samples_per_packet, globals.dual_streams); - /* UNLOCKED ************************************************************************************************* */ + + err = open_audio_stream(&(stream->stream), &inputParameters, &outputParameters); if (err != paNoError) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error opening audio device retrying\n"); switch_yield(1000000); - err = OpenAudioStream(&globals.audio_stream, &inputParameters, &outputParameters, sample_rate, paClipOff, - globals.read_codec.implementation->samples_per_packet, globals.dual_streams); + err = open_audio_stream(&(stream->stream), &inputParameters, &outputParameters); } - switch_mutex_unlock(globals.device_lock); - if (err != paNoError) { + switch_safe_free(stream); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't open audio device\n"); - switch_core_codec_destroy(&globals.read_codec); - switch_core_codec_destroy(&globals.write_codec); - switch_core_timer_destroy(&globals.read_timer); - switch_core_timer_destroy(&globals.write_timer); - switch_core_timer_destroy(&globals.hold_timer); if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_ERROR_AUDIO_DEV) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Reason", Pa_GetErrorText(err)); switch_event_fire(&event); } - return SWITCH_STATUS_FALSE; + return NULL; } - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Engage audio device rate: %d channels %d\n", sample_rate, outputParameters.channelCount); - - engage_ring_device(); - - return SWITCH_STATUS_SUCCESS; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Created audio stream: %d channels %d\n", globals.sample_rate, outputParameters.channelCount); + return stream; } -static switch_status_t engage_ring_device(void) +audio_stream_t *get_audio_stream(int indev, int outdev) { - PaStreamParameters outputParameters = { 0 }; - PaError err; - int sample_rate = globals.sample_rate; - int channels = 1; - - if (globals.ring_stream) { - return SWITCH_STATUS_SUCCESS; + audio_stream_t *stream; + if (outdev == -1) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error invalid output audio device\n"); } - - if (globals.ringdev == globals.outdev) { - if (engage_device(0) == SWITCH_STATUS_SUCCESS) { - globals.ring_stream = globals.audio_stream; - } else { - goto error; - } - } else { - switch_mutex_lock(globals.device_lock); - /* LOCKED ************************************************************************************************** */ - outputParameters.device = globals.ringdev; - outputParameters.channelCount = channels; - outputParameters.sampleFormat = SAMPLE_TYPE; - outputParameters.suggestedLatency = Pa_GetDeviceInfo(outputParameters.device)->defaultLowOutputLatency; - outputParameters.hostApiSpecificStreamInfo = NULL; - err = OpenAudioStream(&globals.ring_stream, NULL, - &outputParameters, sample_rate, paClipOff, globals.read_codec.implementation->samples_per_packet, globals.dual_streams); - /* UNLOCKED ************************************************************************************************* */ - switch_mutex_unlock(globals.device_lock); - - if (err != paNoError) { - goto error; - } + if (create_codecs(0) != SWITCH_STATUS_SUCCESS) { + return NULL; } - - switch_yield(10000); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Engage ring device rate: %d channels %d\n", sample_rate, channels); - return SWITCH_STATUS_SUCCESS; - - - error: - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't open ring device\n"); - return SWITCH_STATUS_FALSE; - + stream = find_audio_stream(indev, outdev, 0); + if (stream != NULL) { + return stream; + } + stream = create_audio_stream(indev, outdev); + if (stream) { + add_stream(stream, 0); + } + return stream; } static switch_status_t dtmf_call(char **argv, int argc, switch_stream_handle_t *stream) @@ -1523,6 +1817,211 @@ static switch_status_t dtmf_call(char **argv, int argc, switch_stream_handle_t * return SWITCH_STATUS_SUCCESS; } +static switch_status_t close_streams(char **argv, int argc, switch_stream_handle_t *stream) +{ + if (globals.call_list) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "ERROR: Cannot use this command this while a call is in progress\n"); + return SWITCH_STATUS_FALSE; + } + destroy_audio_streams(); + stream->write_function(stream, "closestreams all open streams closed\n"); + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t set_indev(char **argv, int argc, switch_stream_handle_t *stream) +{ + int devval; + + if (globals.call_list && ! globals.live_stream_switch) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "ERROR: Cannot use this command this while a call is in progress\n"); + return SWITCH_STATUS_FALSE; + } + if (*argv[0] == '#') { + devval = get_dev_by_number(argv[0] + 1, 1); + } else { + devval = get_dev_by_name(argv[0], 1); + } + if (devval < 0) { + stream->write_function(stream, "indev not set (invalid value)\n"); + return SWITCH_STATUS_FALSE; + } + globals.indev = devval; + switch_audio_stream(); + stream->write_function(stream, "indev set to %d\n", devval); + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t set_outdev(char **argv, int argc, switch_stream_handle_t *stream) +{ + int devval; + if (globals.call_list && ! globals.live_stream_switch) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "ERROR: Cannot use this command this while a call is in progress\n"); + return SWITCH_STATUS_FALSE; + } + if (*argv[0] == '#') { + devval = get_dev_by_number(argv[0] + 1, 0); + } else { + devval = get_dev_by_name(argv[0], 0); + } + if (devval < 0) { + stream->write_function(stream, "outdev not set (invalid value)\n"); + return SWITCH_STATUS_FALSE; + } + + globals.outdev = devval; + switch_audio_stream(); + stream->write_function(stream, "outdev set to %d\n", devval); + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t prepare_stream(char **argv, int argc, switch_stream_handle_t *stream) +{ + int devval=-2,devval2=-1; + if (! strcmp(argv[0], "#-1")) { + devval = -1; + } else if (*argv[0] == '#') { + devval = get_dev_by_number(argv[0]+1, 1); + } + if (devval == -2) { + stream->write_function(stream, "preparestream not prepared as indev has (invalid value)\n"); + return SWITCH_STATUS_FALSE; + } + if (*argv[1] == '#') { + devval2 = get_dev_by_number(argv[1]+1, 0); + } + if (devval2 == -1) { + stream->write_function(stream, "preparestream not prepared as outdev has (invalid value)\n"); + return SWITCH_STATUS_FALSE; + } + + if (! get_audio_stream(devval,devval2)) { + stream->write_function(stream, "preparestream not prepared received an invalid stream back\n"); + return SWITCH_STATUS_FALSE; + } + stream->write_function(stream, "preparestream prepared indev: %d outdev: %d\n", devval, devval2); + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t switch_stream(char **argv, int argc, switch_stream_handle_t *stream) +{ + int devval =-1, devval2 = -1; + if (globals.call_list && ! globals.live_stream_switch) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "ERROR: Cannot use this command this while a call is in progress\n"); + return SWITCH_STATUS_FALSE; + } + if (*argv[0] == '#') { + devval = get_dev_by_number(argv[0]+1, 1); + } + if (devval == -1) { + stream->write_function(stream, "switchstream not prepared as indev has (invalid value)\n"); + return SWITCH_STATUS_FALSE; + } + if (*argv[1] == '#') { + devval2 = get_dev_by_number(argv[1]+1, 0); + } + if (devval2 == -1) { + stream->write_function(stream, "switchstream not prepared as outdev has (invalid value)\n"); + return SWITCH_STATUS_FALSE; + } + globals.indev = devval; + globals.outdev = devval2; + if (switch_audio_stream() != SWITCH_STATUS_SUCCESS) { + stream->write_function(stream, "switchstream was unable to switch\n"); + return SWITCH_STATUS_FALSE; + } + stream->write_function(stream, "switchstream switched to indev: %d outdev: %d\n", devval, devval2); + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t set_ringdev(char **argv, int argc, switch_stream_handle_t *stream) +{ + int devval; + if (globals.call_list && ! globals.live_stream_switch) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "ERROR: Cannot use this command this while a call is in progress\n"); + return SWITCH_STATUS_FALSE; + } + if (! strcmp(argv[0], "#-1")) { + globals.ring_stream = NULL; + globals.ringdev = -1; + stream->write_function(stream, "ringdev set to %d\n", globals.ringdev); + return SWITCH_STATUS_SUCCESS; + } else if (*argv[0] == '#') { + devval = get_dev_by_number(argv[0] + 1, 0); + } else { + devval = get_dev_by_name(argv[0], 0); + } + if (devval == -1) { + stream->write_function(stream, "ringdev not set as dev has (invalid value)\n"); + return SWITCH_STATUS_FALSE; + } + globals.ringdev = devval; + stream->write_function(stream, "ringdev set to %d\n", globals.ringdev); + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t looptest(char **argv, int argc, switch_stream_handle_t *stream) +{ + int samples = 0; + int success = 0; + int i; + + if (globals.call_list) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "ERROR: Cannot use this command this while a call is in progress\n"); + return SWITCH_STATUS_FALSE; + } + if (validate_main_audio_stream() != SWITCH_STATUS_SUCCESS) { + stream->write_function(stream, "looptest Failed to engage audio device\n"); + return SWITCH_STATUS_FALSE; + } + globals.stream_in_use = 1; + for (i = 0; i < 400; i++) { + if (globals.destroying_streams || ! globals.main_stream->stream) { + break; + } + if ((samples = ReadAudioStream(globals.main_stream->stream, globals.read_frame.data, globals.read_codec.implementation->samples_per_packet, &globals.read_timer))) { + WriteAudioStream(globals.main_stream->stream, globals.read_frame.data, (long) samples, &(globals.main_stream->write_timer)); + success = 1; + } + switch_yield(10000); + } + globals.stream_in_use = 0; + + if (!success) { + stream->write_function(stream, "Failed to read any bytes from indev\n"); + return SWITCH_STATUS_FALSE; + } + destroy_audio_streams(); + stream->write_function(stream, "looptest complete\n"); + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t set_ringfile(char **argv, int argc, switch_stream_handle_t *stream) +{ + if (! argv[0]) { + stream->write_function(stream, "%s", globals.ring_file); + return SWITCH_STATUS_SUCCESS; + } + if (create_codecs(0) == SWITCH_STATUS_SUCCESS) { + switch_file_handle_t fh = { 0 }; + if (switch_core_file_open(&fh, + argv[0], + globals.read_codec.implementation->number_of_channels, + globals.read_codec.implementation->actual_samples_per_second, + SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) == SWITCH_STATUS_SUCCESS) { + switch_core_file_close(&fh); + set_global_ring_file(argv[0]); + } else { + stream->write_function(stream, "ringfile Unable to open ring file %s\n", argv[0]); + return SWITCH_STATUS_FALSE; + } + } else { + stream->write_function(stream, "ringfile Failed to init codecs device\n"); + return SWITCH_STATUS_FALSE; + } + stream->write_function(stream, "ringfile set to %s", globals.ring_file); + return SWITCH_STATUS_SUCCESS; +} + static switch_status_t switch_call(char **argv, int argc, switch_stream_handle_t *stream) { private_t *tp, *tech_pvt = NULL; @@ -1542,7 +2041,10 @@ static switch_status_t switch_call(char **argv, int argc, switch_stream_handle_t } } else if (!strcasecmp(callid, "none")) { for (tp = globals.call_list; tp; tp = tp->next) { + if (switch_test_flag(tp, TFLAG_MASTER)) { switch_clear_flag_locked(tp, TFLAG_MASTER); + create_hold_event(tp,0); + } } stream->write_function(stream, "OK\n"); goto done; @@ -1559,6 +2061,7 @@ static switch_status_t switch_call(char **argv, int argc, switch_stream_handle_t remove_pvt(tech_pvt); } add_pvt(tech_pvt, PA_MASTER); + create_hold_event(tech_pvt, 1); stream->write_function(stream, "OK\n"); } else { stream->write_function(stream, "NO SUCH CALL\n"); @@ -1609,7 +2112,6 @@ static switch_status_t answer_call(char **argv, int argc, switch_stream_handle_t switch_channel_t *channel = switch_core_session_get_channel(tp->session); switch_set_flag_locked(tp, TFLAG_ANSWER); add_pvt(tp, PA_MASTER); - deactivate_ring_device(); switch_channel_mark_answered(channel); } } else { @@ -1624,7 +2126,6 @@ static switch_status_t answer_call(char **argv, int argc, switch_stream_handle_t switch_channel_t *channel = switch_core_session_get_channel(tp->session); switch_set_flag_locked(tp, TFLAG_ANSWER); add_pvt(tp, PA_MASTER); - deactivate_ring_device(); switch_channel_mark_answered(channel); x++; break; @@ -1766,7 +2267,6 @@ static switch_status_t place_call(char **argv, int argc, switch_stream_handle_t channel = switch_core_session_get_channel(session); switch_core_session_set_private(session, tech_pvt); tech_pvt->session = session; - globals.flags = GFLAG_EAR | GFLAG_MOUTH; } else { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Hey where is my memory pool?\n"); switch_core_session_destroy(&session); @@ -1805,9 +2305,8 @@ static switch_status_t place_call(char **argv, int argc, switch_stream_handle_t switch_channel_set_caller_profile(channel, tech_pvt->caller_profile); } tech_pvt->session = session; - if ((status = engage_device(0)) == SWITCH_STATUS_SUCCESS) { + if ((status = validate_main_audio_stream()) == SWITCH_STATUS_SUCCESS) { switch_set_flag_locked(tech_pvt, TFLAG_ANSWER); - deactivate_ring_device(); switch_channel_mark_answered(channel); switch_channel_set_state(channel, CS_INIT); if (switch_core_session_thread_launch(tech_pvt->session) != SWITCH_STATUS_SUCCESS) { @@ -1855,10 +2354,11 @@ SWITCH_STANDARD_API(pa_cmd) { char *argv[1024] = { 0 }; int argc = 0; - char *mycmd = NULL, *devname = NULL; + char *mycmd = NULL; switch_status_t status = SWITCH_STATUS_SUCCESS; pa_command_t func = NULL; - int lead = 1, devval = 0; + int devval; + int lead = 1; char *wcmd = NULL, *action = NULL; char cmd_buf[1024] = ""; char *http = NULL; @@ -1878,9 +2378,15 @@ SWITCH_STANDARD_API(pa_cmd) "pa devlist [xml]\n" "pa indev #|\n" "pa outdev #|\n" + "pa preparestream # #\n" + "pa switchstream # #\n" + "pa closestreams\n" "pa ringdev #|\n" - "pa play [ringtest|]\n" - "pa ringfile [filename]\n" "pa looptest\n" "--------------------------------------------------------------------------------\n"; + "pa play [ringtest|] [seconds] [no_close]\n" + "pa playdev # [ringtest|] [seconds] [no_close]\n" + "pa ringfile [filename]\n" + "pa looptest\n" + "--------------------------------------------------------------------------------\n"; if (stream->param_event) { @@ -1973,169 +2479,42 @@ SWITCH_STANDARD_API(pa_cmd) func = switch_call; } else if (!strcasecmp(argv[0], "dtmf")) { func = dtmf_call; + } else if (!strcasecmp(argv[0], "closestreams")) { + func = close_streams; } else if (argv[1] && !strcmp(argv[0], "indev")) { - - if (globals.call_list) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "ERROR: Cannot use this command this while a call is in progress\n"); - goto done; - } - - if (*argv[1] == '#') { - devval = get_dev_by_number(argv[1] + 1, 1); - } else { - devval = get_dev_by_name(argv[1], 1); - } - devname = "indev"; - if (devval > -1) { - globals.indev = devval; - //engage_device(1); - } + func = set_indev; } else if (argv[1] && !strcmp(argv[0], "outdev")) { - - if (globals.call_list) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "ERROR: Cannot use this command this while a call is in progress\n"); - goto done; - } - - if (*argv[1] == '#') { - devval = get_dev_by_number(argv[1] + 1, 0); - } else { - devval = get_dev_by_name(argv[1], 0); - } - devname = "outdev"; - if (devval > -1) { - globals.outdev = devval; - //engage_device(1); - } + func = set_outdev; + } else if (argv[1] && argv[2] && !strcmp(argv[0], "preparestream")) { + func = prepare_stream; + } else if (argv[1] && argv[2] && !strcmp(argv[0], "switchstream")) { + func = switch_stream; } else if (argv[1] && !strcmp(argv[0], "ringdev")) { - - if (globals.call_list) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "ERROR: Cannot use this command this while a call is in progress\n"); - goto done; - } - - if (*argv[1] == '#') { - devval = get_dev_by_number(argv[1] + 1, 0); - } else { - devval = get_dev_by_name(argv[1], 0); - } - devname = "ringdev"; - if (devval > -1) { - globals.ringdev = devval; - //engage_device(1); - } - } else if ((argv[1] && !strcasecmp(argv[0], "play"))) { - switch_file_handle_t fh = { 0 }; - char *playfile = NULL; - int samples = 0; - int seconds = 5; - int wrote = 0; - - if (globals.call_list) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "ERROR: Cannot use this command this while a call is in progress\n"); - goto done; - } - - if (!strcasecmp(argv[1], "ringtest")) { - playfile = globals.ring_file; - } else { - playfile = argv[1]; - } - - fh.pre_buffer_datalen = SWITCH_DEFAULT_FILE_BUFFER_LEN; - if (engage_device(0) == SWITCH_STATUS_SUCCESS) { - if (switch_core_file_open(&fh, - playfile, - globals.read_codec.implementation->number_of_channels, - globals.read_codec.implementation->actual_samples_per_second, - SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) == SWITCH_STATUS_SUCCESS) { - switch_size_t olen = globals.read_codec.implementation->samples_per_packet; - int16_t abuf[2048]; - - if (argv[2]) { - int i = atoi(argv[2]); - if (i >= 0) { - seconds = i; - } - } - - samples = globals.read_codec.implementation->actual_samples_per_second * seconds; - while (switch_core_file_read(&fh, abuf, &olen) == SWITCH_STATUS_SUCCESS) { - WriteAudioStream(globals.audio_stream, abuf, (long) olen, &globals.read_timer); - wrote += (int) olen; - if (samples) { - samples -= (int) olen; - if (samples <= 0) { - break; - } - } - olen = globals.read_codec.implementation->samples_per_packet; - } - - switch_core_file_close(&fh); - deactivate_audio_device(); - - seconds = wrote / globals.read_codec.implementation->actual_samples_per_second; - stream->write_function(stream, "playback test [%s] %d second(s) %d samples @%dkhz", - playfile, seconds, wrote, globals.read_codec.implementation->actual_samples_per_second); - - - } else { - stream->write_function(stream, "Cannot play requested file %s\n", argv[1]); - } - } else { + func = set_ringdev; + } else if ((argv[1] && !strcmp(argv[0], "play"))) { + if (validate_main_audio_stream() == SWITCH_STATUS_SUCCESS) { + play_dev(stream, globals.main_stream ? globals.main_stream->outdev : -1,argv[1],argv[2], argv[3]); + }else{ stream->write_function(stream, "Failed to engage audio device\n"); } goto done; + } else if ((argv[1] && argv[2] && !strcmp(argv[0], "playdev"))) { + if (*argv[1] == '#') { + devval = get_dev_by_number(argv[1] + 1, 0); + } else { + devval = -1; + } + play_dev(stream, devval,argv[2],argv[3],argv[4]); + goto done; } else if (!strcasecmp(argv[0], "looptest")) { - if (globals.call_list) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "ERROR: Cannot use this command this while a call is in progress\n"); - goto done; - } - - if (engage_device(0) == SWITCH_STATUS_SUCCESS) { - int samples = 0; - int success = 0; - int i; - for (i = 0; i < 400; i++) { - if ((samples = ReadAudioStream(globals.audio_stream, globals.read_frame.data, - globals.read_codec.implementation->samples_per_packet, &globals.read_timer))) { - WriteAudioStream(globals.audio_stream, globals.read_frame.data, (long) samples, &globals.write_timer); - success = 1; - } - switch_yield(10000); - } - if (!success) { - stream->write_function(stream, "Failed to read any bytes from indev\n"); - } - deactivate_audio_device(); - } else { - stream->write_function(stream, "Failed to engage audio device\n"); - } - goto done; + func = looptest; } else if (!strcasecmp(argv[0], "ringfile")) { - if (argv[1]) { - if (engage_device(0) == SWITCH_STATUS_SUCCESS) { - switch_file_handle_t fh = { 0 }; - if (switch_core_file_open(&fh, - argv[1], - globals.read_codec.implementation->number_of_channels, - globals.read_codec.implementation->actual_samples_per_second, - SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) == SWITCH_STATUS_SUCCESS) { - switch_core_file_close(&fh); - set_global_ring_file(argv[1]); - } else { - stream->write_function(stream, "Unable to open ring file %s\n", argv[1]); - } - } else { - stream->write_function(stream, "Failed to engage audio device\n"); - } - } else { - stream->write_function(stream, "%s", globals.ring_file); - } - goto done; + func = set_ringfile; + } else { + stream->write_function(stream, "Unknown Command or not enough args [%s]\n", argv[0]); } + if (func) { if (http) { stream->write_function(stream, "
");
@@ -2143,21 +2522,12 @@ SWITCH_STANDARD_API(pa_cmd)
 
 		switch_mutex_lock(globals.pa_mutex);
 		status = func(&argv[lead], argc - lead, stream);
+		status = SWITCH_STATUS_SUCCESS; /*if func was defined we want to always return success as the command was found */
 		switch_mutex_unlock(globals.pa_mutex);
 
 		if (http) {
 			stream->write_function(stream, "\n\n
"); } - } else { - if (devname) { - if (devval > -1) { - stream->write_function(stream, "%s set to %d\n", devname, devval); - } else { - stream->write_function(stream, "%s not set (invalid value)\n", devname); - } - } else { - stream->write_function(stream, "Unknown Command [%s]\n", argv[0]); - } } done: @@ -2171,6 +2541,14 @@ SWITCH_STANDARD_API(pa_cmd) " " " " " " + " " + " " + " " + " " + " " + " " + " " + " " "

" "\n" "" From e79174cacf6abb943fe34840a5261b940b281c91 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 3 Feb 2011 19:32:14 -0600 Subject: [PATCH 05/36] fix regression from d72cde9b76a856cf002366300bea02c26db44ffb --- src/switch_core_session.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/switch_core_session.c b/src/switch_core_session.c index 4836aae73f..d2e28de523 100644 --- a/src/switch_core_session.c +++ b/src/switch_core_session.c @@ -1865,6 +1865,17 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_get_app_flags(const char *ap SWITCH_DECLARE(switch_status_t) switch_core_session_execute_application_async(switch_core_session_t *session, const char *app, const char *arg) { switch_event_t *execute_event; + char *ap, *arp; + + if (!arg && strstr(app, "::")) { + ap = switch_core_session_strdup(session, app); + app = ap; + + if ((arp = strstr(ap, "::"))) { + *arp = '\0'; + arg = arp + 2; + } + } if (switch_event_create(&execute_event, SWITCH_EVENT_COMMAND) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "call-command", "execute"); @@ -1894,6 +1905,10 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_execute_application_get_flag switch_application_interface_t *application_interface; switch_status_t status = SWITCH_STATUS_SUCCESS; + if (!arg && strstr(app, "::")) { + return switch_core_session_execute_application_async(session, app, arg); + } + if (switch_channel_down(session->channel)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Channel is hungup, aborting execution of application: %s\n", app); return SWITCH_STATUS_FALSE; From bdf678e401a8077aab06b9c04004c92ef6631e26 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 3 Feb 2011 20:12:36 -0600 Subject: [PATCH 06/36] dont run execute_on_fsk when there was no data collected --- src/mod/applications/mod_fsk/mod_fsk.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/mod/applications/mod_fsk/mod_fsk.c b/src/mod/applications/mod_fsk/mod_fsk.c index 9802353075..0291707c62 100644 --- a/src/mod/applications/mod_fsk/mod_fsk.c +++ b/src/mod/applications/mod_fsk/mod_fsk.c @@ -220,6 +220,7 @@ static switch_bool_t fsk_detect_callback(switch_media_bug_t *bug, void *user_dat char *sp; switch_event_t *event; const char *app_var; + int total = 0; switch_event_create_plain(&event, SWITCH_EVENT_CHANNEL_DATA); @@ -255,6 +256,7 @@ static switch_bool_t fsk_detect_callback(switch_media_bug_t *bug, void *user_dat } if (varname && val) { + total++; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_DEBUG, "%s setting FSK var [%s][%s]\n", switch_channel_get_name(channel), varname, val); switch_channel_set_variable(channel, varname, val); @@ -270,7 +272,7 @@ static switch_bool_t fsk_detect_callback(switch_media_bug_t *bug, void *user_dat } } - if ((app_var = switch_channel_get_variable(channel, "execute_on_fsk"))) { + if (total && (app_var = switch_channel_get_variable(channel, "execute_on_fsk"))) { char *app_arg; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_DEBUG, "%s processing execute_on_fsk [%s]\n", From dc436b82a52da05686ac178ad7854556e9688ed8 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 3 Feb 2011 20:42:17 -0600 Subject: [PATCH 07/36] block control-z from fs cli and print a warning how to exit properly --- libs/esl/fs_cli.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/libs/esl/fs_cli.c b/libs/esl/fs_cli.c index 1e3bf04ca1..19e8d7f82a 100644 --- a/libs/esl/fs_cli.c +++ b/libs/esl/fs_cli.c @@ -8,6 +8,7 @@ #include #define CMD_BUFLEN 1024 +static int WARN_STOP = 0; #ifdef WIN32 #define strdup(src) _strdup(src) @@ -535,6 +536,13 @@ static BOOL console_readConsole(HANDLE conIn, char* buf, int len, int* pRed, int static void handle_SIGINT(int sig) { if (sig); + + WARN_STOP = 1; + + signal(SIGINT, handle_SIGINT); +#ifdef SIGTSTP + signal(SIGTSTP, handle_SIGINT); +#endif return; } @@ -581,6 +589,12 @@ static void *msg_thread_run(esl_thread_t *me, void *obj) while(thread_running && handle->connected) { esl_status_t status = esl_recv_event_timed(handle, 10, 1, NULL); + + if (WARN_STOP) { + printf("Type control-D or /exit or /quit or /bye to exit.\n\n"); + WARN_STOP = 0; + } + if (status == ESL_FAIL) { esl_log(ESL_LOG_WARNING, "Disconnected.\n"); running = -1; thread_running = 0; @@ -1023,6 +1037,9 @@ int main(int argc, char *argv[]) } signal(SIGINT, handle_SIGINT); +#ifdef SIGTSTP + signal(SIGTSTP, handle_SIGINT); +#endif #ifdef SIGQUIT signal(SIGQUIT, handle_SIGQUIT); #endif From 2d190b37abe00999a2e76861b8c88f0053e0b78f Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Thu, 3 Feb 2011 23:46:19 -0600 Subject: [PATCH 08/36] fix iLBC under windows --- libs/ilbc/src/iLBC_decode.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libs/ilbc/src/iLBC_decode.c b/libs/ilbc/src/iLBC_decode.c index fc46fe408c..9fc7a24bb4 100644 --- a/libs/ilbc/src/iLBC_decode.c +++ b/libs/ilbc/src/iLBC_decode.c @@ -47,7 +47,9 @@ { fld dbl frndint + fstp dbl } + return (long int) dbl; } #elif defined (_WIN64) #include From b6ac001276961761b14a89270da02498b4d3e740 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 4 Feb 2011 08:44:11 -0600 Subject: [PATCH 09/36] fix regression from f60fdf653dd2d7f8d3eaa6a9086e1f68bd993c59 --- src/mod/applications/mod_dptools/mod_dptools.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c index 4be2a64f61..0b16492e14 100755 --- a/src/mod/applications/mod_dptools/mod_dptools.c +++ b/src/mod/applications/mod_dptools/mod_dptools.c @@ -2887,7 +2887,7 @@ static switch_call_cause_t user_outgoing_channel(switch_core_session_t *session, switch_call_cause_t *cancel_cause) { switch_xml_t x_domain = NULL, xml = NULL, x_user = NULL, x_group = NULL, x_param, x_params; - char *user = NULL, *domain = NULL; + char *user = NULL, *domain = NULL, *dup_domain = NULL; const char *dest = NULL; static switch_call_cause_t cause = SWITCH_CAUSE_NONE; unsigned int timelimit = 60; @@ -2908,7 +2908,8 @@ static switch_call_cause_t user_outgoing_channel(switch_core_session_t *session, if ((domain = strchr(user, '@'))) { *domain++ = '\0'; } else { - domain = switch_core_get_variable_pdup("domain", switch_core_session_get_pool(session)); + domain = switch_core_get_variable_dup("domain"); + dup_domain = domain; } if (!domain) { @@ -3115,6 +3116,7 @@ static switch_call_cause_t user_outgoing_channel(switch_core_session_t *session, } switch_safe_free(user); + switch_safe_free(dup_domain); return cause; } From 46f6c6e42d2775ccfecb8f445ebbaaf32ab34df7 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 4 Feb 2011 08:56:30 -0600 Subject: [PATCH 10/36] fix regression from f60fdf653dd2d7f8d3eaa6a9086e1f68bd993c59 --- src/mod/applications/mod_dptools/mod_dptools.c | 4 +++- .../dialplans/mod_dialplan_asterisk/mod_dialplan_asterisk.c | 6 +++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c index 0b16492e14..f7bf86b4c7 100755 --- a/src/mod/applications/mod_dptools/mod_dptools.c +++ b/src/mod/applications/mod_dptools/mod_dptools.c @@ -2774,7 +2774,7 @@ static switch_call_cause_t group_outgoing_channel(switch_core_session_t *session switch_originate_flag_t myflags = SOF_NONE; char *cid_name_override = NULL; char *cid_num_override = NULL; - char *domain = NULL; + char *domain = NULL, *dup_domain = NULL; switch_channel_t *new_channel = NULL; unsigned int timelimit = 60; const char *skip, *var; @@ -2788,6 +2788,7 @@ static switch_call_cause_t group_outgoing_channel(switch_core_session_t *session *domain++ = '\0'; } else { domain = switch_core_get_variable_pdup("domain", switch_core_session_get_pool(session)); + dup_domain = domain; } if (!domain) { @@ -2859,6 +2860,7 @@ static switch_call_cause_t group_outgoing_channel(switch_core_session_t *session switch_safe_free(template); switch_safe_free(group); + switch_safe_free(dup_domain); if (cause == SWITCH_CAUSE_NONE) { cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; diff --git a/src/mod/dialplans/mod_dialplan_asterisk/mod_dialplan_asterisk.c b/src/mod/dialplans/mod_dialplan_asterisk/mod_dialplan_asterisk.c index 43534dadba..3bc5cb4a3d 100644 --- a/src/mod/dialplans/mod_dialplan_asterisk/mod_dialplan_asterisk.c +++ b/src/mod/dialplans/mod_dialplan_asterisk/mod_dialplan_asterisk.c @@ -309,11 +309,13 @@ static switch_call_cause_t sip_outgoing_channel(switch_core_session_t *session, switch_call_cause_t *cancel_cause) { const char *profile; + char *dup_profile = NULL; if (session) { profile = switch_channel_get_variable(switch_core_session_get_channel(session), "sip_profile"); } else { - profile = switch_core_get_variable_pdup("sip_profile", switch_core_session_get_pool(session)); + dup_profile = switch_core_get_variable_dup("sip_profile"); + profile = dup_profile; } if (zstr(profile)) { profile = "default"; @@ -323,6 +325,8 @@ static switch_call_cause_t sip_outgoing_channel(switch_core_session_t *session, UNPROTECT_INTERFACE(sip_endpoint_interface); + switch_safe_free(dup_profile); + return switch_core_session_outgoing_channel(session, var_event, "sofia", outbound_profile, new_session, pool, SOF_NONE, cancel_cause); } From 2ec2a9b0d335a8d6a30ab5a92448ac3ad63649ff Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 4 Feb 2011 09:40:04 -0600 Subject: [PATCH 11/36] skip blocking writes on fs_cli to avoid backing up event socket --- libs/esl/fs_cli.c | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/libs/esl/fs_cli.c b/libs/esl/fs_cli.c index 19e8d7f82a..a70d63fab5 100644 --- a/libs/esl/fs_cli.c +++ b/libs/esl/fs_cli.c @@ -589,22 +589,36 @@ static void *msg_thread_run(esl_thread_t *me, void *obj) while(thread_running && handle->connected) { esl_status_t status = esl_recv_event_timed(handle, 10, 1, NULL); - - if (WARN_STOP) { - printf("Type control-D or /exit or /quit or /bye to exit.\n\n"); - WARN_STOP = 0; - } + int aok = 1; if (status == ESL_FAIL) { - esl_log(ESL_LOG_WARNING, "Disconnected.\n"); + if (aok) esl_log(ESL_LOG_WARNING, "Disconnected.\n"); running = -1; thread_running = 0; } else if (status == ESL_SUCCESS) { +#ifndef WIN32 + fd_set can_write; + int fd; + struct timeval to; + + fd = fileno(stdout); + memset(&to, 0, sizeof(to)); + FD_ZERO(&can_write); + FD_SET(fd, &can_write); + to.tv_sec = 0; + to.tv_usec = 100000; + if (select(fd + 1, NULL, &can_write, NULL, &to) > 0) { + aok = FD_ISSET(fd, &can_write); + } else { + aok = 0; + } +#endif + if (handle->last_event) { const char *type = esl_event_get_header(handle->last_event, "content-type"); int known = 0; if (!esl_strlen_zero(type)) { - if (!strcasecmp(type, "log/data")) { + if (aok && !strcasecmp(type, "log/data")) { const char *userdata = esl_event_get_header(handle->last_event, "user-data"); if (esl_strlen_zero(userdata) || esl_strlen_zero(filter_uuid) || !strcasecmp(filter_uuid, userdata)) { @@ -631,7 +645,7 @@ static void *msg_thread_run(esl_thread_t *me, void *obj) } else if (!strcasecmp(type, "text/disconnect-notice")) { running = -1; thread_running = 0; known++; - } else if (!strcasecmp(type, "text/event-plain")) { + } else if (aok && !strcasecmp(type, "text/event-plain")) { char *foo; esl_event_serialize(handle->last_ievent, &foo, ESL_FALSE); printf("RECV EVENT\n%s\n", foo); @@ -641,7 +655,7 @@ static void *msg_thread_run(esl_thread_t *me, void *obj) } } - if (!known) { + if (aok && !known) { char *foo; printf("INCOMING DATA [%s]\n%s\n", type, handle->last_event->body ? handle->last_event->body : ""); esl_event_serialize(handle->last_event, &foo, ESL_FALSE); @@ -651,6 +665,11 @@ static void *msg_thread_run(esl_thread_t *me, void *obj) } } + if (WARN_STOP) { + if (aok) printf("Type control-D or /exit or /quit or /bye to exit.\n\n"); + WARN_STOP = 0; + } + usleep(1000); } From 36f6218b8bba3233cf3fb501b01a0288a08e9f00 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 4 Feb 2011 10:58:26 -0600 Subject: [PATCH 12/36] add sanity check on jitterbuffer debug --- src/switch_rtp.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/switch_rtp.c b/src/switch_rtp.c index e8d7558bce..4df867aa64 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -1875,6 +1875,10 @@ static void jb_logger(const char *file, const char *func, int line, int level, c SWITCH_DECLARE(switch_status_t) switch_rtp_debug_jitter_buffer(switch_rtp_t *rtp_session, const char *name) { + if (!switch_rtp_ready(rtp_session)) { + return SWITCH_STATUS_FALSE; + } + stfu_n_debug(rtp_session->jb, name); stfu_global_set_logger(jb_logger); From e9e33f5160fb5272c4f912dac6a29415215bba1c Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Fri, 4 Feb 2011 12:48:07 -0600 Subject: [PATCH 13/36] FS-3033 VS2010 libportaudio project improvements for DirectX builds and switch to build DirectX by default --- Freeswitch.2010.sln | 24 ++-- .../build/msvc/portaudio.2010.vcxproj | 136 ++++-------------- 2 files changed, 43 insertions(+), 117 deletions(-) diff --git a/Freeswitch.2010.sln b/Freeswitch.2010.sln index edee701d51..464cb2e273 100644 --- a/Freeswitch.2010.sln +++ b/Freeswitch.2010.sln @@ -1569,18 +1569,18 @@ Global {0A18A071-125E-442F-AFF7-A3F68ABECF99}.All|x64 Setup.ActiveCfg = Release DirectSound|x64 {0A18A071-125E-442F-AFF7-A3F68ABECF99}.All|x64 Setup.Build.0 = Release DirectSound|x64 {0A18A071-125E-442F-AFF7-A3F68ABECF99}.All|x86 Setup.ActiveCfg = Release DirectSound|x64 - {0A18A071-125E-442F-AFF7-A3F68ABECF99}.Debug|Win32.ActiveCfg = Debug|Win32 - {0A18A071-125E-442F-AFF7-A3F68ABECF99}.Debug|Win32.Build.0 = Debug|Win32 - {0A18A071-125E-442F-AFF7-A3F68ABECF99}.Debug|x64.ActiveCfg = Debug|x64 - {0A18A071-125E-442F-AFF7-A3F68ABECF99}.Debug|x64.Build.0 = Debug|x64 - {0A18A071-125E-442F-AFF7-A3F68ABECF99}.Debug|x64 Setup.ActiveCfg = Debug|x64 - {0A18A071-125E-442F-AFF7-A3F68ABECF99}.Debug|x86 Setup.ActiveCfg = Debug|Win32 - {0A18A071-125E-442F-AFF7-A3F68ABECF99}.Release|Win32.ActiveCfg = Release|Win32 - {0A18A071-125E-442F-AFF7-A3F68ABECF99}.Release|Win32.Build.0 = Release|Win32 - {0A18A071-125E-442F-AFF7-A3F68ABECF99}.Release|x64.ActiveCfg = Release|x64 - {0A18A071-125E-442F-AFF7-A3F68ABECF99}.Release|x64.Build.0 = Release|x64 - {0A18A071-125E-442F-AFF7-A3F68ABECF99}.Release|x64 Setup.ActiveCfg = Release|x64 - {0A18A071-125E-442F-AFF7-A3F68ABECF99}.Release|x86 Setup.ActiveCfg = Release|Win32 + {0A18A071-125E-442F-AFF7-A3F68ABECF99}.Debug|Win32.ActiveCfg = Debug DirectSound|Win32 + {0A18A071-125E-442F-AFF7-A3F68ABECF99}.Debug|Win32.Build.0 = Debug DirectSound|Win32 + {0A18A071-125E-442F-AFF7-A3F68ABECF99}.Debug|x64.ActiveCfg = Debug DirectSound|x64 + {0A18A071-125E-442F-AFF7-A3F68ABECF99}.Debug|x64.Build.0 = Debug DirectSound|x64 + {0A18A071-125E-442F-AFF7-A3F68ABECF99}.Debug|x64 Setup.ActiveCfg = Debug DirectSound|x64 + {0A18A071-125E-442F-AFF7-A3F68ABECF99}.Debug|x86 Setup.ActiveCfg = Debug DirectSound|Win32 + {0A18A071-125E-442F-AFF7-A3F68ABECF99}.Release|Win32.ActiveCfg = Release DirectSound|Win32 + {0A18A071-125E-442F-AFF7-A3F68ABECF99}.Release|Win32.Build.0 = Release DirectSound|Win32 + {0A18A071-125E-442F-AFF7-A3F68ABECF99}.Release|x64.ActiveCfg = Release DirectSound|x64 + {0A18A071-125E-442F-AFF7-A3F68ABECF99}.Release|x64.Build.0 = Release DirectSound|x64 + {0A18A071-125E-442F-AFF7-A3F68ABECF99}.Release|x64 Setup.ActiveCfg = Release DirectSound|x64 + {0A18A071-125E-442F-AFF7-A3F68ABECF99}.Release|x86 Setup.ActiveCfg = Release DirectSound|Win32 {08DAD348-9E0A-4A2E-97F1-F1E7E24A7836}.All|Win32.ActiveCfg = Release|x64 {08DAD348-9E0A-4A2E-97F1-F1E7E24A7836}.All|x64.ActiveCfg = Release|x64 {08DAD348-9E0A-4A2E-97F1-F1E7E24A7836}.All|x64.Build.0 = Release|x64 diff --git a/libs/portaudio/build/msvc/portaudio.2010.vcxproj b/libs/portaudio/build/msvc/portaudio.2010.vcxproj index b4eca56713..10b4c25fd9 100644 --- a/libs/portaudio/build/msvc/portaudio.2010.vcxproj +++ b/libs/portaudio/build/msvc/portaudio.2010.vcxproj @@ -41,11 +41,11 @@ - DynamicLibrary + StaticLibrary false - DynamicLibrary + StaticLibrary false @@ -57,11 +57,11 @@ false - DynamicLibrary + StaticLibrary false - DynamicLibrary + StaticLibrary false @@ -77,9 +77,11 @@ + + @@ -92,10 +94,12 @@ + + @@ -110,18 +114,6 @@ <_ProjectFileVersion>10.0.30319.1 - $(Configuration)\ - $(Configuration)\ - true - $(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\ - true - $(Configuration)\ - $(Configuration)\ - false - $(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\ - false @@ -231,45 +223,23 @@ true true Win32 - .\Debug_x86/portaudio.tlb - - Disabled ..\..\src\common;..\..\include;.\;..\..\src\os\win;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_USRDLL;PA_ENABLE_DEBUG_OUTPUT;_CRT_SECURE_NO_DEPRECATE;PA_NO_ASIO;PAWIN_USE_WDMKS_DEVICE_INFO;%(PreprocessorDefinitions) + WIN32;_DEBUG;_USRDLL;PA_ENABLE_DEBUG_OUTPUT;_CRT_SECURE_NO_DEPRECATE;PA_NO_ASIO;PA_NO_WMME;PAWIN_USE_WDMKS_DEVICE_INFO;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebugDLL - $(Platform)\$(Configuration)/portaudio.pch - $(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\ Level3 true - ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0409 - - ksuser.lib;%(AdditionalDependencies) - $(Platform)\$(Configuration)\portaudio_x86.dll - true - .\portaudio.def - true - $(Platform)\$(Configuration)\portaudio_x86.pdb - false - - - $(Platform)\$(Configuration)\portaudio_x86.lib - MachineX86 - true - $(Platform)\$(Configuration)\portaudio.bsc @@ -278,45 +248,23 @@ true true X64 - .\Debug_x86/portaudio.tlb - - Disabled ..\..\src\common;..\..\include;.\;..\..\src\os\win;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_USRDLL;PA_ENABLE_DEBUG_OUTPUT;_CRT_SECURE_NO_DEPRECATE;PAWIN_USE_WDMKS_DEVICE_INFO;%(PreprocessorDefinitions) + WIN32;_DEBUG;_USRDLL;PA_ENABLE_DEBUG_OUTPUT;_CRT_SECURE_NO_DEPRECATE;PA_NO_ASIO;PA_NO_WMME;PAWIN_USE_WDMKS_DEVICE_INFO;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebugDLL - $(Platform)\$(Configuration)\portaudio.pch - $(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\ Level3 true - ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0409 - - ksuser.lib;%(AdditionalDependencies) - $(Platform)\$(Configuration)\portaudio_x64.dll - true - .\portaudio.def - true - $(Platform)\$(Configuration)/portaudio_x64.pdb - false - - - $(Platform)\$(Configuration)\portaudio_x64.lib - MachineX64 - true - $(Platform)\$(Configuration)/portaudio_x64.bsc @@ -325,22 +273,15 @@ true true Win32 - .\Release_x86/portaudio.tlb - - MaxSpeed - OnlyExplicitInline + Default ..\..\src\common;..\..\include;.\;..\..\src\os\win;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_USRDLL;PA_ENABLE_DEBUG_OUTPUT;_CRT_SECURE_NO_DEPRECATE;PA_NO_ASIO;%(PreprocessorDefinitions) + WIN32;NDEBUG;_USRDLL;PA_ENABLE_DEBUG_OUTPUT;_CRT_SECURE_NO_DEPRECATE;PA_NO_ASIO;PA_NO_WMME;%(PreprocessorDefinitions) true MultiThreadedDLL true - $(Platform)\$(Configuration)/portaudio.pch - $(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\ Level3 true @@ -348,20 +289,8 @@ NDEBUG;%(PreprocessorDefinitions) 0x0409 - - $(Platform)\$(Configuration)\portaudio_x86.dll - true - .\portaudio.def - $(Platform)\$(Configuration)\portaudio_x86.pdb - false - - - $(Platform)\$(Configuration)\portaudio_x86.lib - MachineX86 - true - $(Platform)\$(Configuration)\portaudio.bsc @@ -370,22 +299,15 @@ true true X64 - .\Release_x86/portaudio.tlb - - MaxSpeed - OnlyExplicitInline - ..\..\src\common;..\..\include;.\;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_USRDLL;PA_ENABLE_DEBUG_OUTPUT;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) + Default + ..\..\src\common;..\..\include;.\;..\..\src\os\win;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_USRDLL;PA_ENABLE_DEBUG_OUTPUT;_CRT_SECURE_NO_DEPRECATE;PA_NO_ASIO;PA_NO_WMME;%(PreprocessorDefinitions) true MultiThreadedDLL true - $(Platform)\$(Configuration)\portaudio.pch - $(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\ Level3 true @@ -393,20 +315,8 @@ NDEBUG;%(PreprocessorDefinitions) 0x0409 - - $(Platform)\$(Configuration)\portaudio_x64.dll - true - .\portaudio.def - $(Platform)\$(Configuration)/portaudio_x64.pdb - false - - - $(Platform)\$(Configuration)/portaudio_x64.lib - MachineX64 - true - $(Platform)\$(Configuration)\portaudio_x64.bsc @@ -594,6 +504,7 @@ true ..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories) %(PreprocessorDefinitions) + true ..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories) %(PreprocessorDefinitions) true @@ -605,6 +516,7 @@ true ..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories) %(PreprocessorDefinitions) + true ..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories) %(PreprocessorDefinitions) true @@ -618,6 +530,7 @@ true ..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories) %(PreprocessorDefinitions) + true ..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories) %(PreprocessorDefinitions) true @@ -629,6 +542,7 @@ true ..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories) %(PreprocessorDefinitions) + true ..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories) %(PreprocessorDefinitions) true @@ -642,6 +556,7 @@ true ..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories) %(PreprocessorDefinitions) + true ..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories) %(PreprocessorDefinitions) true @@ -653,6 +568,7 @@ true ..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories) %(PreprocessorDefinitions) + true ..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories) %(PreprocessorDefinitions) true @@ -666,6 +582,7 @@ true ..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories) %(PreprocessorDefinitions) + true ..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories) %(PreprocessorDefinitions) true @@ -677,6 +594,7 @@ true ..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories) %(PreprocessorDefinitions) + true ..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories) %(PreprocessorDefinitions) true @@ -690,6 +608,7 @@ true ..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories) %(PreprocessorDefinitions) + true ..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories) %(PreprocessorDefinitions) true @@ -701,6 +620,7 @@ true ..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories) %(PreprocessorDefinitions) + true ..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories) %(PreprocessorDefinitions) true @@ -714,6 +634,7 @@ true ..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories) %(PreprocessorDefinitions) + true ..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories) %(PreprocessorDefinitions) true @@ -725,6 +646,7 @@ true ..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories) %(PreprocessorDefinitions) + true ..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories) %(PreprocessorDefinitions) true @@ -738,6 +660,7 @@ true ..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories) %(PreprocessorDefinitions) + true ..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories) %(PreprocessorDefinitions) true @@ -749,6 +672,7 @@ true ..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories) %(PreprocessorDefinitions) + true ..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories) %(PreprocessorDefinitions) true @@ -762,6 +686,7 @@ true ..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories) %(PreprocessorDefinitions) + true ..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories) %(PreprocessorDefinitions) true @@ -773,6 +698,7 @@ true ..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories) %(PreprocessorDefinitions) + true ..\..\src\hostapi\asio\ASIOSDK\host;..\..\src\hostapi\asio\ASIOSDK\host\pc;..\..\src\hostapi\asio\ASIOSDK\common;%(AdditionalIncludeDirectories) %(PreprocessorDefinitions) true From f4481b05ab8ae1faf6eedb438085e688371e79c6 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 4 Feb 2011 13:05:48 -0600 Subject: [PATCH 14/36] fix sql err --- src/mod/endpoints/mod_sofia/sofia_presence.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c index a38a61eab8..2313cb7a1a 100644 --- a/src/mod/endpoints/mod_sofia/sofia_presence.c +++ b/src/mod/endpoints/mod_sofia/sofia_presence.c @@ -2576,7 +2576,7 @@ uint32_t sofia_presence_contact_count(sofia_profile_t *profile, const char *cont char buf[32] = ""; char *sql; - sql = switch_mprintf("select count(*) from sip_subscriptions where profile_name='%q' and contact_str='%q'", profile->name, contact_str); + sql = switch_mprintf("select count(*) from sip_subscriptions where profile_name='%q' and contact='%q'", profile->name, contact_str); sofia_glue_execute_sql2str(profile, profile->ireg_mutex, sql, buf, sizeof(buf)); switch_safe_free(sql); From b8b7266abb7a6c081ad1e1531aea69daf5d7509c Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 4 Feb 2011 13:11:31 -0600 Subject: [PATCH 15/36] add default to conf to demonstrate min-idle-cpu --- conf/autoload_configs/switch.conf.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/conf/autoload_configs/switch.conf.xml b/conf/autoload_configs/switch.conf.xml index 8342f120fc..32cb76f08a 100644 --- a/conf/autoload_configs/switch.conf.xml +++ b/conf/autoload_configs/switch.conf.xml @@ -23,6 +23,10 @@ + + + + + diff --git a/src/mod/codecs/mod_opus/Makefile b/src/mod/codecs/mod_opus/Makefile new file mode 100644 index 0000000000..a34695678b --- /dev/null +++ b/src/mod/codecs/mod_opus/Makefile @@ -0,0 +1,28 @@ +BASE=../../../.. + +OPUS=opus-0.9.0 + +OPUS_DIR=$(switch_srcdir)/libs/$(OPUS) +OPUS_BUILDDIR=$(switch_builddir)/libs/$(OPUS) +LOCAL_CFLAGS=-I$(OPUS_DIR)/src -g -O2 + +IETF_LA=$(OPUS_BUILDDIR)/src/.libs/libietfcodec.a +CELT_LA=$(OPUS_BUILDDIR)/celt/libcelt/.libs/libcelt0.a +SILK_LA=$(OPUS_BUILDDIR)/silk/.libs/libSKP_SILK_SDK.a + +LOCAL_LIBADD=$(IETF_LA) $(CELT_LA) $(SILK_LA) -lm -lz + +include $(BASE)/build/modmake.rules + +$(OPUS_DIR): + $(GETLIB) $(OPUS).tar.gz + +$(OPUS_BUILDDIR)/Makefile: $(OPUS_DIR) + mkdir -p $(OPUS_BUILDDIR) + cd $(OPUS_BUILDDIR) && $(DEFAULT_VARS) $(OPUS_DIR)/configure --disable-shared --with-pic --srcdir=$(OPUS_DIR) + $(TOUCH_TARGET) + +$(IETF_LA): $(OPUS_BUILDDIR)/Makefile + cd $(OPUS_BUILDDIR) && $(MAKE) + $(TOUCH_TARGET) + diff --git a/src/mod/codecs/mod_opus/mod_opus.c b/src/mod/codecs/mod_opus/mod_opus.c new file mode 100644 index 0000000000..341254fe0c --- /dev/null +++ b/src/mod/codecs/mod_opus/mod_opus.c @@ -0,0 +1,209 @@ +/* + * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * Copyright (C) 2005-2011, Anthony Minessale II + * + * Version: MPL 1.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * + * The Initial Developer of the Original Code is + * Anthony Minessale II + * Portions created by the Initial Developer are Copyright (C) + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Brian K. West + * + * mod_opus.c -- The OPUS ultra-low delay audio codec (http://www.opus-codec.org/) + * + */ + +#include "switch.h" +#include "opus.h" + + +SWITCH_MODULE_LOAD_FUNCTION(mod_opus_load); +SWITCH_MODULE_DEFINITION(mod_opus, mod_opus_load, NULL, NULL); + +struct opus_context { + OpusEncoder *encoder_object; + OpusDecoder *decoder_object; + int frame_size; +}; + +static switch_status_t switch_opus_init(switch_codec_t *codec, switch_codec_flag_t flags, const switch_codec_settings_t *codec_settings) +{ + struct opus_context *context = NULL; + int encoding = (flags & SWITCH_CODEC_FLAG_ENCODE); + int decoding = (flags & SWITCH_CODEC_FLAG_DECODE); + + if (!(encoding || decoding) || (!(context = switch_core_alloc(codec->memory_pool, sizeof(*context))))) { + return SWITCH_STATUS_FALSE; + } + + context->frame_size = codec->implementation->samples_per_packet; + + if (encoding) { + /* come up with a way to specify these */ + int bitrate_bps = codec->implementation->bits_per_second; + int mode = MODE_HYBRID; + int use_vbr = 1; + int complexity = 10; + int use_inbandfec = 1; + int use_dtx = 1; + int bandwidth = BANDWIDTH_FULLBAND; + + context->encoder_object = opus_encoder_create(codec->implementation->actual_samples_per_second, codec->implementation->number_of_channels); + + opus_encoder_ctl(context->encoder_object, OPUS_SET_MODE(mode)); + opus_encoder_ctl(context->encoder_object, OPUS_SET_BITRATE(bitrate_bps)); + opus_encoder_ctl(context->encoder_object, OPUS_SET_BANDWIDTH(bandwidth)); + opus_encoder_ctl(context->encoder_object, OPUS_SET_VBR_FLAG(use_vbr)); + opus_encoder_ctl(context->encoder_object, OPUS_SET_COMPLEXITY(complexity)); + opus_encoder_ctl(context->encoder_object, OPUS_SET_INBAND_FEC_FLAG(use_inbandfec)); + opus_encoder_ctl(context->encoder_object, OPUS_SET_DTX_FLAG(use_dtx)); + + } + + if (decoding) { + context->decoder_object = opus_decoder_create(codec->implementation->actual_samples_per_second, codec->implementation->number_of_channels); + } + + codec->private_info = context; + + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t switch_opus_destroy(switch_codec_t *codec) +{ + codec->private_info = NULL; + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t switch_opus_encode(switch_codec_t *codec, + switch_codec_t *other_codec, + void *decoded_data, + uint32_t decoded_data_len, + uint32_t decoded_rate, void *encoded_data, uint32_t *encoded_data_len, uint32_t *encoded_rate, + unsigned int *flag) +{ + struct opus_context *context = codec->private_info; + int bytes = 0; + int len = (int) *encoded_data_len; + + if (!context) { + return SWITCH_STATUS_FALSE; + } + + if (len > 1275) len = 1275; + + bytes = opus_encode(context->encoder_object, (void *) decoded_data, decoded_data_len / 2, (unsigned char *) encoded_data, len); + + if (bytes > 0) { + *encoded_data_len = (uint32_t) bytes; + return SWITCH_STATUS_SUCCESS; + } + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Encoder Error!\n"); + return SWITCH_STATUS_GENERR; +} + +static switch_status_t switch_opus_decode(switch_codec_t *codec, + switch_codec_t *other_codec, + void *encoded_data, + uint32_t encoded_data_len, + uint32_t encoded_rate, void *decoded_data, uint32_t *decoded_data_len, uint32_t *decoded_rate, + unsigned int *flag) +{ + struct opus_context *context = codec->private_info; + int samples = 0; + + if (!context) { + return SWITCH_STATUS_FALSE; + } + + samples = opus_decode(context->decoder_object, encoded_data, encoded_data_len, decoded_data, *decoded_data_len); + + if (samples < 0) { + return SWITCH_STATUS_GENERR; + } + + *decoded_data_len = samples * 2; + + return SWITCH_STATUS_SUCCESS; +} + +SWITCH_MODULE_LOAD_FUNCTION(mod_opus_load) +{ + switch_codec_interface_t *codec_interface; + + /* connect my internal structure to the blank pointer passed to me */ + *module_interface = switch_loadable_module_create_module_interface(pool, modname); + + SWITCH_ADD_CODEC(codec_interface, "OPUS (BETA)"); + + switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */ + 115, /* the IANA code number */ + "OPUS", /* the IANA code name */ + NULL, /* default fmtp to send (can be overridden by the init function) */ + 48000, /* samples transferred per second */ + 48000, /* actual samples transferred per second */ + 32000, /* bits transferred per second */ + 10000, /* number of microseconds per frame */ + 80, /* number of samples per frame */ + 960, /* number of bytes per frame decompressed */ + 0, /* number of bytes per frame compressed */ + 1, /* number of channels represented */ + 1, /* number of frames per network packet */ + switch_opus_init, /* function to initialize a codec handle using this implementation */ + switch_opus_encode, /* function to encode raw data into encoded data */ + switch_opus_decode, /* function to decode encoded data into raw data */ + switch_opus_destroy); /* deinitalize a codec handle using this implementation */ + + + switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */ + 115, /* the IANA code number */ + "OPUS", /* the IANA code name */ + NULL, /* default fmtp to send (can be overridden by the init function) */ + 48000, /* samples transferred per second */ + 48000, /* actual samples transferred per second */ + 32000, /* bits transferred per second */ + 20000, /* number of microseconds per frame */ + 160, /* number of samples per frame */ + 1920, /* number of bytes per frame decompressed */ + 0, /* number of bytes per frame compressed */ + 1, /* number of channels represented */ + 1, /* number of frames per network packet */ + switch_opus_init, /* function to initialize a codec handle using this implementation */ + switch_opus_encode, /* function to encode raw data into encoded data */ + switch_opus_decode, /* function to decode encoded data into raw data */ + switch_opus_destroy); /* deinitalize a codec handle using this implementation */ + + + + + /* indicate that the module should continue to be loaded */ + return SWITCH_STATUS_SUCCESS; +} + +/* For Emacs: + * Local Variables: + * mode:c + * indent-tabs-mode:t + * tab-width:4 + * c-basic-offset:4 + * End: + * For VIM: + * vim:set softtabstop=4 shiftwidth=4 tabstop=4: + */ From e7d68a79dc7838d74e7b8985494dcde532910d32 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 4 Feb 2011 16:02:31 -0600 Subject: [PATCH 19/36] change signalling name to avoid polluting the namespace before its ready --- src/mod/codecs/mod_opus/mod_opus.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mod/codecs/mod_opus/mod_opus.c b/src/mod/codecs/mod_opus/mod_opus.c index 341254fe0c..ddb5a7ac83 100644 --- a/src/mod/codecs/mod_opus/mod_opus.c +++ b/src/mod/codecs/mod_opus/mod_opus.c @@ -151,11 +151,11 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_opus_load) /* connect my internal structure to the blank pointer passed to me */ *module_interface = switch_loadable_module_create_module_interface(pool, modname); - SWITCH_ADD_CODEC(codec_interface, "OPUS (BETA)"); + SWITCH_ADD_CODEC(codec_interface, "OPUS (BETA 0.9.0)"); switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */ 115, /* the IANA code number */ - "OPUS", /* the IANA code name */ + "Opus-0.9.0",/* the IANA code name */ NULL, /* default fmtp to send (can be overridden by the init function) */ 48000, /* samples transferred per second */ 48000, /* actual samples transferred per second */ @@ -174,7 +174,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_opus_load) switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */ 115, /* the IANA code number */ - "OPUS", /* the IANA code name */ + "Opus-0.9.0", /* the IANA code name */ NULL, /* default fmtp to send (can be overridden by the init function) */ 48000, /* samples transferred per second */ 48000, /* actual samples transferred per second */ From 998a04d2cfa361a4d600175809d5fef02374c720 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 4 Feb 2011 16:25:00 -0600 Subject: [PATCH 20/36] add 10 20 and 40ms --- src/mod/codecs/mod_opus/mod_opus.c | 69 +++++++++++++----------------- 1 file changed, 30 insertions(+), 39 deletions(-) diff --git a/src/mod/codecs/mod_opus/mod_opus.c b/src/mod/codecs/mod_opus/mod_opus.c index ddb5a7ac83..0234ed8541 100644 --- a/src/mod/codecs/mod_opus/mod_opus.c +++ b/src/mod/codecs/mod_opus/mod_opus.c @@ -147,52 +147,43 @@ static switch_status_t switch_opus_decode(switch_codec_t *codec, SWITCH_MODULE_LOAD_FUNCTION(mod_opus_load) { switch_codec_interface_t *codec_interface; + int samples = 80; + int bytes = 960; + int mss = 10000; + int x = 0; + int rate = 48000; + int bits = 32000; /* connect my internal structure to the blank pointer passed to me */ *module_interface = switch_loadable_module_create_module_interface(pool, modname); SWITCH_ADD_CODEC(codec_interface, "OPUS (BETA 0.9.0)"); - switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */ - 115, /* the IANA code number */ - "Opus-0.9.0",/* the IANA code name */ - NULL, /* default fmtp to send (can be overridden by the init function) */ - 48000, /* samples transferred per second */ - 48000, /* actual samples transferred per second */ - 32000, /* bits transferred per second */ - 10000, /* number of microseconds per frame */ - 80, /* number of samples per frame */ - 960, /* number of bytes per frame decompressed */ - 0, /* number of bytes per frame compressed */ - 1, /* number of channels represented */ - 1, /* number of frames per network packet */ - switch_opus_init, /* function to initialize a codec handle using this implementation */ - switch_opus_encode, /* function to encode raw data into encoded data */ - switch_opus_decode, /* function to decode encoded data into raw data */ - switch_opus_destroy); /* deinitalize a codec handle using this implementation */ - - - switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */ - 115, /* the IANA code number */ - "Opus-0.9.0", /* the IANA code name */ - NULL, /* default fmtp to send (can be overridden by the init function) */ - 48000, /* samples transferred per second */ - 48000, /* actual samples transferred per second */ - 32000, /* bits transferred per second */ - 20000, /* number of microseconds per frame */ - 160, /* number of samples per frame */ - 1920, /* number of bytes per frame decompressed */ - 0, /* number of bytes per frame compressed */ - 1, /* number of channels represented */ - 1, /* number of frames per network packet */ - switch_opus_init, /* function to initialize a codec handle using this implementation */ - switch_opus_encode, /* function to encode raw data into encoded data */ - switch_opus_decode, /* function to decode encoded data into raw data */ - switch_opus_destroy); /* deinitalize a codec handle using this implementation */ - - - + for (x = 0; x < 3; x++) { + switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */ + 115, /* the IANA code number */ + "Opus-0.9.0",/* the IANA code name */ + NULL, /* default fmtp to send (can be overridden by the init function) */ + rate, /* samples transferred per second */ + rate, /* actual samples transferred per second */ + bits, /* bits transferred per second */ + mss, /* number of microseconds per frame */ + samples, /* number of samples per frame */ + bytes, /* number of bytes per frame decompressed */ + 0, /* number of bytes per frame compressed */ + 1, /* number of channels represented */ + 1, /* number of frames per network packet */ + switch_opus_init, /* function to initialize a codec handle using this implementation */ + switch_opus_encode, /* function to encode raw data into encoded data */ + switch_opus_decode, /* function to decode encoded data into raw data */ + switch_opus_destroy); /* deinitalize a codec handle using this implementation */ + + bytes *= 2; + samples *= 2; + mss *= 2; + } + /* indicate that the module should continue to be loaded */ return SWITCH_STATUS_SUCCESS; } From 294436486302d0547b34ba26e5fa402c4ebaa58f Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 4 Feb 2011 16:53:38 -0600 Subject: [PATCH 21/36] nm 40 doesn't work yet --- src/mod/codecs/mod_opus/mod_opus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/codecs/mod_opus/mod_opus.c b/src/mod/codecs/mod_opus/mod_opus.c index 0234ed8541..b9a31208a4 100644 --- a/src/mod/codecs/mod_opus/mod_opus.c +++ b/src/mod/codecs/mod_opus/mod_opus.c @@ -159,7 +159,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_opus_load) SWITCH_ADD_CODEC(codec_interface, "OPUS (BETA 0.9.0)"); - for (x = 0; x < 3; x++) { + for (x = 0; x < 2; x++) { switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */ 115, /* the IANA code number */ "Opus-0.9.0",/* the IANA code name */ From 0d5fcf65a0fef932f32874da6f4bdddb69279c53 Mon Sep 17 00:00:00 2001 From: Mathieu Rene Date: Sun, 6 Feb 2011 01:28:09 -0500 Subject: [PATCH 22/36] xml_config: change min/max enforcements to >= instead of > --- src/switch_xml_config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/switch_xml_config.c b/src/switch_xml_config.c index b6b37bd7db..5ade057b37 100644 --- a/src/switch_xml_config.c +++ b/src/switch_xml_config.c @@ -177,7 +177,7 @@ SWITCH_DECLARE(switch_status_t) switch_xml_config_parse_event(switch_event_t *ev if (int_options) { /* Enforce validation options */ - if ((int_options->enforce_min && !(intval > int_options->min)) || (int_options->enforce_max && !(intval < int_options->max))) { + if ((int_options->enforce_min && !(intval >= int_options->min)) || (int_options->enforce_max && !(intval <= int_options->max))) { /* Validation failed, set default */ intval = (int) (intptr_t) item->defaultvalue; /* Then complain */ From 7386b9f8f55e6b2648bcfb3f9dafaf62dccd772e Mon Sep 17 00:00:00 2001 From: Mathieu Rene Date: Sun, 6 Feb 2011 01:26:55 -0500 Subject: [PATCH 23/36] Add session.ringReady() to check for CF_RING_READY --- src/mod/languages/mod_spidermonkey/mod_spidermonkey.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c b/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c index 1d6ee8d679..a818c1dcd1 100644 --- a/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c +++ b/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c @@ -2126,6 +2126,15 @@ static JSBool session_media_ready(JSContext * cx, JSObject * obj, uintN argc, js } +static JSBool session_ring_ready(JSContext * cx, JSObject * obj, uintN argc, jsval * argv, jsval * rval) +{ + struct js_session *jss = JS_GetPrivate(cx, obj); + + *rval = BOOLEAN_TO_JSVAL((jss && jss->session && switch_channel_test_flag(switch_core_session_get_channel(jss->session), CF_RING_READY)) ? JS_TRUE : JS_FALSE); + + return JS_TRUE; +} + static JSBool session_answered(JSContext * cx, JSObject * obj, uintN argc, jsval * argv, jsval * rval) { struct js_session *jss = JS_GetPrivate(cx, obj); @@ -2673,6 +2682,7 @@ static JSFunctionSpec session_methods[] = { {"ready", session_ready, 0}, {"answered", session_answered, 0}, {"mediaReady", session_media_ready, 0}, + {"ringReady", session_ring_ready, 0}, {"waitForAnswer", session_wait_for_answer, 0}, {"waitForMedia", session_wait_for_media, 0}, {"getEvent", session_get_event, 0}, From 2b4f163826132cf55698008a22c065374320796a Mon Sep 17 00:00:00 2001 From: Mathieu Rene Date: Sun, 6 Feb 2011 01:40:13 -0500 Subject: [PATCH 24/36] Add libjpeg-dev to apt prereqs --- support-d/prereq.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/support-d/prereq.sh b/support-d/prereq.sh index 4e214cff89..8bc454ded4 100755 --- a/support-d/prereq.sh +++ b/support-d/prereq.sh @@ -2,7 +2,7 @@ UNAME=`uname` NEEDED_PACKAGES_YUM='automake autoconf libtool screen gdb gcc-c++ compat-gcc-32 compat-gcc-32-c++ subversion ncurses-devel unixODBC-devel make wget' -NEEDED_PACAKGES_APT='automake autoconf libtool screen gdb libncurses5-dev unixodbc-dev subversion emacs22-nox gcc g++ make' +NEEDED_PACAKGES_APT='automake autoconf libtool screen gdb libncurses5-dev unixodbc-dev subversion emacs22-nox gcc g++ make libjpeg-dev' NEEDED_PACKAGES_PKG_ADD='' From d4b5b07b2a76404ed8bf5adf8bc2bc9c0cbd9f04 Mon Sep 17 00:00:00 2001 From: Leon de Rooij Date: Mon, 7 Feb 2011 10:36:04 +0100 Subject: [PATCH 25/36] reswig mod_lua for freeswitch.email --- src/mod/languages/mod_lua/mod_lua_wrap.cpp | 50 ++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/src/mod/languages/mod_lua/mod_lua_wrap.cpp b/src/mod/languages/mod_lua/mod_lua_wrap.cpp index 1d84a39fd5..559d4032c0 100644 --- a/src/mod/languages/mod_lua/mod_lua_wrap.cpp +++ b/src/mod/languages/mod_lua/mod_lua_wrap.cpp @@ -1582,6 +1582,55 @@ fail: } +static int _wrap_email(lua_State* L) { + int SWIG_arg = -1; + char *arg1 = (char *) 0 ; + char *arg2 = (char *) 0 ; + char *arg3 = (char *) NULL ; + char *arg4 = (char *) NULL ; + char *arg5 = (char *) NULL ; + char *arg6 = (char *) NULL ; + char *arg7 = (char *) NULL ; + bool result; + + SWIG_check_num_args("email",2,7) + if(!lua_isstring(L,1)) SWIG_fail_arg("email",1,"char *"); + if(!lua_isstring(L,2)) SWIG_fail_arg("email",2,"char *"); + if(lua_gettop(L)>=3 && !lua_isstring(L,3)) SWIG_fail_arg("email",3,"char *"); + if(lua_gettop(L)>=4 && !lua_isstring(L,4)) SWIG_fail_arg("email",4,"char *"); + if(lua_gettop(L)>=5 && !lua_isstring(L,5)) SWIG_fail_arg("email",5,"char *"); + if(lua_gettop(L)>=6 && !lua_isstring(L,6)) SWIG_fail_arg("email",6,"char *"); + if(lua_gettop(L)>=7 && !lua_isstring(L,7)) SWIG_fail_arg("email",7,"char *"); + arg1 = (char *)lua_tostring(L, 1); + arg2 = (char *)lua_tostring(L, 2); + if(lua_gettop(L)>=3){ + arg3 = (char *)lua_tostring(L, 3); + } + if(lua_gettop(L)>=4){ + arg4 = (char *)lua_tostring(L, 4); + } + if(lua_gettop(L)>=5){ + arg5 = (char *)lua_tostring(L, 5); + } + if(lua_gettop(L)>=6){ + arg6 = (char *)lua_tostring(L, 6); + } + if(lua_gettop(L)>=7){ + arg7 = (char *)lua_tostring(L, 7); + } + result = (bool)email(arg1,arg2,arg3,arg4,arg5,arg6,arg7); + SWIG_arg=0; + lua_pushboolean(L,(int)(result==true)); SWIG_arg++; + return SWIG_arg; + + if(0) SWIG_fail; + +fail: + lua_error(L); + return SWIG_arg; +} + + static int _wrap_new_IVRMenu(lua_State* L) { int SWIG_arg = -1; IVRMenu *arg1 = (IVRMenu *) 0 ; @@ -7525,6 +7574,7 @@ static swig_lua_class _wrap_class_LUA_Dbh = { "Dbh", &SWIGTYPE_p_LUA__Dbh,_wrap_ static const struct luaL_reg swig_commands[] = { { "consoleLog", _wrap_consoleLog}, { "consoleCleanLog", _wrap_consoleCleanLog}, + { "email", _wrap_email}, { "console_log", _wrap_console_log}, { "console_clean_log", _wrap_console_clean_log}, { "msleep", _wrap_msleep}, From 080c5ae98167e590bebf698439c550bdb656925e Mon Sep 17 00:00:00 2001 From: cypromis Date: Mon, 7 Feb 2011 14:04:44 +0100 Subject: [PATCH 26/36] FS-1742 - Make Voicemail use 1 SQL query instead of 4 to get the message count use in MWI - Now also working on your more favourite and less favourite databases --- src/mod/applications/mod_voicemail/mod_voicemail.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/mod/applications/mod_voicemail/mod_voicemail.c b/src/mod/applications/mod_voicemail/mod_voicemail.c index 80b011e189..f868c3a284 100644 --- a/src/mod/applications/mod_voicemail/mod_voicemail.c +++ b/src/mod/applications/mod_voicemail/mod_voicemail.c @@ -1278,7 +1278,9 @@ static void message_count(vm_profile_t *profile, const char *id_in, const char * myid = resolve_id(id_in, domain_name, "message-count"); switch_snprintf(sql, sizeof(sql), - "select read_epoch=0, read_flags, count(read_epoch) from voicemail_msgs where username='%s' and domain='%s' and in_folder='%s' group by read_epoch=0,read_flags;", + "select 1, read_flags, count(read_epoch) from voicemail_msgs where username='%s' and domain='%s' and in_folder='%s' and read_epoch=0 group by read_flags + union + select 0, read_flags, count(read_epoch) from voicemail_msgs where username='%s' and domain='%s' and in_folder='%s' and read_epoch<>0 group by read_flags;", myid, domain_name, myfolder); vm_execute_sql_callback(profile, profile->mutex, sql, message_count_callback, &cbt); From cf83f9c381a6abb988efc41b8711271b4665b79e Mon Sep 17 00:00:00 2001 From: cypromis Date: Mon, 7 Feb 2011 15:32:26 +0100 Subject: [PATCH 27/36] seems whitespaces are unpopular on some linux/gcc combinations --- src/mod/applications/mod_voicemail/mod_voicemail.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/mod/applications/mod_voicemail/mod_voicemail.c b/src/mod/applications/mod_voicemail/mod_voicemail.c index f868c3a284..16841277d6 100644 --- a/src/mod/applications/mod_voicemail/mod_voicemail.c +++ b/src/mod/applications/mod_voicemail/mod_voicemail.c @@ -1277,11 +1277,8 @@ static void message_count(vm_profile_t *profile, const char *id_in, const char * myid = resolve_id(id_in, domain_name, "message-count"); - switch_snprintf(sql, sizeof(sql), - "select 1, read_flags, count(read_epoch) from voicemail_msgs where username='%s' and domain='%s' and in_folder='%s' and read_epoch=0 group by read_flags - union - select 0, read_flags, count(read_epoch) from voicemail_msgs where username='%s' and domain='%s' and in_folder='%s' and read_epoch<>0 group by read_flags;", - myid, domain_name, myfolder); + switch_snprintf(sql, sizeof(sql), "select 1, read_flags, count(read_epoch) from voicemail_msgs where username='%s' and domain='%s' and in_folder='%s' and read_epoch=0 group by read_flags union + select 0, read_flags, count(read_epoch) from voicemail_msgs where username='%s' and domain='%s' and in_folder='%s' and read_epoch<>0 group by read_flags;", myid, domain_name, myfolder); vm_execute_sql_callback(profile, profile->mutex, sql, message_count_callback, &cbt); From 12c13e115b96e9e036bd65655c1f12a72a83510e Mon Sep 17 00:00:00 2001 From: cypromis Date: Mon, 7 Feb 2011 16:01:20 +0100 Subject: [PATCH 28/36] more formatting mistakes *sigh* --- src/mod/applications/mod_voicemail/mod_voicemail.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mod/applications/mod_voicemail/mod_voicemail.c b/src/mod/applications/mod_voicemail/mod_voicemail.c index 16841277d6..f829e574d2 100644 --- a/src/mod/applications/mod_voicemail/mod_voicemail.c +++ b/src/mod/applications/mod_voicemail/mod_voicemail.c @@ -1277,9 +1277,9 @@ static void message_count(vm_profile_t *profile, const char *id_in, const char * myid = resolve_id(id_in, domain_name, "message-count"); - switch_snprintf(sql, sizeof(sql), "select 1, read_flags, count(read_epoch) from voicemail_msgs where username='%s' and domain='%s' and in_folder='%s' and read_epoch=0 group by read_flags union - select 0, read_flags, count(read_epoch) from voicemail_msgs where username='%s' and domain='%s' and in_folder='%s' and read_epoch<>0 group by read_flags;", myid, domain_name, myfolder); - + switch_snprintf(sql, sizeof(sql), "select 1, read_flags, count(read_epoch) from voicemail_msgs where username='%s' and domain='%s' and in_folder='%s' " + "and read_epoch=0 group by read_flags union select 0, read_flags, count(read_epoch) from voicemail_msgs where username='%s' " + "and domain='%s' and in_folder='%s' and read_epoch<>0 group by read_flags;", myid, domain_name, myfolder); vm_execute_sql_callback(profile, profile->mutex, sql, message_count_callback, &cbt); *total_new_messages = cbt.total_new_messages + cbt.total_new_urgent_messages; From bab7a2392f955facbb91d0f30512682e2b38773e Mon Sep 17 00:00:00 2001 From: Daniel Swarbrick Date: Mon, 7 Feb 2011 17:09:14 +0100 Subject: [PATCH 29/36] refactor config parsing --- conf/autoload_configs/cdr_pg_csv.conf.xml | 14 +- .../mod_cdr_pg_csv/mod_cdr_pg_csv.c | 141 +++++++++--------- 2 files changed, 77 insertions(+), 78 deletions(-) diff --git a/conf/autoload_configs/cdr_pg_csv.conf.xml b/conf/autoload_configs/cdr_pg_csv.conf.xml index 2f2efa9b26..427bf2d058 100644 --- a/conf/autoload_configs/cdr_pg_csv.conf.xml +++ b/conf/autoload_configs/cdr_pg_csv.conf.xml @@ -1,19 +1,23 @@ - - - - - + + + + + + + + + diff --git a/src/mod/event_handlers/mod_cdr_pg_csv/mod_cdr_pg_csv.c b/src/mod/event_handlers/mod_cdr_pg_csv/mod_cdr_pg_csv.c index 5227161f23..1ec56bdd64 100644 --- a/src/mod/event_handlers/mod_cdr_pg_csv/mod_cdr_pg_csv.c +++ b/src/mod/event_handlers/mod_cdr_pg_csv/mod_cdr_pg_csv.c @@ -37,18 +37,27 @@ #include #include +SWITCH_MODULE_LOAD_FUNCTION(mod_cdr_pg_csv_load); +SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_cdr_pg_csv_shutdown); +SWITCH_MODULE_DEFINITION(mod_cdr_pg_csv, mod_cdr_pg_csv_load, mod_cdr_pg_csv_shutdown, NULL); + + typedef enum { CDR_LEG_A = (1 << 0), CDR_LEG_B = (1 << 1) } cdr_leg_t; -struct cdr_fd { +typedef enum { + SPOOL_FORMAT_CSV, + SPOOL_FORMAT_SQL +} spool_format_t; + +typedef struct { int fd; char *path; int64_t bytes; switch_mutex_t *mutex; -}; -typedef struct cdr_fd cdr_fd_t; +} cdr_fd_t; const char *default_template = "\"${local_ip_v4}\",\"${caller_id_name}\",\"${caller_id_number}\",\"${destination_number}\",\"${context}\",\"${start_stamp}\"," @@ -59,23 +68,59 @@ static struct { switch_memory_pool_t *pool; switch_hash_t *fd_hash; switch_hash_t *template_hash; - char *log_dir; - char *default_template; int shutdown; - int rotate; - int debug; - cdr_leg_t legs; char *db_info; char *db_table; - char *spool_format; PGconn *db_connection; int db_online; + cdr_leg_t legs; + char *spool_dir; + spool_format_t spool_format; + int rotate; + int debug; + char *default_template; switch_mutex_t *db_mutex; } globals = { 0 }; -SWITCH_MODULE_LOAD_FUNCTION(mod_cdr_pg_csv_load); -SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_cdr_pg_csv_shutdown); -SWITCH_MODULE_DEFINITION(mod_cdr_pg_csv, mod_cdr_pg_csv_load, mod_cdr_pg_csv_shutdown, NULL); +static switch_xml_config_enum_item_t config_opt_cdr_leg_enum[] = { + {"a", CDR_LEG_A}, + {"b", CDR_LEG_B}, + {"ab", CDR_LEG_A | CDR_LEG_B}, + {NULL, 0} +}; + +static switch_xml_config_enum_item_t config_opt_spool_format_enum[] = { + {"csv", SPOOL_FORMAT_CSV}, + {"sql", SPOOL_FORMAT_SQL}, + {NULL, 0} +}; + +static switch_status_t config_validate_spool_dir(switch_xml_config_item_t *item, const char *newvalue, switch_config_callback_type_t callback_type, switch_bool_t changed) +{ + if ((callback_type == CONFIG_LOAD || callback_type == CONFIG_RELOAD)) { + if (zstr(newvalue)) { + globals.spool_dir = switch_core_sprintf(globals.pool, "%s%scdr-pg-csv", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR); + } + } + + return SWITCH_STATUS_SUCCESS; +} + +static switch_xml_config_item_t config_settings[] = { + /* key, type, flags, ptr, default_value, data, syntax, helptext */ + SWITCH_CONFIG_ITEM_STRING_STRDUP("db-info", CONFIG_RELOADABLE, &globals.db_info, "dbname=cdr", NULL, NULL), + SWITCH_CONFIG_ITEM_STRING_STRDUP("db-table", CONFIG_RELOADABLE, &globals.db_table, "cdr", NULL, NULL), + SWITCH_CONFIG_ITEM_STRING_STRDUP("default-template", CONFIG_RELOADABLE, &globals.default_template, "default", NULL, NULL), + SWITCH_CONFIG_ITEM("legs", SWITCH_CONFIG_ENUM, CONFIG_RELOADABLE, &globals.legs, (void *) CDR_LEG_A, &config_opt_cdr_leg_enum, "a|b|ab", NULL), + SWITCH_CONFIG_ITEM("spool-format", SWITCH_CONFIG_ENUM, CONFIG_RELOADABLE, &globals.spool_format, (void *) SPOOL_FORMAT_CSV, &config_opt_spool_format_enum, "csv|sql", "Disk spool format to use if SQL insert fails."), + SWITCH_CONFIG_ITEM("rotate-on-hup", SWITCH_CONFIG_BOOL, CONFIG_RELOADABLE, &globals.rotate, SWITCH_FALSE, NULL, NULL, NULL), + SWITCH_CONFIG_ITEM("debug", SWITCH_CONFIG_BOOL, CONFIG_RELOADABLE, &globals.debug, SWITCH_FALSE, NULL, NULL, NULL), + + /* key, type, flags, ptr, defaultvalue, function, functiondata, syntax, helptext */ + SWITCH_CONFIG_ITEM_CALLBACK("spool-dir", SWITCH_CONFIG_STRING, CONFIG_RELOADABLE, &globals.spool_dir, NULL, config_validate_spool_dir, NULL, NULL, NULL), + SWITCH_CONFIG_ITEM_END() +}; + static off_t fd_size(int fd) { @@ -363,12 +408,12 @@ static switch_status_t insert_cdr(const char * const template, const char * cons switch_mutex_unlock(globals.db_mutex); /* SQL INSERT failed for whatever reason. Spool the attempted query to disk */ - if (!strcasecmp(globals.spool_format, "sql")) { - path = switch_mprintf("%s%scdr-spool.sql", globals.log_dir, SWITCH_PATH_SEPARATOR); + if (globals.spool_format == SPOOL_FORMAT_SQL) { + path = switch_mprintf("%s%scdr-spool.sql", globals.spool_dir, SWITCH_PATH_SEPARATOR); assert(path); spool_cdr(path, sql); } else { - path = switch_mprintf("%s%scdr-spool.csv", globals.log_dir, SWITCH_PATH_SEPARATOR); + path = switch_mprintf("%s%scdr-spool.csv", globals.spool_dir, SWITCH_PATH_SEPARATOR); assert(path); spool_cdr(path, cdr); } @@ -402,8 +447,8 @@ static switch_status_t my_on_reporting(switch_core_session_t *session) } } - if (switch_dir_make_recursive(globals.log_dir, SWITCH_DEFAULT_DIR_PERMS, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error creating %s\n", globals.log_dir); + if (switch_dir_make_recursive(globals.spool_dir, SWITCH_DEFAULT_DIR_PERMS, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error creating %s\n", globals.spool_dir); return SWITCH_STATUS_FALSE; } @@ -485,7 +530,6 @@ static switch_state_handler_table_t state_handlers = { }; - static switch_status_t load_config(switch_memory_pool_t *pool) { char *cf = "cdr_pg_csv.conf"; @@ -509,40 +553,11 @@ static switch_status_t load_config(switch_memory_pool_t *pool) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding default template.\n"); globals.legs = CDR_LEG_A; + if (switch_xml_config_parse_module_settings("cdr_pg_csv.conf", SWITCH_FALSE, config_settings) != SWITCH_STATUS_SUCCESS) { + return SWITCH_STATUS_FALSE; + } + if ((xml = switch_xml_open_cfg(cf, &cfg, NULL))) { - - if ((settings = switch_xml_child(cfg, "settings"))) { - for (param = switch_xml_child(settings, "param"); param; param = param->next) { - char *var = (char *) switch_xml_attr_soft(param, "name"); - char *val = (char *) switch_xml_attr_soft(param, "value"); - if (!strcasecmp(var, "debug")) { - globals.debug = switch_true(val); - } else if (!strcasecmp(var, "legs")) { - globals.legs = 0; - - if (strchr(val, 'a')) { - globals.legs |= CDR_LEG_A; - } - - if (strchr(val, 'b')) { - globals.legs |= CDR_LEG_B; - } - } else if (!strcasecmp(var, "log-base")) { - globals.log_dir = switch_core_sprintf(pool, "%s%scdr-pg-csv", val, SWITCH_PATH_SEPARATOR); - } else if (!strcasecmp(var, "rotate-on-hup")) { - globals.rotate = switch_true(val); - } else if (!strcasecmp(var, "db-info")) { - globals.db_info = switch_core_strdup(pool, val); - } else if (!strcasecmp(var, "db-table") || !strcasecmp(var, "g-table")) { - globals.db_table = switch_core_strdup(pool, val); - } else if (!strcasecmp(var, "default-template")) { - globals.default_template = switch_core_strdup(pool, val); - } else if (!strcasecmp(var, "spool-format")) { - globals.spool_format = switch_core_strdup(pool, val); - } - } - } - if ((settings = switch_xml_child(cfg, "templates"))) { for (param = switch_xml_child(settings, "template"); param; param = param->next) { char *var = (char *) switch_xml_attr(param, "name"); @@ -558,26 +573,6 @@ static switch_status_t load_config(switch_memory_pool_t *pool) switch_xml_free(xml); } - if (!globals.log_dir) { - globals.log_dir = switch_core_sprintf(pool, "%s%scdr-pg-csv", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR); - } - - if (zstr(globals.db_info)) { - globals.db_info = switch_core_strdup(pool, "dbname=cdr"); - } - - if (zstr(globals.db_table)) { - globals.db_table = switch_core_strdup(pool, "cdr"); - } - - if (zstr(globals.default_template)) { - globals.default_template = switch_core_strdup(pool, "default"); - } - - if (zstr(globals.spool_format)) { - globals.spool_format = switch_core_strdup(pool, "csv"); - } - return status; } @@ -588,8 +583,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_cdr_pg_csv_load) load_config(pool); - if ((status = switch_dir_make_recursive(globals.log_dir, SWITCH_DEFAULT_DIR_PERMS, pool)) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error creating %s\n", globals.log_dir); + if ((status = switch_dir_make_recursive(globals.spool_dir, SWITCH_DEFAULT_DIR_PERMS, pool)) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error creating %s\n", globals.spool_dir); return status; } From 8c12162a9d92ceac55c6305f2336efcf7157b923 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 7 Feb 2011 12:53:31 -0600 Subject: [PATCH 30/36] FS-3040 --- src/mod/applications/mod_voicemail/mod_voicemail.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/mod/applications/mod_voicemail/mod_voicemail.c b/src/mod/applications/mod_voicemail/mod_voicemail.c index f829e574d2..bea82142b6 100644 --- a/src/mod/applications/mod_voicemail/mod_voicemail.c +++ b/src/mod/applications/mod_voicemail/mod_voicemail.c @@ -1277,9 +1277,14 @@ static void message_count(vm_profile_t *profile, const char *id_in, const char * myid = resolve_id(id_in, domain_name, "message-count"); - switch_snprintf(sql, sizeof(sql), "select 1, read_flags, count(read_epoch) from voicemail_msgs where username='%s' and domain='%s' and in_folder='%s' " - "and read_epoch=0 group by read_flags union select 0, read_flags, count(read_epoch) from voicemail_msgs where username='%s' " - "and domain='%s' and in_folder='%s' and read_epoch<>0 group by read_flags;", myid, domain_name, myfolder); + switch_snprintf(sql, sizeof(sql), "select 1, read_flags, count(read_epoch) from voicemail_msgs where " + "username='%s' and domain='%s' and in_folder='%s' " + "and read_epoch=0 group by read_flags union select 0, read_flags, count(read_epoch) from voicemail_msgs where username='%s' " + "and domain='%s' and in_folder='%s' and read_epoch<>0 group by read_flags;", + myid, domain_name, myfolder, myid, domain_name, myfolder); + + + vm_execute_sql_callback(profile, profile->mutex, sql, message_count_callback, &cbt); *total_new_messages = cbt.total_new_messages + cbt.total_new_urgent_messages; From 526e6fe48cadc9418d64f2b639bad68d8883dcdd Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 7 Feb 2011 13:14:20 -0600 Subject: [PATCH 31/36] FS-3038 --- .../applications/mod_commands/mod_commands.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/mod/applications/mod_commands/mod_commands.c b/src/mod/applications/mod_commands/mod_commands.c index 807770ac15..f34042a54f 100644 --- a/src/mod/applications/mod_commands/mod_commands.c +++ b/src/mod/applications/mod_commands/mod_commands.c @@ -4439,19 +4439,23 @@ SWITCH_STANDARD_API(strftime_tz_api_function) if ((format = strchr(mycmd, ' '))) { *format++ = '\0'; - } - if ((p = strchr(format, '|'))) { - *p++ = '\0'; - when = atol(format); - format = p; + if (format && (p = strchr(format, '|'))) { + *p++ = '\0'; + when = atol(format); + format = p; + } } } - if (switch_strftime_tz(tz_name, format, date, sizeof(date), when * 1000000) == SWITCH_STATUS_SUCCESS) { /* The lookup of the zone may fail. */ + if (zstr(format)) { + format = "%Y-%m-%d"; + } + + if (format && switch_strftime_tz(tz_name, format, date, sizeof(date), when * 1000000) == SWITCH_STATUS_SUCCESS) { /* The lookup of the zone may fail. */ stream->write_function(stream, "%s", date); } else { - stream->write_function(stream, "-ERR Invalid Timezone\n"); + stream->write_function(stream, "-ERR Invalid Timezone/Format\n"); } switch_safe_free(mycmd); From f0a31e1bfff2d49d97bc0ee83627c426fa311bfc Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 7 Feb 2011 14:35:56 -0600 Subject: [PATCH 32/36] default to 10 --- src/mod/endpoints/mod_sofia/mod_sofia.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index c78aac7933..c6832030b4 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -3708,7 +3708,7 @@ SWITCH_STANDARD_API(sofia_function) if (argc > 2) { if (strstr(argv[2], "presence")) { - mod_sofia_globals.debug_presence = 1; + mod_sofia_globals.debug_presence = 10; stream->write_function(stream, "+OK Debugging presence\n"); } From bcb2262fdc48b36bd2e6bfe45adcbaecd1d091ee Mon Sep 17 00:00:00 2001 From: Daniel Swarbrick Date: Mon, 7 Feb 2011 22:22:37 +0100 Subject: [PATCH 33/36] major factor of pgsql field handling --- conf/autoload_configs/cdr_pg_csv.conf.xml | 25 +- .../mod_cdr_pg_csv/mod_cdr_pg_csv.c | 279 +++++++----------- 2 files changed, 130 insertions(+), 174 deletions(-) diff --git a/conf/autoload_configs/cdr_pg_csv.conf.xml b/conf/autoload_configs/cdr_pg_csv.conf.xml index 427bf2d058..4fec817b45 100644 --- a/conf/autoload_configs/cdr_pg_csv.conf.xml +++ b/conf/autoload_configs/cdr_pg_csv.conf.xml @@ -16,10 +16,25 @@ - - - - - + + + + + + + + + + + + + + + + + + + + diff --git a/src/mod/event_handlers/mod_cdr_pg_csv/mod_cdr_pg_csv.c b/src/mod/event_handlers/mod_cdr_pg_csv/mod_cdr_pg_csv.c index 1ec56bdd64..51194f4b14 100644 --- a/src/mod/event_handlers/mod_cdr_pg_csv/mod_cdr_pg_csv.c +++ b/src/mod/event_handlers/mod_cdr_pg_csv/mod_cdr_pg_csv.c @@ -59,28 +59,34 @@ typedef struct { switch_mutex_t *mutex; } cdr_fd_t; -const char *default_template = - "\"${local_ip_v4}\",\"${caller_id_name}\",\"${caller_id_number}\",\"${destination_number}\",\"${context}\",\"${start_stamp}\"," - "\"${answer_stamp}\",\"${end_stamp}\",\"${duration}\",\"${billsec}\",\"${hangup_cause}\",\"${uuid}\",\"${bleg_uuid}\",\"${accountcode}\"," - "\"${read_codec}\",\"${write_codec}\""; +typedef struct { + char *col_name; + char *var_name; + switch_bool_t quote; + switch_bool_t not_null; +} cdr_field_t; + +typedef struct { + char *columns; + cdr_field_t fields[1]; +} db_schema_t; static struct { switch_memory_pool_t *pool; switch_hash_t *fd_hash; - switch_hash_t *template_hash; int shutdown; char *db_info; char *db_table; + db_schema_t *db_schema; PGconn *db_connection; + switch_mutex_t *db_mutex; int db_online; cdr_leg_t legs; char *spool_dir; spool_format_t spool_format; int rotate; int debug; - char *default_template; - switch_mutex_t *db_mutex; -} globals = { 0 }; +} globals; static switch_xml_config_enum_item_t config_opt_cdr_leg_enum[] = { {"a", CDR_LEG_A}, @@ -110,7 +116,6 @@ static switch_xml_config_item_t config_settings[] = { /* key, type, flags, ptr, default_value, data, syntax, helptext */ SWITCH_CONFIG_ITEM_STRING_STRDUP("db-info", CONFIG_RELOADABLE, &globals.db_info, "dbname=cdr", NULL, NULL), SWITCH_CONFIG_ITEM_STRING_STRDUP("db-table", CONFIG_RELOADABLE, &globals.db_table, "cdr", NULL, NULL), - SWITCH_CONFIG_ITEM_STRING_STRDUP("default-template", CONFIG_RELOADABLE, &globals.default_template, "default", NULL, NULL), SWITCH_CONFIG_ITEM("legs", SWITCH_CONFIG_ENUM, CONFIG_RELOADABLE, &globals.legs, (void *) CDR_LEG_A, &config_opt_cdr_leg_enum, "a|b|ab", NULL), SWITCH_CONFIG_ITEM("spool-format", SWITCH_CONFIG_ENUM, CONFIG_RELOADABLE, &globals.spool_format, (void *) SPOOL_FORMAT_CSV, &config_opt_spool_format_enum, "csv|sql", "Disk spool format to use if SQL insert fails."), SWITCH_CONFIG_ITEM("rotate-on-hup", SWITCH_CONFIG_BOOL, CONFIG_RELOADABLE, &globals.rotate, SWITCH_FALSE, NULL, NULL, NULL), @@ -239,135 +244,13 @@ static void spool_cdr(const char *path, const char *log_line) switch_safe_free(log_line_lf); } -static switch_status_t insert_cdr(const char * const template, const char * const cdr) +static switch_status_t insert_cdr(const char *values) { - char *columns, *values; - char *p, *q; - unsigned vlen; - char *nullValues, *temp, *tp; - int nullCounter = 0, charCounter = 0; char *sql = NULL, *path = NULL; PGresult *res; - if (!template || !*template || !cdr || !*cdr) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Bad parameter\n"); - return SWITCH_STATUS_FALSE; - } - - /* Build comma-separated list of field names by dropping $ { } ; chars */ - switch_strdup(columns, template); - for (p = columns, q = columns; *p; ++p) { - switch (*p) { - case '$': case '"': case '{': case '}': case ';': - break; - default: - *q++ = *p; - } - } - *q = '\0'; - - /* - * In the expanded vars, replace double quotes (") with single quotes (') - * for correct PostgreSQL syntax, and replace semi-colon with space to - * prevent SQL injection attacks - */ - switch_strdup(values, cdr); - for (p = values; *p; ++p) { - switch(*p) { - case '"': - *p = '\''; - break; - case ';': - *p = ' '; - break; - } - } - vlen = p - values; - - /* - * Patch for changing empty strings ('') in the expanded variables to - * PostgreSQL null - */ - for (p = values; *p; ++p) { - if (*p == ',') { - if (charCounter == 0) { - nullCounter++; - } - charCounter = 0; - } else if (*p != ' ' && *p != '\'') { - charCounter++; - } - } - - if (charCounter == 0) { - nullCounter++; - } - - nullCounter *= 4; - vlen += nullCounter; - switch_zmalloc(nullValues, strlen(values) + nullCounter + 1); - charCounter = 0; - temp = nullValues; - tp = nullValues; - - for (p = values; *p; ++tp, ++p) { - if (*p == ',') { - if (charCounter == 0) { - temp++; - *temp = 'n'; - temp++; - if (temp == tp) tp++; - *temp = 'u'; - temp++; - if (temp == tp) tp++; - *temp = 'l'; - temp++; - if (temp == tp) tp++; - *temp = 'l'; - temp++; - while (temp != tp) { - *temp = ' '; - temp++; - } - } - charCounter = 0; - temp = tp; - } else if (*p != ' ' && *p != '\'') { - charCounter++; - } - *tp = *p; - } - - if (charCounter == 0) { - temp++; - *temp = 'n'; - temp++; - if (temp == tp) tp++; - *temp = 'u'; - temp++; - if (temp == tp) tp++; - *temp = 'l'; - temp++; - if (temp == tp) tp++; - *temp = 'l'; - temp++; - while (temp != tp) { - *temp = ' '; - temp++; - } - } - - charCounter = 0; - temp = tp; - *tp = 0; - tp = values; - values = nullValues; - switch_safe_free(tp); - - sql = switch_mprintf("INSERT INTO %s (%s) VALUES (%s);", globals.db_table, columns, values); + sql = switch_mprintf("INSERT INTO %s (%s) VALUES (%s);", globals.db_table, globals.db_schema->columns, values); assert(sql); - switch_safe_free(columns); - switch_safe_free(values); if (globals.debug) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Query: \"%s\"\n", sql); @@ -415,7 +298,7 @@ static switch_status_t insert_cdr(const char * const template, const char * cons } else { path = switch_mprintf("%s%scdr-spool.csv", globals.spool_dir, SWITCH_PATH_SEPARATOR); assert(path); - spool_cdr(path, cdr); + spool_cdr(path, values); } switch_safe_free(path); @@ -428,8 +311,10 @@ static switch_status_t my_on_reporting(switch_core_session_t *session) { switch_channel_t *channel = switch_core_session_get_channel(session); switch_status_t status = SWITCH_STATUS_SUCCESS; - const char *template_str = NULL; - char *expanded_vars = NULL; + char *values = NULL, *tmp = NULL, *pq_var = NULL; + const char *var = NULL; + cdr_field_t *cdr_field = NULL; + switch_size_t len, offset; if (globals.shutdown) { return SWITCH_STATUS_SUCCESS; @@ -465,24 +350,40 @@ static switch_status_t my_on_reporting(switch_core_session_t *session) } } - template_str = (const char *) switch_core_hash_find(globals.template_hash, globals.default_template); + switch_zmalloc(values, 1); + offset = 0; - if (!template_str) { - template_str = default_template; + for (cdr_field = globals.db_schema->fields; cdr_field->var_name; cdr_field++) { + if ((var = switch_channel_get_variable(channel, cdr_field->var_name))) { + /* Allocate sufficient buffer for PQescapeString */ + len = strlen(var); + tmp = switch_core_session_alloc(session, len * 2 + 1); + PQescapeString(tmp, var, len); + var = tmp; + } + + if (cdr_field->quote) { + if ((cdr_field->not_null == SWITCH_FALSE) && zstr(var)) { + pq_var = switch_mprintf("null,", var); + } else { + pq_var = switch_mprintf("'%s',", var); + } + } else { + pq_var = switch_mprintf("%s,", var); + } + + /* Resize values buffer to accomodate next var */ + len = strlen(pq_var); + tmp = realloc(values, offset + len); + values = tmp; + memcpy(values + offset, pq_var, len); + switch_safe_free(pq_var); + offset += len; } + *(values + --offset) = '\0'; - expanded_vars = switch_channel_expand_variables(channel, template_str); - - if (!expanded_vars) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error expanding CDR variables.\n"); - return SWITCH_STATUS_FALSE; - } - - insert_cdr(template_str, expanded_vars); - - if (expanded_vars != template_str) { - switch_safe_free(expanded_vars); - } + insert_cdr(values); + switch_safe_free(values); return status; } @@ -532,9 +433,13 @@ static switch_state_handler_table_t state_handlers = { static switch_status_t load_config(switch_memory_pool_t *pool) { - char *cf = "cdr_pg_csv.conf"; - switch_xml_t cfg, xml, settings, param; switch_status_t status = SWITCH_STATUS_SUCCESS; + char *cf = "cdr_pg_csv.conf", *ptr; + switch_xml_t cfg, xml, schema, field; + const char *attr; + int num_fields = 0; + switch_size_t len = 0; + cdr_field_t *cdr_field; if (globals.db_online) { PQfinish(globals.db_connection); @@ -544,32 +449,69 @@ static switch_status_t load_config(switch_memory_pool_t *pool) memset(&globals, 0, sizeof(globals)); switch_core_hash_init(&globals.fd_hash, pool); - switch_core_hash_init(&globals.template_hash, pool); switch_mutex_init(&globals.db_mutex, SWITCH_MUTEX_NESTED, pool); globals.pool = pool; - switch_core_hash_insert(globals.template_hash, "default", default_template); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding default template.\n"); - globals.legs = CDR_LEG_A; - - if (switch_xml_config_parse_module_settings("cdr_pg_csv.conf", SWITCH_FALSE, config_settings) != SWITCH_STATUS_SUCCESS) { + if (switch_xml_config_parse_module_settings(cf, SWITCH_FALSE, config_settings) != SWITCH_STATUS_SUCCESS) { return SWITCH_STATUS_FALSE; } if ((xml = switch_xml_open_cfg(cf, &cfg, NULL))) { - if ((settings = switch_xml_child(cfg, "templates"))) { - for (param = switch_xml_child(settings, "template"); param; param = param->next) { - char *var = (char *) switch_xml_attr(param, "name"); - if (var) { - char *tpl; - tpl = switch_core_strdup(pool, param->txt); - - switch_core_hash_insert(globals.template_hash, var, tpl); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding template %s.\n", var); + if ((schema = switch_xml_child(cfg, "schema"))) { + /* Count fields in schema so we can calculate required buffer size */ + for (field = switch_xml_child(schema, "field"); field; field = field->next) { + if (switch_xml_attr(field, "var")) { + num_fields++; } } + + globals.db_schema = switch_core_alloc(pool, (num_fields + 1) * sizeof(cdr_field_t)); + cdr_field = globals.db_schema->fields; + + for (field = switch_xml_child(schema, "field"); field; field = field->next) { + if ((attr = switch_xml_attr(field, "var"))) { + cdr_field->var_name = switch_core_strdup(pool, attr); + + /* Assume SQL column name is the same as FreeSWITCH channel var name, unless specified otherwise */ + if ((attr = switch_xml_attr(field, "column"))) { + cdr_field->col_name = switch_core_strdup(pool, attr); + } else { + cdr_field->col_name = switch_core_strdup(pool, cdr_field->var_name); + } + + /* Assume all fields should be quoted (treated as strings), unless specified otherwise */ + if ((attr = switch_xml_attr(field, "quote")) && !strncmp(attr, "false", 5)) { + cdr_field->quote = SWITCH_FALSE; + } else { + cdr_field->quote = SWITCH_TRUE; + } + + /* Assume all fields allow SQL nulls, unless specified otherwise */ + if ((attr = switch_xml_attr(field, "not-null")) && !strncmp(attr, "true", 4)) { + cdr_field->not_null = SWITCH_TRUE; + } else { + cdr_field->not_null = SWITCH_FALSE; + } + + len += strlen(cdr_field->col_name) + 1; + cdr_field++; + } + } + cdr_field->var_name = 0; + + globals.db_schema->columns = switch_core_alloc(pool, len); + ptr = globals.db_schema->columns; + for (cdr_field = globals.db_schema->fields; cdr_field->col_name; cdr_field++) { + len = strlen(cdr_field->col_name); + memcpy(ptr, cdr_field->col_name, len); + ptr += len; + *ptr = ','; + ptr++; + } + *--ptr = '\0'; } + switch_xml_free(xml); } @@ -596,7 +538,6 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_cdr_pg_csv_load) switch_core_add_state_handler(&state_handlers); *module_interface = switch_loadable_module_create_module_interface(pool, modname); - return status; } From 3830484155cfa3bd8ef09b88515e8afa6c251121 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Mon, 7 Feb 2011 16:06:45 -0600 Subject: [PATCH 34/36] freetdm: do not expect result_cb to be set to make the interface cleaner --- libs/freetdm/src/ftdm_io.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 0f92f59053..c9000de1f2 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -37,9 +37,6 @@ * */ -#ifdef MOYTEST -crap -#endif #define _GNU_SOURCE #include "private/ftdm_core.h" #include @@ -2509,10 +2506,12 @@ FT_DECLARE(ftdm_status_t) _ftdm_call_place(const char *file, const char *func, i } /* we have a locked channel and are not afraid of using it! */ - status = hunting->result_cb(fchan, caller_data); - if (status != FTDM_SUCCESS) { - status = FTDM_ECANCELED; - goto done; + if (hunting->result_cb) { + status = hunting->result_cb(fchan, caller_data); + if (status != FTDM_SUCCESS) { + status = FTDM_ECANCELED; + goto done; + } } ftdm_channel_set_caller_data(fchan, caller_data); From 428ef9666734805fa7f97f8291c06252a4f1b798 Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Mon, 7 Feb 2011 17:29:26 -0500 Subject: [PATCH 35/36] freetdm: allow reception of FACILITY msg in any channel state when transparent facility is enabled --- .../ftmod_sangoma_isdn_stack_hndl.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c index 578677a39f..bcc7d938b7 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c @@ -801,6 +801,23 @@ void sngisdn_process_fac_ind (sngisdn_event_data_t *sngisdn_event) ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing FACILITY IND (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId); + if (signal_data->facility_ie_decode == SNGISDN_OPT_FALSE) { + /* If Facility decoding is disabled, we do not care about current call state, just pass event up to user */ + ftdm_sigmsg_t sigev; + if (facEvnt->facElmt.facStr.pres) { + get_facility_ie_str(ftdmchan, &facEvnt->facElmt.facStr.val[2], facEvnt->facElmt.facStr.len-2); + } + memset(&sigev, 0, sizeof(sigev)); + sigev.chan_id = ftdmchan->chan_id; + sigev.span_id = ftdmchan->span_id; + sigev.channel = ftdmchan; + + sigev.event_id = FTDM_SIGEVENT_FACILITY; + ftdm_span_send_signal(ftdmchan->span, &sigev); + ISDN_FUNC_TRACE_EXIT(__FUNCTION__); + return; + } + switch (ftdmchan->state) { case FTDM_CHANNEL_STATE_GET_CALLERID: /* Update the caller ID Name */ From df4a18dcba1ad6a3ac20f67982642e8fe0e35471 Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Tue, 8 Feb 2011 11:52:40 -0500 Subject: [PATCH 36/36] Fixes to support QSIG over T1 --- .../ftmod_sangoma_isdn_cfg.c | 2 + .../ftmod_sangoma_isdn_stack_cfg.c | 38 +++++++++++-------- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c index bd5b13bfec..9fe28190e1 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c @@ -84,6 +84,8 @@ static ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span signal_data->switchtype = SNGISDN_SWITCH_4ESS; } else if (!strcasecmp(switch_name, "dms100")) { signal_data->switchtype = SNGISDN_SWITCH_DMS100; + } else if (!strcasecmp(switch_name, "qsig")) { + signal_data->switchtype = SNGISDN_SWITCH_QSIG; } else { ftdm_log(FTDM_LOG_ERROR, "%s:Unsupported switchtype %s for trunktype:%s\n", span->name, switch_name, ftdm_trunk_type2str(span->trunk_type)); return FTDM_FAIL; diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c index a52a624dd0..1bd2753e81 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c @@ -667,25 +667,33 @@ ftdm_status_t sngisdn_stack_cfg_q931_dlsap(ftdm_span_t *span) cfg.t.cfg.s.inDLSAP.maxBSrvCnt = 2; cfg.t.cfg.s.inDLSAP.maxDSrvCnt = 2; #endif /* ISDN_SRV */ - - if (signal_data->signalling == SNGISDN_SIGNALING_NET) { - cfg.t.cfg.s.inDLSAP.ackOpt = TRUE; - cfg.t.cfg.s.inDLSAP.intType = NETWORK; - cfg.t.cfg.s.inDLSAP.clrGlr = FALSE; /* in case of glare, do not clear local call */ - cfg.t.cfg.s.inDLSAP.statEnqOpt = TRUE; - if (signal_data->switchtype == SNGISDN_SWITCH_EUROISDN || - signal_data->switchtype == SNGISDN_SWITCH_INSNET) { - cfg.t.cfg.s.inDLSAP.rstOpt = FALSE; - } else { - cfg.t.cfg.s.inDLSAP.rstOpt = TRUE; - } - } else { - cfg.t.cfg.s.inDLSAP.ackOpt = FALSE; - cfg.t.cfg.s.inDLSAP.intType = USER; + if (signal_data->switchtype == SNGISDN_SWITCH_QSIG) { + cfg.t.cfg.s.inDLSAP.ackOpt = TRUE; + cfg.t.cfg.s.inDLSAP.intType = SYM_USER; cfg.t.cfg.s.inDLSAP.clrGlr = TRUE; /* in case of glare, clear local call */ cfg.t.cfg.s.inDLSAP.statEnqOpt = FALSE; cfg.t.cfg.s.inDLSAP.rstOpt = FALSE; + } else { + if (signal_data->signalling == SNGISDN_SIGNALING_NET) { + cfg.t.cfg.s.inDLSAP.ackOpt = TRUE; + cfg.t.cfg.s.inDLSAP.intType = NETWORK; + cfg.t.cfg.s.inDLSAP.clrGlr = FALSE; /* in case of glare, do not clear local call */ + cfg.t.cfg.s.inDLSAP.statEnqOpt = TRUE; + + if (signal_data->switchtype == SNGISDN_SWITCH_EUROISDN || + signal_data->switchtype == SNGISDN_SWITCH_INSNET) { + cfg.t.cfg.s.inDLSAP.rstOpt = FALSE; + } else { + cfg.t.cfg.s.inDLSAP.rstOpt = TRUE; + } + } else { + cfg.t.cfg.s.inDLSAP.ackOpt = FALSE; + cfg.t.cfg.s.inDLSAP.intType = USER; + cfg.t.cfg.s.inDLSAP.clrGlr = TRUE; /* in case of glare, clear local call */ + cfg.t.cfg.s.inDLSAP.statEnqOpt = FALSE; + cfg.t.cfg.s.inDLSAP.rstOpt = FALSE; + } } /* Override the restart options if user selected that option */