OMG this rocks

git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@102 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
Anthony Minessale 2005-12-09 22:19:08 +00:00
parent 86c1904cce
commit c5174dbcc8
8 changed files with 174 additions and 44 deletions

View File

@ -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_dialplan_interface *) loadable_module_get_dialplan_interface(char *name);
SWITCH_DECLARE(switch_timer_interface *) loadable_module_get_timer_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_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(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(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); SWITCH_DECLARE(void) loadable_module_shutdown(void);

View File

@ -254,7 +254,7 @@ struct switch_application_interface {
struct switch_api_interface { struct switch_api_interface {
const char *interface_name; const char *interface_name;
const char *desc; const char *desc;
switch_status (*function)(char *in, char *out, size_t outlen); switch_api_function function;
const struct switch_api_interface *next; const struct switch_api_interface *next;
}; };

View File

@ -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_read_hook)(switch_core_session *, int);
typedef switch_status (*switch_waitfor_write_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_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 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_pollset_t switch_pollset_t;
typedef apr_file_t switch_file_t; typedef apr_file_t switch_file_t;
typedef apr_thread_cond_t switch_thread_cond_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_UNSPEC APR_UNSPEC
#define SWITCH_POLLIN APR_POLLIN #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_close apr_file_close
#define switch_file_read apr_file_read #define switch_file_read apr_file_read
#define switch_file_write apr_file_write #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_READ APR_FOPEN_READ
#define SWITCH_FOPEN_WRITE APR_FOPEN_WRITE #define SWITCH_FOPEN_WRITE APR_FOPEN_WRITE

View File

@ -69,7 +69,11 @@ static void *audio_bridge_thread(switch_thread *thread, void *obj)
break; 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_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) { 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); 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"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Bad Frame....Bubye!\n");
data->running = -1; data->running = -1;
} }
//switch_yield(100);
} }
switch_channel_hangup(chan_b); switch_channel_hangup(chan_b);

View File

