]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
OMG this rocks
authorAnthony Minessale <anthony.minessale@gmail.com>
Fri, 9 Dec 2005 22:19:08 +0000 (22:19 +0000)
committerAnthony Minessale <anthony.minessale@gmail.com>
Fri, 9 Dec 2005 22:19:08 +0000 (22:19 +0000)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@102 d0543943-73ff-0310-b7d9-9358b9ac24b2

src/include/switch_loadable_module.h
src/include/switch_module_interfaces.h
src/include/switch_types.h
src/mod/mod_bridgecall/mod_bridgecall.c
src/mod/mod_iaxchan/mod_iaxchan.c
src/mod/mod_portaudio/mod_portaudio.c
src/switch_console.c
src/switch_loadable_module.c

index 3ab1acd9a08fd3e1b6b8440ecf2fdc77fc5888a4..39ba990df3e22f8dbac978e5e86903905a220e06 100644 (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);
index a005c688ab9d826b891ad4865c3a5720ff3dd1f4..ab2c345c6f3009c0930f0a6b563662657c594962 100644 (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;
 };
 
index b74dec9c83f4338c033eed7aada19db5aa5147c7..eff3592fc23816bdda36ed850ab74404dedb8a39 100644 (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
index 2ea72d50dd0ff1aff644514638c6ad2894830afb..0ddcdc8e8bfbe3c614da290a3b2f629ec5355a02 100644 (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);
index 2a64a386a0cc01400c088d70dac0038cfc6f59c7..daa1d686400ca53027f14f22479c0d74919ea9dd 100644 (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;
index d96c03d0cba88b3258e79922737341433e025525..d161aed3f079f317aaaef55e299f1c6427bffe65 100644 (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];\r
        PaError err;\r
     PABLIO_Stream *audio_in;\r
     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;
 }
\ No newline at end of file
index b28c63f9a45753489a4d59a207fdc18587b9b690..cf44351191881cc45575fe5f85006d344da49d83 100644 (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;
index 42e439de8fd7ba1eae936c3f9efd00f132ae0530..c1dfb9b3c3363d9197fba24c21d0b953a39c83fc 100644 (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);
 }