FS-3252 additional fix to this bug and add better fax detect code to mod_spandsp
This commit is contained in:
parent
9227b53872
commit
7fe313cf3d
|
@ -70,11 +70,46 @@ SWITCH_STANDARD_APP(stop_dtmf_session_function)
|
||||||
spandsp_stop_inband_dtmf_session(session);
|
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)
|
static void event_handler(switch_event_t *event)
|
||||||
{
|
{
|
||||||
mod_spandsp_fax_event_handler(event);
|
mod_spandsp_fax_event_handler(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SWITCH_STANDARD_APP(t38_gateway_function)
|
SWITCH_STANDARD_APP(t38_gateway_function)
|
||||||
{
|
{
|
||||||
switch_channel_t *channel = switch_core_session_get_channel(session);
|
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||||
|
@ -83,10 +118,19 @@ SWITCH_STANDARD_APP(t38_gateway_function)
|
||||||
int argc = 0;
|
int argc = 0;
|
||||||
char *argv[2] = { 0 };
|
char *argv[2] = { 0 };
|
||||||
char *dupdata;
|
char *dupdata;
|
||||||
const char *direction = argv[0], *flags = argv[1];
|
const char *direction = NULL, *flags = NULL;
|
||||||
|
|
||||||
dupdata = switch_core_session_strdup(session, data);
|
if (!zstr(data) && (dupdata = switch_core_session_strdup(session, data))) {
|
||||||
argc = switch_split(dupdata, ' ', argv);
|
if ((argc = switch_split(dupdata, ' ', argv))) {
|
||||||
|
if (argc > 0) {
|
||||||
|
direction = argv[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc > 1) {
|
||||||
|
flags = argv[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (zstr(direction) || strcasecmp(direction, "self")) {
|
if (zstr(direction) || strcasecmp(direction, "self")) {
|
||||||
direction = "peer";
|
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_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_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_fax_load(pool);
|
||||||
mod_spandsp_codecs_load(module_interface, pool);
|
mod_spandsp_codecs_load(module_interface, pool);
|
||||||
|
|
||||||
|
|
|
@ -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_start(switch_core_session_t *session, const char *name);
|
||||||
switch_status_t callprogress_detector_stop(switch_core_session_t *session);
|
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);
|
||||||
|
|
|
@ -1806,6 +1806,250 @@ switch_bool_t t38_gateway_start(switch_core_session_t *session, const char *app,
|
||||||
return SWITCH_FALSE;
|
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:
|
/* For Emacs:
|
||||||
|
|
Loading…
Reference in New Issue