]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FS-3252 additional fix to this bug and add better fax detect code to mod_spandsp
authorAnthony Minessale <anthm@freeswitch.org>
Tue, 19 Apr 2011 18:29:42 +0000 (13:29 -0500)
committerAnthony Minessale <anthm@freeswitch.org>
Tue, 19 Apr 2011 18:29:42 +0000 (13:29 -0500)
src/mod/applications/mod_spandsp/mod_spandsp.c
src/mod/applications/mod_spandsp/mod_spandsp.h
src/mod/applications/mod_spandsp/mod_spandsp_fax.c

index ecb660eabba6fe901052ebf079c22cd3ceb28d60..fd2ac7f9475d6e2b84f1feda10bec4f6e90f2769 100644 (file)
@@ -70,11 +70,46 @@ SWITCH_STANDARD_APP(stop_dtmf_session_function)
        spandsp_stop_inband_dtmf_session(session);
 }
 
+
+SWITCH_STANDARD_APP(spandsp_fax_detect_session_function)
+{
+    int argc = 0;
+    char *argv[3] = { 0 };
+    char *dupdata;
+    const char *app = NULL, *arg = NULL;
+    int timeout = 0;
+
+    if (!zstr(data) && (dupdata = switch_core_session_strdup(session, data))) {
+        if ((argc = switch_split(dupdata, ' ', argv)) == 3) {
+            app = argv[0];
+            arg = argv[1];
+            timeout = atoi(argv[2]);
+            if (timeout < 0) {
+                timeout = 0;
+            }
+        }
+    }
+    
+    if (app) {
+        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Enabling fax detection '%s' '%s'\n", argv[0], argv[1]);
+        spandsp_fax_detect_session(session, "rw", timeout, 1, app, arg, NULL);
+    } else {
+        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot Enable fax detection '%s' '%s'\n", argv[0], argv[1]);
+    }
+}
+
+SWITCH_STANDARD_APP(spandsp_stop_fax_detect_session_function)
+{
+       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Disabling fax detection\n");
+    spandsp_fax_stop_detect_session(session);
+}
+
 static void event_handler(switch_event_t *event)
 {
        mod_spandsp_fax_event_handler(event);
 }
 
+
 SWITCH_STANDARD_APP(t38_gateway_function)
 {
     switch_channel_t *channel = switch_core_session_get_channel(session);
@@ -83,10 +118,19 @@ SWITCH_STANDARD_APP(t38_gateway_function)
     int argc = 0;
     char *argv[2] = { 0 };
     char *dupdata;
-    const char *direction = argv[0], *flags = argv[1];
+    const char *direction = NULL, *flags = NULL;
     
-    dupdata = switch_core_session_strdup(session, data);
-    argc = switch_split(dupdata, ' ', argv);
+    if (!zstr(data) && (dupdata = switch_core_session_strdup(session, data))) {
+        if ((argc = switch_split(dupdata, ' ', argv))) {
+            if (argc > 0) {
+                direction = argv[0];
+            }
+            
+            if (argc > 1) {
+                flags = argv[1];
+            }
+        }
+    }
 
     if (zstr(direction) || strcasecmp(direction, "self")) {
         direction = "peer";
@@ -106,7 +150,8 @@ SWITCH_STANDARD_APP(t38_gateway_function)
             }
         }
 
-        switch_ivr_tone_detect_session(session, "t38", "1100.0", "rw", timeout, 1, direction, NULL, t38_gateway_start);        
+        //switch_ivr_tone_detect_session(session, "t38", "1100.0", "rw", timeout, 1, direction, NULL, t38_gateway_start);        
+        spandsp_fax_detect_session(session, "rw", timeout, 1, direction, NULL, t38_gateway_start);
     }
 }
 
@@ -209,6 +254,12 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_spandsp_init)
        SWITCH_ADD_APP(app_interface, "spandsp_stop_dtmf", "stop inband dtmf", "Stop detecting inband dtmf.", stop_dtmf_session_function, "", SAF_NONE);
        SWITCH_ADD_APP(app_interface, "spandsp_start_dtmf", "Detect dtmf", "Detect inband dtmf on the session", dtmf_session_function, "", SAF_MEDIA_TAP);
 
+       SWITCH_ADD_APP(app_interface, "spandsp_start_fax_detect", "start fax detect", "start fax detect", spandsp_fax_detect_session_function, 
+                   "<app>[ <arg>][ <timeout>]", SAF_NONE);
+
+       SWITCH_ADD_APP(app_interface, "spandsp_stop_fax_detect", "stop fax detect", "stop fax detect", spandsp_stop_fax_detect_session_function, "", SAF_NONE);
+                   
+
        mod_spandsp_fax_load(pool);
     mod_spandsp_codecs_load(module_interface, pool);
 
