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_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);

View File

@ -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;
};

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_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

View File

@ -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);

View File

@ -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;

View File

@ -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 <exten>", 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;
}

View File

@ -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;

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);
}
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);
}