@ -87,26 +87,8 @@ struct private_object {
switch_thread_cond_t *cond; switch_thread_cond_t *cond;
}; };
static void set_global_dialplan(char *dialplan) SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_dialplan, globals.dialplan)
{ SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_codec_string, globals.codec_string)
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);
}
static char *IAXNAMES[] = {"IAX_EVENT_CONNECT","IAX_EVENT_ACCEPT","IAX_EVENT_HANGUP","IAX_EVENT_REJECT","IAX_EVENT_VOICE", 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) 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) static void iax_out_cb(const char *s)
{ {
if (globals.debug) { if (globals.debug) {
iax_err_cb(s); 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(); load_config();
if (globals.debug) {
iax_enable_debug();
}
if ((res = iax_init(globals.port) < 0)) { if ((res = iax_init(globals.port) < 0)) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Error Binding Port!\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Error Binding Port!\n");
return SWITCH_STATUS_TERM; return SWITCH_STATUS_TERM;

View File

@ -68,6 +68,8 @@ static struct {
unsigned int flags; unsigned int flags;
int indev; int indev;
int outdev; int outdev;
int call_id;
switch_hash *call_hash;
} globals; } globals;
struct private_object { struct private_object {
@ -78,6 +80,7 @@ struct private_object {
unsigned char databuf[1024]; unsigned char databuf[1024];
switch_core_session *session; switch_core_session *session;
switch_caller_profile *caller_profile; switch_caller_profile *caller_profile;
char call_id[50];
PaError err; PaError err;
PABLIO_Stream *audio_in; PABLIO_Stream *audio_in;
PABLIO_Stream *audio_out; 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_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_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 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); assert(tech_pvt != NULL);
switch_clear_flag(tech_pvt, TFLAG_IO); 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->read_codec);
switch_core_codec_destroy(&tech_pvt->write_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) static switch_status channel_send_dtmf(switch_core_session *session, char *dtmf)
{ {
struct private_object *tech_pvt = NULL; struct private_object *tech_pvt = NULL;
char *digit;
tech_pvt = switch_core_session_get_private(session); tech_pvt = switch_core_session_get_private(session);
assert(tech_pvt != NULL); 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; return SWITCH_STATUS_SUCCESS;
} }
@ -374,6 +382,27 @@ static switch_status channel_answer_channel(switch_core_session *session)
return SWITCH_STATUS_SUCCESS; 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 = { static const switch_event_handler_table channel_event_handlers = {
/*.on_init*/ channel_on_init, /*.on_init*/ channel_on_init,
/*.on_ring*/ channel_on_ring, /*.on_ring*/ channel_on_ring,
@ -408,13 +437,10 @@ static const switch_loadable_module_interface channel_module_interface = {
/*.timer_interface*/ NULL, /*.timer_interface*/ NULL,
/*.dialplan_interface*/ NULL, /*.dialplan_interface*/ NULL,
/*.codec_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) { 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; return SWITCH_STATUS_TERM;
} }
Pa_Initialize(); Pa_Initialize();
load_config(); load_config();
switch_core_hash_init(&globals.call_hash, module_pool);
dump_info(); dump_info();
/* connect my internal structure to the blank pointer passed to me */ /* connect my internal structure to the blank pointer passed to me */
*interface = &channel_module_interface; *interface = &channel_module_interface;
@ -482,7 +512,7 @@ static switch_status load_config(void)
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
/*
SWITCH_MOD_DECLARE(switch_status) switch_module_runtime(void) 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"); make_call("8888");
return SWITCH_STATUS_TERM; return SWITCH_STATUS_TERM;
} }
*/
SWITCH_MOD_DECLARE(switch_status) switch_module_shutdown(void) SWITCH_MOD_DECLARE(switch_status) switch_module_shutdown(void)
{ {
@ -582,12 +612,19 @@ error:
return err; return err;
} }
static void make_call(char *dest) static switch_status place_call(char *dest, char *out, size_t outlen)
{ {
switch_core_session *session; switch_core_session *session;
int sample_rate = 8000; int sample_rate = 8000;
int codec_ms = 20; int codec_ms = 20;
if (!dest) {
strncpy(out, "Usage: pacall <exten>", outlen - 1);
return SWITCH_STATUS_FALSE;
}
strncpy(out, "FAIL", outlen - 1);
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "New Inbound Channel\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "New Inbound Channel\n");
if ((session = switch_core_session_request(&channel_endpoint_interface, NULL))) { if ((session = switch_core_session_request(&channel_endpoint_interface, NULL))) {
struct private_object *tech_pvt; struct private_object *tech_pvt;
@ -600,7 +637,7 @@ static void make_call(char *dest)
} else { } else {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Hey where is my memory pool?\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Hey where is my memory pool?\n");
switch_core_session_destroy(&session); switch_core_session_destroy(&session);
return; return SWITCH_STATUS_FALSE;
} }
if ((tech_pvt->caller_profile = switch_caller_profile_new(session, 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, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
NULL) != SWITCH_STATUS_SUCCESS) { NULL) != SWITCH_STATUS_SUCCESS) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't load codec?\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't load codec?\n");
return; return SWITCH_STATUS_FALSE;
} else { } else {
if (switch_core_codec_init(&tech_pvt->write_codec, if (switch_core_codec_init(&tech_pvt->write_codec,
"L16", "L16",
@ -633,7 +670,7 @@ static void make_call(char *dest)
SWITCH_CODEC_FLAG_ENCODE |SWITCH_CODEC_FLAG_DECODE, NULL) != SWITCH_STATUS_SUCCESS) { SWITCH_CODEC_FLAG_ENCODE |SWITCH_CODEC_FLAG_DECODE, NULL) != SWITCH_STATUS_SUCCESS) {
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't load codec?\n"); switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Can't load codec?\n");
switch_core_codec_destroy(&tech_pvt->read_codec); 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) { if (tech_pvt->err == paNoError) {
switch_channel_set_state(channel, CS_INIT); 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 { } else {
switch_core_codec_destroy(&tech_pvt->read_codec); switch_core_codec_destroy(&tech_pvt->read_codec);
switch_core_codec_destroy(&tech_pvt->write_codec); switch_core_codec_destroy(&tech_pvt->write_codec);
switch_core_session_destroy(&session); 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;
}

View File

@ -33,6 +33,9 @@
static int switch_console_process(char *cmd) static int switch_console_process(char *cmd)
{ {
switch_api_interface *api;
char *arg = NULL;
#ifdef EMBED_PERL #ifdef EMBED_PERL
const char *perlhelp = "perl - execute some perl. (print to STDERR if you want to see it.)\n"; const char *perlhelp = "perl - execute some perl. (print to STDERR if you want to see it.)\n";
#else #else
@ -53,6 +56,17 @@ static int switch_console_process(char *cmd)
return 1; 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 #ifdef EMBED_PERL
if (!strncmp(cmd, "perl ", 5)) { if (!strncmp(cmd, "perl ", 5)) {
cmd += 5; cmd += 5;

View File

@ -363,7 +363,7 @@ SWITCH_DECLARE(switch_application_interface *) loadable_module_get_application_i
return switch_core_hash_find(loadable_modules.application_hash, name); 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); return switch_core_hash_find(loadable_modules.api_hash, name);
} }