index 09e816627a9b078d043073730af3522247a1cf89..7b94b55062bb2038f6d7d5e0bfb956af5d75e3fc 100644 (file)
@@ -68,3 +68,9 @@ switch_status_t spandsp_inband_dtmf_session(switch_core_session_t *session);
 
 switch_status_t callprogress_detector_start(switch_core_session_t *session, const char *name);
 switch_status_t callprogress_detector_stop(switch_core_session_t *session);
+
+SWITCH_DECLARE(switch_status_t) spandsp_fax_detect_session(switch_core_session_t *session,
+                                                                                                                  const char *flags, time_t timeout,
+                                                                                                                  int hits, const char *app, const char *data, switch_tone_detect_callback_t callback);
+
+SWITCH_DECLARE(switch_status_t) spandsp_fax_stop_detect_session(switch_core_session_t *session);
index 1ea2fd790f5d3d30b51c17a0b95e85aa83228ab1..620971b3078959b2644e4ed77d0e440450bbae46 100644 (file)
@@ -1806,6 +1806,250 @@ switch_bool_t t38_gateway_start(switch_core_session_t *session, const char *app,
     return SWITCH_FALSE;
 }
 
+typedef struct {
+       char *app;
+       char *data;
+       char *key;
+       int up;
+       int total_hits;
+       int hits;
+       int sleep;
+       int expires;
+       int default_sleep;
+       int default_expires;
+       switch_tone_detect_callback_t callback; 
+       modem_connect_tones_rx_state_t rx_tones;
+
+       switch_media_bug_t *bug;
+       switch_core_session_t *session;
+       int bug_running;
+       
+} spandsp_fax_tone_container_t;
+
+static switch_status_t tone_on_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf, switch_dtmf_direction_t direction)
+{
+       switch_channel_t *channel = switch_core_session_get_channel(session);
+       spandsp_fax_tone_container_t *cont = switch_channel_get_private(channel, "_fax_tone_detect_");
+       
+
+       if (!cont || dtmf->digit != 'f') {
+               return SWITCH_STATUS_SUCCESS;
+       }
+
+       if (cont->callback) {
+               cont->callback(cont->session, cont->app, cont->data);
+       } else {
+               switch_channel_execute_on(switch_core_session_get_channel(cont->session), "execute_on_fax_detect");
+               if (cont->app) {
+                       switch_core_session_execute_application_async(cont->session, cont->app, cont->data);
+               }
+       }
+               
+       return SWITCH_STATUS_SUCCESS;
+
+}
+
+
+static switch_bool_t tone_detect_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type)
+{
+       spandsp_fax_tone_container_t *cont = (spandsp_fax_tone_container_t *) user_data;
+       switch_frame_t *frame = NULL;
+       switch_bool_t rval = SWITCH_TRUE;
+
+       switch (type) {
+       case SWITCH_ABC_TYPE_INIT:
+               if (cont) {
+                       cont->bug_running = 1;
+                       modem_connect_tones_rx_init(&cont->rx_tones, MODEM_CONNECT_TONES_FAX_CED_OR_PREAMBLE, NULL, NULL);
+               }
+               break;
+       case SWITCH_ABC_TYPE_CLOSE:
+               break;
+       case SWITCH_ABC_TYPE_READ_REPLACE:
+       case SWITCH_ABC_TYPE_WRITE_REPLACE:
+               {
+                       int skip = 0;
+                       
+                       if (type == SWITCH_ABC_TYPE_READ_REPLACE) {
+                               frame = switch_core_media_bug_get_read_replace_frame(bug);
+                       } else {
+                               frame = switch_core_media_bug_get_write_replace_frame(bug);
+                       }
+                       
+                       if (cont->sleep) {
+                               cont->sleep--;
+                               if (cont->sleep) {
+                                       skip = 1;
+                               }
+                       }
+
+                       if (cont->expires) {
+                               cont->expires--;
+                               if (!cont->expires) {
+                                       cont->hits = 0;
+                                       cont->sleep = 0;
+                                       cont->expires = 0;
+                               }
+                       }
+
+                       if (!cont->up) {
+                               skip = 1;
+                       }
+
+                       if (skip) {
+                               return SWITCH_TRUE;
+                       }
+
+                       cont->hits = 0;
+                       modem_connect_tones_rx(&cont->rx_tones, frame->data, frame->samples);
+                       cont->hits = modem_connect_tones_rx_get(&cont->rx_tones);
+
+                       if (cont->hits) {
+                               switch_event_t *event;
+                               
+                               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(switch_core_media_bug_get_session(bug)), SWITCH_LOG_DEBUG,
+                                                                 "Fax Tone Detected. [%s][%s]\n", cont->app, switch_str_nil(cont->data));
+
+                               if (cont->callback) {
+                                       cont->callback(cont->session, cont->app, cont->data);
+                               } else {
+                                       switch_channel_execute_on(switch_core_session_get_channel(cont->session), "execute_on_fax_detect");
+                                       if (cont->app) {
+                                               switch_core_session_execute_application_async(cont->session, cont->app, cont->data);
+                                       }
+                               }
+                               
+
+                               if (switch_event_create(&event, SWITCH_EVENT_DETECTED_TONE) == SWITCH_STATUS_SUCCESS) {
+                                       switch_event_t *dup;
+                                       switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Detected-Fax-Tone", "true");
+                               
+                                       if (switch_event_dup(&dup, event) == SWITCH_STATUS_SUCCESS) {
+                                               switch_event_fire(&dup);
+                                       }
+
+                                       if (switch_core_session_queue_event(cont->session, &event) != SWITCH_STATUS_SUCCESS) {
+                                               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(switch_core_media_bug_get_session(bug)), SWITCH_LOG_ERROR,
+                                                                                 "Event queue failed!\n");
+                                               switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "delivery-failure", "true");
+                                               switch_event_fire(&event);
+                                       }
+                               }
+
+                               rval = SWITCH_FALSE;
+                       }
+                       
+               }
+               break;
+       case SWITCH_ABC_TYPE_WRITE:
+       default:
+               break;
+       }
+
+       if (rval == SWITCH_FALSE) {
+               cont->bug_running = 0;
+       }
+
+       return rval;
+}
+
+SWITCH_DECLARE(switch_status_t) spandsp_fax_stop_detect_session(switch_core_session_t *session)
+{
+       switch_channel_t *channel = switch_core_session_get_channel(session);
+       spandsp_fax_tone_container_t *cont = switch_channel_get_private(channel, "_fax_tone_detect_");
+
+       if (cont) {
+               switch_channel_set_private(channel, "_fax_tone_detect_", NULL);
+               cont->up = 0;
+               switch_core_media_bug_remove(session, &cont->bug);
+               return SWITCH_STATUS_SUCCESS;
+       }
+       return SWITCH_STATUS_FALSE;
+}
+
+SWITCH_DECLARE(switch_status_t) spandsp_fax_detect_session(switch_core_session_t *session,
+                                                                                                                  const char *flags, time_t timeout,
+                                                                                                                  int hits, const char *app, const char *data, switch_tone_detect_callback_t callback)
+{
+       switch_channel_t *channel = switch_core_session_get_channel(session);
+       switch_status_t status;
+       spandsp_fax_tone_container_t *cont = switch_channel_get_private(channel, "_fax_tone_detect_");
+       switch_media_bug_flag_t bflags = 0;
+       const char *var;
+       switch_codec_implementation_t read_impl = { 0 };
+       switch_core_session_get_read_impl(session, &read_impl);
+
+       if (cont) {
+               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Max Tones Reached!\n");
+               return SWITCH_STATUS_FALSE;
+       }
+
+       if (!cont && !(cont = switch_core_session_alloc(session, sizeof(*cont)))) {
+               return SWITCH_STATUS_MEMERR;
+       }
+
+       if (app) {
+               cont->app = switch_core_session_strdup(session, app);
+       }
+
+       if (data) {
+               cont->data = switch_core_session_strdup(session, data);
+       }
+
+       cont->callback = callback;
+       cont->up = 1;
+       cont->session = session;
+
+       if (switch_channel_pre_answer(channel) != SWITCH_STATUS_SUCCESS) {
+               return SWITCH_STATUS_FALSE;
+       }
+
+       cont->default_sleep = 25;
+       cont->default_expires = 250;
+
+       if ((var = switch_channel_get_variable(channel, "fax_tone_detect_sleep"))) {
+               int tmp = atoi(var);
+               if (tmp > 0) {
+                       cont->default_sleep = tmp;
+               }
+       }
+
+       if ((var = switch_channel_get_variable(channel, "fax_tone_detect_expires"))) {
+               int tmp = atoi(var);
+               if (tmp > 0) {
+                       cont->default_expires = tmp;
+               }
+       }
+
+       if (zstr(flags)) {
+               bflags = SMBF_READ_REPLACE;
+       } else {
+               if (strchr(flags, 'r')) {
+                       bflags |= SMBF_READ_REPLACE;
+               } else if (strchr(flags, 'w')) {
+                       bflags |= SMBF_WRITE_REPLACE;
+               }
+       }
+
+       bflags |= SMBF_NO_PAUSE;
+
+
+       switch_core_event_hook_add_send_dtmf(session, tone_on_dtmf);
+       switch_core_event_hook_add_recv_dtmf(session, tone_on_dtmf);
+
+
+       if ((status = switch_core_media_bug_add(session, "fax_tone_detect", "",
+                                                                                       tone_detect_callback, cont, timeout, bflags, &cont->bug)) != SWITCH_STATUS_SUCCESS) {
+               cont->bug_running = 0;
+               return status;
+       }
+
+       switch_channel_set_private(channel, "_fax_tone_detect_", cont);
+
+       return SWITCH_STATUS_SUCCESS;
+}
+
+
 
 
 /* For Emacs: