mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-04-13 07:45:26 +00:00
OMG this rocks
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@102 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
parent
86c1904cce
commit
c5174dbcc8
@ -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);
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user