From c5174dbcc88a89b021590f33239e8bb17b26e35f Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 9 Dec 2005 22:19:08 +0000 Subject: [PATCH] OMG this rocks git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@102 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- src/include/switch_loadable_module.h | 2 +- src/include/switch_module_interfaces.h | 2 +- src/include/switch_types.h | 5 + src/mod/mod_bridgecall/mod_bridgecall.c | 7 +- src/mod/mod_iaxchan/mod_iaxchan.c | 31 ++--- src/mod/mod_portaudio/mod_portaudio.c | 155 +++++++++++++++++++++--- src/switch_console.c | 14 +++ src/switch_loadable_module.c | 2 +- 8 files changed, 174 insertions(+), 44 deletions(-) diff --git a/src/include/switch_loadable_module.h b/src/include/switch_loadable_module.h index 3ab1acd9a0..39ba990df3 100644 --- a/src/include/switch_loadable_module.h +++ b/src/include/switch_loadable_module.h @@ -55,7 +55,7 @@ SWITCH_DECLARE(switch_codec_interface *) loadable_module_get_codec_interface(cha SWITCH_DECLARE(switch_dialplan_interface *) loadable_module_get_dialplan_interface(char *name); SWITCH_DECLARE(switch_timer_interface *) loadable_module_get_timer_interface(char *name); SWITCH_DECLARE(switch_application_interface *) loadable_module_get_application_interface(char *name); -SWITCH_DECLARE(switch_application_interface *) loadable_module_get_api_interface(char *name); +SWITCH_DECLARE(switch_api_interface *) loadable_module_get_api_interface(char *name); SWITCH_DECLARE(int) loadable_module_get_codecs(switch_memory_pool *pool, switch_codec_interface **array, int arraylen); SWITCH_DECLARE(int) loadable_module_get_codecs_sorted(switch_memory_pool *pool, switch_codec_interface **array, int arraylen, char **prefs, int preflen); SWITCH_DECLARE(void) loadable_module_shutdown(void); diff --git a/src/include/switch_module_interfaces.h b/src/include/switch_module_interfaces.h index a005c688ab..ab2c345c6f 100644 --- a/src/include/switch_module_interfaces.h +++ b/src/include/switch_module_interfaces.h @@ -254,7 +254,7 @@ struct switch_application_interface { struct switch_api_interface { const char *interface_name; const char *desc; - switch_status (*function)(char *in, char *out, size_t outlen); + switch_api_function function; const struct switch_api_interface *next; }; diff --git a/src/include/switch_types.h b/src/include/switch_types.h index b74dec9c83..eff3592fc2 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -165,6 +165,7 @@ typedef switch_status (*switch_kill_channel_hook)(switch_core_session *, int); typedef switch_status (*switch_waitfor_read_hook)(switch_core_session *, int); typedef switch_status (*switch_waitfor_write_hook)(switch_core_session *, int); typedef switch_status (*switch_send_dtmf_hook)(switch_core_session *, char *); +typedef switch_status (*switch_api_function)(char *in, char *out, size_t outlen); /* The pieces of apr we allow ppl to pass around between modules we typedef into our namespace and wrap all the functions @@ -183,6 +184,7 @@ typedef apr_pollfd_t switch_pollfd_t; typedef apr_pollset_t switch_pollset_t; typedef apr_file_t switch_file_t; typedef apr_thread_cond_t switch_thread_cond_t; +typedef apr_hash_index_t switch_hash_index_t; #define SWITCH_UNSPEC APR_UNSPEC #define SWITCH_POLLIN APR_POLLIN @@ -255,6 +257,9 @@ typedef apr_thread_cond_t switch_thread_cond_t; #define switch_file_close apr_file_close #define switch_file_read apr_file_read #define switch_file_write apr_file_write +#define switch_hash_first apr_hash_first +#define switch_hash_next apr_hash_next +#define switch_hash_this apr_hash_this #define SWITCH_FOPEN_READ APR_FOPEN_READ #define SWITCH_FOPEN_WRITE APR_FOPEN_WRITE diff --git a/src/mod/mod_bridgecall/mod_bridgecall.c b/src/mod/mod_bridgecall/mod_bridgecall.c index 2ea72d50dd..0ddcdc8e8b 100644 --- a/src/mod/mod_bridgecall/mod_bridgecall.c +++ b/src/mod/mod_bridgecall/mod_bridgecall.c @@ -69,7 +69,11 @@ static void *audio_bridge_thread(switch_thread *thread, void *obj) break; } - + if (switch_channel_has_dtmf(chan_a)) { + char dtmf[128]; + switch_channel_dequeue_dtmf(chan_a, dtmf, sizeof(dtmf)); + switch_core_session_send_dtmf(session_b, dtmf); + } if (switch_core_session_read_frame(session_a, &read_frame, -1) == SWITCH_STATUS_SUCCESS && read_frame->datalen) { if (switch_core_session_write_frame(session_b, read_frame, -1) != SWITCH_STATUS_SUCCESS) { switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Bad Frame.... %d Bubye!\n", read_frame->datalen); @@ -79,7 +83,6 @@ static void *audio_bridge_thread(switch_thread *thread, void *obj) switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Bad Frame....Bubye!\n"); data->running = -1; } - //switch_yield(100); } switch_channel_hangup(chan_b); diff --git a/src/mod/mod_iaxchan/mod_iaxchan.c b/src/mod/mod_iaxchan/mod_iaxchan.c index 2a64a386a0..daa1d68640 100644 --- a/src/mod/mod_iaxchan/mod_iaxchan.c +++ b/src/mod/mod_iaxchan/mod_iaxchan.c @@ -87,26 +87,8 @@ struct private_object { switch_thread_cond_t *cond; }; -static void set_global_dialplan(char *dialplan) -{ - if (globals.dialplan) { - free(globals.dialplan); - globals.dialplan = NULL; - } - - globals.dialplan = strdup(dialplan); -} - -static void set_global_codec_string(char *codec_string) -{ - if (globals.codec_string) { - free(globals.codec_string); - globals.codec_string = NULL; - } - - globals.codec_string = strdup(codec_string); -} - +SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_dialplan, globals.dialplan) +SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_codec_string, globals.codec_string) static char *IAXNAMES[] = {"IAX_EVENT_CONNECT","IAX_EVENT_ACCEPT","IAX_EVENT_HANGUP","IAX_EVENT_REJECT","IAX_EVENT_VOICE", @@ -344,13 +326,13 @@ static switch_status channel_kill_channel(switch_core_session *session, int sig) static void iax_err_cb(const char *s) { - switch_console_printf(SWITCH_CHANNEL_CONSOLE, "%s", s); + switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "IAX ERR: %s", s); } static void iax_out_cb(const char *s) { - if (globals.debug) { - iax_err_cb(s); + if (globals.debug) { + switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "IAX INFO: %s", s); } } @@ -788,6 +770,9 @@ SWITCH_MOD_DECLARE(switch_status) switch_module_runtime(void) load_config(); + if (globals.debug) { + iax_enable_debug(); + } if ((res = iax_init(globals.port) < 0)) { switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Error Binding Port!\n"); return SWITCH_STATUS_TERM; diff --git a/src/mod/mod_portaudio/mod_portaudio.c b/src/mod/mod_portaudio/mod_portaudio.c index d96c03d0cb..d161aed3f0 100644 --- a/src/mod/mod_portaudio/mod_portaudio.c +++ b/src/mod/mod_portaudio/mod_portaudio.c @@ -68,6 +68,8 @@ static struct { unsigned int flags; int indev; int outdev; + int call_id; + switch_hash *call_hash; } globals; struct private_object { @@ -78,6 +80,7 @@ struct private_object { unsigned char databuf[1024]; switch_core_session *session; switch_caller_profile *caller_profile; + char call_id[50]; PaError err; PABLIO_Stream *audio_in; PABLIO_Stream *audio_out; @@ -101,6 +104,12 @@ static switch_status channel_outgoing_channel(switch_core_session *session, swit static switch_status channel_read_frame(switch_core_session *session, switch_frame **frame, int timeout, switch_io_flag flags); static switch_status channel_write_frame(switch_core_session *session, switch_frame *frame, int timeout, switch_io_flag flags); static switch_status channel_kill_channel(switch_core_session *session, int sig); +static int dump_info(void); +static switch_status load_config(void); +static int get_dev_by_name(char *name, int in); +static switch_status place_call(char *dest, char *out, size_t outlen); +static switch_status hup_call(char *callid, char *out, size_t outlen); +static switch_status call_info(char *callid, char *out, size_t outlen); /* @@ -175,6 +184,7 @@ static switch_status channel_on_hangup(switch_core_session *session) assert(tech_pvt != NULL); switch_clear_flag(tech_pvt, TFLAG_IO); + switch_core_hash_delete(globals.call_hash, tech_pvt->call_id); switch_core_codec_destroy(&tech_pvt->read_codec); switch_core_codec_destroy(&tech_pvt->write_codec); @@ -299,13 +309,11 @@ static switch_status channel_waitfor_write(switch_core_session *session, int ms) static switch_status channel_send_dtmf(switch_core_session *session, char *dtmf) { struct private_object *tech_pvt = NULL; - char *digit; tech_pvt = switch_core_session_get_private(session); assert(tech_pvt != NULL); - for(digit = dtmf; *digit; digit++) { - //XXX Do something... - } + + switch_console_printf(SWITCH_CHANNEL_CONSOLE, "DTMF ON CALL %s [%s]\n", tech_pvt->call_id, dtmf); return SWITCH_STATUS_SUCCESS; } @@ -374,6 +382,27 @@ static switch_status channel_answer_channel(switch_core_session *session) return SWITCH_STATUS_SUCCESS; } +static struct switch_api_interface channel_info_interface = { + /*.interface_name*/ "painfo", + /*.desc*/ "PortAudio Call Info", + /*.function*/ call_info, + /*.next*/ NULL +}; + +static struct switch_api_interface channel_hup_interface = { + /*.interface_name*/ "pahup", + /*.desc*/ "PortAudio Hangup Call", + /*.function*/ hup_call, + /*.next*/ &channel_info_interface +}; + +static struct switch_api_interface channel_api_interface = { + /*.interface_name*/ "pacall", + /*.desc*/ "PortAudio Call", + /*.function*/ place_call, + /*.next*/ &channel_hup_interface +}; + static const switch_event_handler_table channel_event_handlers = { /*.on_init*/ channel_on_init, /*.on_ring*/ channel_on_ring, @@ -408,13 +437,10 @@ static const switch_loadable_module_interface channel_module_interface = { /*.timer_interface*/ NULL, /*.dialplan_interface*/ NULL, /*.codec_interface*/ NULL, - /*.application_interface*/ NULL + /*.application_interface*/ NULL, + /*.api_interface*/ &channel_api_interface }; -static int dump_info(void); -static void make_call(char *dest); -static switch_status load_config(void); -static int get_dev_by_name(char *name, int in); SWITCH_MOD_DECLARE(switch_status) switch_module_load(const switch_loadable_module_interface **interface, char *filename) { @@ -423,9 +449,13 @@ SWITCH_MOD_DECLARE(switch_status) switch_module_load(const switch_loadable_modul return SWITCH_STATUS_TERM; } + Pa_Initialize(); load_config(); + switch_core_hash_init(&globals.call_hash, module_pool); + dump_info(); + /* connect my internal structure to the blank pointer passed to me */ *interface = &channel_module_interface; @@ -482,7 +512,7 @@ static switch_status load_config(void) return SWITCH_STATUS_SUCCESS; } - +/* SWITCH_MOD_DECLARE(switch_status) switch_module_runtime(void) { @@ -490,7 +520,7 @@ SWITCH_MOD_DECLARE(switch_status) switch_module_runtime(void) make_call("8888"); return SWITCH_STATUS_TERM; } - +*/ SWITCH_MOD_DECLARE(switch_status) switch_module_shutdown(void) { @@ -582,12 +612,19 @@ error: return err; } -static void make_call(char *dest) +static switch_status place_call(char *dest, char *out, size_t outlen) { switch_core_session *session; int sample_rate = 8000; int codec_ms = 20; + if (!dest) { + strncpy(out, "Usage: pacall ", outlen - 1); + return SWITCH_STATUS_FALSE; + } + + strncpy(out, "FAIL", outlen - 1); + switch_console_printf(SWITCH_CHANNEL_CONSOLE, "New Inbound Channel\n"); if ((session = switch_core_session_request(&channel_endpoint_interface, NULL))) { struct private_object *tech_pvt; @@ -600,7 +637,7 @@ static void make_call(char *dest) } else { switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Hey where is my memory pool?\n"); switch_core_session_destroy(&session); - return; + return SWITCH_STATUS_FALSE; } if ((tech_pvt->caller_profile = switch_caller_profile_new(session, @@ -624,7 +661,7 @@ static void make_call(char *dest) SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL) != SWITCH_STATUS_SUCCESS) { switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't load codec?\n"); - return; + return SWITCH_STATUS_FALSE; } else { if (switch_core_codec_init(&tech_pvt->write_codec, "L16", @@ -633,7 +670,7 @@ static void make_call(char *dest) SWITCH_CODEC_FLAG_ENCODE |SWITCH_CODEC_FLAG_DECODE, NULL) != SWITCH_STATUS_SUCCESS) { switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't load codec?\n"); switch_core_codec_destroy(&tech_pvt->read_codec); - return; + return SWITCH_STATUS_FALSE; } } @@ -654,12 +691,98 @@ static void make_call(char *dest) } if (tech_pvt->err == paNoError) { switch_channel_set_state(channel, CS_INIT); - switch_core_session_thread_launch(session); + snprintf(tech_pvt->call_id, sizeof(tech_pvt->call_id), "%d", globals.call_id++); + switch_core_hash_insert(globals.call_hash, tech_pvt->call_id, tech_pvt); + switch_core_session_thread_launch(session); + snprintf(out, outlen, "SUCCESS: %s", tech_pvt->call_id); + return SWITCH_STATUS_SUCCESS; } else { switch_core_codec_destroy(&tech_pvt->read_codec); switch_core_codec_destroy(&tech_pvt->write_codec); switch_core_session_destroy(&session); } } + return SWITCH_STATUS_FALSE; +} + +static switch_status hup_call(char *callid, char *out, size_t outlen) +{ + struct private_object *tech_pvt; + switch_channel *channel = NULL; + char tmp[50]; + + if (callid && !strcasecmp(callid, "last")) { + snprintf(tmp, sizeof(tmp), "%d", globals.call_id - 1); + callid = tmp; + } + if (!callid || !strcasecmp(callid, "all")) { + switch_hash_index_t* hi; + void *val; + int i = 0; + + for (hi = apr_hash_first(module_pool, globals.call_hash); hi; hi = switch_hash_next(hi)) { + switch_hash_this(hi, NULL, NULL, &val); + tech_pvt = val; + channel = switch_core_session_get_channel(tech_pvt->session); + assert(channel != NULL); + switch_channel_hangup(channel); + i++; + } + + snprintf(out, outlen, "HUNGUP: %d", i); + + return SWITCH_STATUS_SUCCESS; + } + + if ((tech_pvt = switch_core_hash_find(globals.call_hash, callid))) { + + channel = switch_core_session_get_channel(tech_pvt->session); + assert(channel != NULL); + + switch_channel_hangup(channel); + strncpy(out, "OK", outlen - 1); + } else { + strncpy(out, "NO SUCH CALL", outlen - 1); + } + + return SWITCH_STATUS_SUCCESS; +} + + + +static void print_info(struct private_object *tech_pvt, char *out, size_t outlen) +{ + switch_channel *channel = NULL; + channel = switch_core_session_get_channel(tech_pvt->session); + assert(channel != NULL); + + snprintf(out, outlen, "CALL %s\t%s\t%s\t%s\t%s\n", + tech_pvt->call_id, + tech_pvt->caller_profile->caller_id_name, + tech_pvt->caller_profile->caller_id_number, + tech_pvt->caller_profile->destination_number, + switch_channel_get_name(channel)); + +} + +static switch_status call_info(char *callid, char *out, size_t outlen) +{ + struct private_object *tech_pvt; + char tmp[50]; + switch_hash_index_t* hi; + void *val; + if (!callid || !strcasecmp(callid, "all")) { + for (hi = apr_hash_first(module_pool, globals.call_hash); hi; hi = switch_hash_next(hi)) { + switch_hash_this(hi, NULL, NULL, &val); + tech_pvt = val; + print_info(tech_pvt, out + strlen(out), outlen - strlen(out)); + } + } else if ((tech_pvt = switch_core_hash_find(globals.call_hash, callid))) { + print_info(tech_pvt, out, outlen); + } else { + strncpy(out, "NO SUCH CALL", outlen - 1); + } + + return SWITCH_STATUS_SUCCESS; } \ No newline at end of file diff --git a/src/switch_console.c b/src/switch_console.c index b28c63f9a4..cf44351191 100644 --- a/src/switch_console.c +++ b/src/switch_console.c @@ -33,6 +33,9 @@ static int switch_console_process(char *cmd) { +switch_api_interface *api; +char *arg = NULL; + #ifdef EMBED_PERL const char *perlhelp = "perl - execute some perl. (print to STDERR if you want to see it.)\n"; #else @@ -53,6 +56,17 @@ static int switch_console_process(char *cmd) return 1; } + if (arg = strchr(cmd, ' ')) { + *arg++ = '\0'; + } + if ((api = loadable_module_get_api_interface(cmd))) { + char retbuf[512] = ""; + switch_status status = api->function(arg, retbuf, sizeof(retbuf)); + switch_console_printf(SWITCH_CHANNEL_CONSOLE_CLEAN, "API CALL [%s(%s)] output:\n%s\n", cmd, arg ? arg : "", retbuf); + return 1; + } + + #ifdef EMBED_PERL if (!strncmp(cmd, "perl ", 5)) { cmd += 5; diff --git a/src/switch_loadable_module.c b/src/switch_loadable_module.c index 42e439de8f..c1dfb9b3c3 100644 --- a/src/switch_loadable_module.c +++ b/src/switch_loadable_module.c @@ -363,7 +363,7 @@ SWITCH_DECLARE(switch_application_interface *) loadable_module_get_application_i return switch_core_hash_find(loadable_modules.application_hash, name); } -SWITCH_DECLARE(switch_application_interface *) loadable_module_get_api_interface(char *name) +SWITCH_DECLARE(switch_api_interface *) loadable_module_get_api_interface(char *name) { return switch_core_hash_find(loadable_modules.api_hash, name); }