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