From 7f3319dc1160c6533081a853a682480dc8fed02d Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 4 Oct 2010 18:23:43 -0500 Subject: [PATCH] add switch_ivr_dmachine async digit parser to core --- src/include/switch_ivr.h | 22 ++ src/include/switch_types.h | 16 ++ src/mod/applications/mod_fifo/mod_fifo.c | 8 +- src/switch_ivr.c | 18 +- src/switch_ivr_async.c | 277 ++++++++++++++++++++++- src/switch_ivr_play_say.c | 91 ++++++-- 6 files changed, 406 insertions(+), 26 deletions(-) diff --git a/src/include/switch_ivr.h b/src/include/switch_ivr.h index 4c562a51d7..5fee7baefa 100644 --- a/src/include/switch_ivr.h +++ b/src/include/switch_ivr.h @@ -842,6 +842,28 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_sound_test(switch_core_session_t *ses SWITCH_DECLARE(void) switch_process_import(switch_core_session_t *session, switch_channel_t *peer_channel, const char *varname); SWITCH_DECLARE(switch_bool_t) switch_ivr_uuid_exists(const char *uuid); + + +SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_create(switch_ivr_dmachine_t **dmachine_p, + switch_memory_pool_t *pool, + uint32_t digit_timeout, uint32_t input_timeout); + +SWITCH_DECLARE(void) switch_ivr_dmachine_destroy(switch_ivr_dmachine_t **dmachine); + +SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_bind(switch_ivr_dmachine_t *dmachine, + const char *digits, + int32_t key, + switch_ivr_dmachine_callback_t callback, + void *user_data); + +SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_feed(switch_ivr_dmachine_t *dmachine, const char *digits, switch_ivr_dmachine_match_t **match); +SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_clear(switch_ivr_dmachine_t *dmachine); +SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_ping(switch_ivr_dmachine_t *dmachine, switch_ivr_dmachine_match_t **match_p); +SWITCH_DECLARE(switch_ivr_dmachine_match_t *) switch_ivr_dmachine_get_match(switch_ivr_dmachine_t *dmachine); + + + + /** @} */ SWITCH_END_EXTERN_C diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 668fdc81c4..32fb141d42 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -833,6 +833,7 @@ typedef enum { SWITCH_STATUS_NOUNLOAD, SWITCH_STATUS_IGNORE, SWITCH_STATUS_TOO_SMALL, + SWITCH_STATUS_FOUND, SWITCH_STATUS_NOT_INITALIZED } switch_status_t; @@ -1684,12 +1685,27 @@ typedef switch_status_t (*switch_input_callback_function_t) (switch_core_session switch_input_type_t input_type, void *buf, unsigned int buflen); typedef switch_status_t (*switch_read_frame_callback_function_t) (switch_core_session_t *session, switch_frame_t *frame, void *user_data); typedef struct switch_say_interface switch_say_interface_t; + +struct switch_ivr_dmachine; +typedef struct switch_ivr_dmachine switch_ivr_dmachine_t; + +struct switch_ivr_dmachine_match { + switch_ivr_dmachine_t *dmachine; + const char *match_digits; + int32_t match_key; + void *user_data; +}; + +typedef struct switch_ivr_dmachine_match switch_ivr_dmachine_match_t; +typedef switch_status_t (*switch_ivr_dmachine_callback_t) (switch_ivr_dmachine_match_t *match); + typedef struct { switch_input_callback_function_t input_callback; void *buf; uint32_t buflen; switch_read_frame_callback_function_t read_frame_callback; void *user_data; + switch_ivr_dmachine_t *dmachine; } switch_input_args_t; typedef struct { diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index 563706c9f2..560b1cd6ad 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -507,19 +507,19 @@ static switch_status_t caller_read_frame_callback(switch_core_session_t *session args.buflen = sizeof(buf); if (switch_ivr_play_file(session, NULL, cd->list[cd->index], &args) != SWITCH_STATUS_SUCCESS) { - return SWITCH_STATUS_FALSE; + return SWITCH_STATUS_BREAK; } if (match_key(caller_exit_key, *buf)) { cd->abort = 1; - return SWITCH_STATUS_FALSE; + return SWITCH_STATUS_BREAK; } cd->next = switch_epoch_time_now(NULL) + cd->freq; cd->index++; } } else if (cd->orbit_timeout && switch_epoch_time_now(NULL) >= cd->orbit_timeout) { cd->do_orbit = 1; - return SWITCH_STATUS_FALSE; + return SWITCH_STATUS_BREAK; } return SWITCH_STATUS_SUCCESS; @@ -540,7 +540,7 @@ static switch_status_t consumer_read_frame_callback(switch_core_session_t *sessi } if (total) { - return SWITCH_STATUS_FALSE; + return SWITCH_STATUS_BREAK; } return SWITCH_STATUS_SUCCESS; diff --git a/src/switch_ivr.c b/src/switch_ivr.c index 7e7e8cda20..ef360d3148 100644 --- a/src/switch_ivr.c +++ b/src/switch_ivr.c @@ -224,7 +224,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_sleep(switch_core_session_t *session, switch_ivr_parse_all_events(session); - if (args && (args->input_callback || args->buf || args->buflen)) { + if (args && (args->input_callback || args->buf || args->buflen || args->dmachine)) { switch_dtmf_t dtmf; /* @@ -237,7 +237,13 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_sleep(switch_core_session_t *session, break; } switch_channel_dequeue_dtmf(channel, &dtmf); - if (args->input_callback) { + + if (args->dmachine) { + char ds[2] = {dtmf.digit, '\0'}; + if ((status = switch_ivr_dmachine_feed(args->dmachine, ds, NULL)) != SWITCH_STATUS_SUCCESS) { + break; + } + } else if (args->input_callback) { status = args->input_callback(session, (void *) &dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen); } else { switch_copy_string((char *) args->buf, (void *) &dtmf, args->buflen); @@ -947,8 +953,14 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_collect_digits_callback(switch_core_s break; } + if (args && args->dmachine) { + if ((status = switch_ivr_dmachine_ping(args->dmachine, NULL)) != SWITCH_STATUS_SUCCESS) { + break; + } + } + if (read_frame && args && (args->read_frame_callback)) { - if (args->read_frame_callback(session, read_frame, args->user_data) != SWITCH_STATUS_SUCCESS) { + if ((status = args->read_frame_callback(session, read_frame, args->user_data)) != SWITCH_STATUS_SUCCESS) { break; } } diff --git a/src/switch_ivr_async.c b/src/switch_ivr_async.c index 4fe5732f82..1fee5f99ab 100644 --- a/src/switch_ivr_async.c +++ b/src/switch_ivr_async.c @@ -35,6 +35,281 @@ #include #include +struct switch_ivr_dmachine_binding { + char *digits; + int32_t key; + switch_ivr_dmachine_callback_t callback; + switch_byte_t is_regex; + void *user_data; + struct switch_ivr_dmachine_binding *next; +}; +typedef struct switch_ivr_dmachine_binding switch_ivr_dmachine_binding_t; + +#define DM_MAX_DIGIT_LEN 512 + +struct switch_ivr_dmachine { + switch_memory_pool_t *pool; + switch_byte_t my_pool; + uint32_t digit_timeout_ms; + uint32_t input_timeout_ms; + switch_ivr_dmachine_binding_t *binding_list; + switch_ivr_dmachine_binding_t *tail; + switch_ivr_dmachine_binding_t *last_matching_binding; + switch_ivr_dmachine_match_t match; + char digits[DM_MAX_DIGIT_LEN]; + char last_matching_digits[DM_MAX_DIGIT_LEN]; + uint32_t cur_digit_len; + uint32_t max_digit_len; + switch_time_t last_digit_time; + switch_byte_t is_match; +}; + +SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_create(switch_ivr_dmachine_t **dmachine_p, + switch_memory_pool_t *pool, + uint32_t digit_timeout_ms, uint32_t input_timeout_ms) +{ + switch_byte_t my_pool = !!pool; + switch_ivr_dmachine_t *dmachine; + + if (digit_timeout_ms < 1 || input_timeout_ms < 1) return SWITCH_STATUS_FALSE; + + if (!pool) { + switch_core_new_memory_pool(&pool); + } + + dmachine = switch_core_alloc(pool, sizeof(*dmachine)); + dmachine->pool = pool; + dmachine->my_pool = my_pool; + dmachine->digit_timeout_ms = digit_timeout_ms; + dmachine->input_timeout_ms = input_timeout_ms; + dmachine->match.dmachine = dmachine; + *dmachine_p = dmachine; + + return SWITCH_STATUS_SUCCESS; +} + + +SWITCH_DECLARE(void) switch_ivr_dmachine_destroy(switch_ivr_dmachine_t **dmachine) +{ + switch_memory_pool_t *pool; + + if (!(dmachine && *dmachine)) return; + + pool = (*dmachine)->pool; + + if ((*dmachine)->my_pool) { + switch_core_destroy_memory_pool(&pool); + } +} + +SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_bind(switch_ivr_dmachine_t *dmachine, + const char *digits, + int32_t key, + switch_ivr_dmachine_callback_t callback, + void *user_data) +{ + switch_ivr_dmachine_binding_t *binding; + switch_size_t len; + + if (strlen(digits) > DM_MAX_DIGIT_LEN -1) { + return SWITCH_STATUS_FALSE; + } + + binding = switch_core_alloc(dmachine->pool, sizeof(*binding)); + if (*digits == '~') { + binding->is_regex = 1; + digits++; + } + binding->key = key; + binding->digits = switch_core_strdup(dmachine->pool, digits); + binding->callback = callback; + binding->user_data = user_data; + + if (dmachine->tail) { + dmachine->tail->next = binding; + } else { + dmachine->binding_list = binding; + } + + dmachine->tail = binding; + + len = strlen(digits); + + if (binding->is_regex && dmachine->max_digit_len != DM_MAX_DIGIT_LEN -1) { + dmachine->max_digit_len = DM_MAX_DIGIT_LEN -1; + } else if (len > dmachine->max_digit_len) { + dmachine->max_digit_len = (uint32_t) len; + } + + if (binding->is_regex) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "binding regex: %s key: %.4d callback: %p data: %p\n", + digits, key, (void *)(intptr_t) callback, user_data); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "binding digits: %4s key: %.4d callback: %p data: %p\n", + digits, key, (void *)(intptr_t) callback, user_data); + } + + return SWITCH_STATUS_SUCCESS; +} + +typedef enum { + DM_MATCH_NONE, + DM_MATCH_EXACT, + DM_MATCH_PARTIAL, + DM_MATCH_BOTH +} dm_match_t; + + +static dm_match_t switch_ivr_dmachine_check_match(switch_ivr_dmachine_t *dmachine, switch_bool_t is_timeout) +{ + dm_match_t best = DM_MATCH_NONE; + switch_ivr_dmachine_binding_t *bp, *exact_bp = NULL; + int exact_count = 0, partial_count = 0, both_count = 0; + + + if (!dmachine->cur_digit_len) goto end; + + for(bp = dmachine->binding_list; bp; bp = bp->next) { + + if (bp->is_regex) { + switch_status_t r_status = switch_regex_match(dmachine->digits, bp->digits); + + if (r_status == SWITCH_STATUS_SUCCESS) { + if (is_timeout) { + best = DM_MATCH_EXACT; + exact_count++; + exact_bp = bp; + break; + } + + best = DM_MATCH_PARTIAL; + partial_count++; + continue; + } + } else { + if (!exact_bp && !strcmp(bp->digits, dmachine->digits)) { + exact_bp = bp; + best = DM_MATCH_EXACT; + exact_count++; + continue; + } + + if (!strncmp(dmachine->digits, bp->digits, strlen(dmachine->digits))) { + if (best == DM_MATCH_EXACT) { + if (is_timeout) { + best = DM_MATCH_EXACT; + exact_count++; + exact_bp = bp; + } else { + best = DM_MATCH_BOTH; + both_count++; + } + } else { + best = DM_MATCH_PARTIAL; + partial_count++; + } + break; + } + } + } + + end: + + if (!both_count && exact_bp) { + dmachine->last_matching_binding = exact_bp; + switch_set_string(dmachine->last_matching_digits, dmachine->digits); + best = DM_MATCH_EXACT; + } + + return best; + +} + +static switch_bool_t switch_ivr_dmachine_check_timeout(switch_ivr_dmachine_t *dmachine) +{ + switch_time_t now = switch_time_now(); + uint32_t timeout = dmachine->cur_digit_len ? dmachine->digit_timeout_ms : dmachine->input_timeout_ms; + + if ((uint32_t)((now - dmachine->last_digit_time) / 1000) > timeout) { + return SWITCH_TRUE; + } + + return SWITCH_FALSE; +} + +SWITCH_DECLARE(switch_ivr_dmachine_match_t *) switch_ivr_dmachine_get_match(switch_ivr_dmachine_t *dmachine) +{ + if (dmachine->is_match) { + dmachine->is_match = 0; + return &dmachine->match; + } + + return NULL; +} + +SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_ping(switch_ivr_dmachine_t *dmachine, switch_ivr_dmachine_match_t **match_p) +{ + switch_bool_t is_timeout = switch_ivr_dmachine_check_timeout(dmachine); + dm_match_t is_match = switch_ivr_dmachine_check_match(dmachine, is_timeout); + switch_status_t r; + + if (!dmachine->last_digit_time) { + r = SWITCH_STATUS_SUCCESS; + } else if (dmachine->cur_digit_len > dmachine->max_digit_len) { + r = SWITCH_STATUS_FALSE; + } else if (is_match == DM_MATCH_EXACT || (is_match == DM_MATCH_BOTH && is_timeout)) { + r = SWITCH_STATUS_FOUND; + + dmachine->match.match_digits = dmachine->last_matching_digits; + dmachine->match.match_key = dmachine->last_matching_binding->key; + dmachine->match.user_data = dmachine->last_matching_binding->user_data; + + if (dmachine->last_matching_binding->callback) { + dmachine->last_matching_binding->callback(&dmachine->match); + } + + if (match_p) { + *match_p = &dmachine->match; + } + + dmachine->is_match = 1; + } else if (is_timeout) { + r = SWITCH_STATUS_TIMEOUT; + } else if (dmachine->cur_digit_len == dmachine->max_digit_len) { + r = SWITCH_STATUS_NOTFOUND; + } else { + r = SWITCH_STATUS_SUCCESS; + } + + if (r != SWITCH_STATUS_SUCCESS) { + switch_ivr_dmachine_clear(dmachine); + } + + return r; +} + +SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_feed(switch_ivr_dmachine_t *dmachine, const char *digits, switch_ivr_dmachine_match_t **match) +{ + if (strlen(digits) + strlen(dmachine->digits) > dmachine->max_digit_len) { + return SWITCH_STATUS_FALSE; + } + + strncat(dmachine->digits, digits, dmachine->max_digit_len); + dmachine->cur_digit_len = strlen(dmachine->digits); + dmachine->last_digit_time = switch_time_now(); + + return switch_ivr_dmachine_ping(dmachine, match); +} + +SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_clear(switch_ivr_dmachine_t *dmachine) +{ + memset(dmachine->digits, 0, sizeof(dmachine->digits)); + dmachine->cur_digit_len = 0; + dmachine->last_digit_time = 0; + return SWITCH_STATUS_SUCCESS; +} + + #ifdef SWITCH_VIDEO_IN_THREADS struct echo_helper { switch_core_session_t *session; @@ -2528,7 +2803,7 @@ static void *SWITCH_THREAD_FUNC speech_thread(switch_thread_t *thread, void *obj if (status == SWITCH_STATUS_SUCCESS && switch_true(switch_channel_get_variable(channel, "asr_intercept_dtmf"))) { const char *p; - + if ((p = switch_stristr("", xmlstr))) { p += 7; } diff --git a/src/switch_ivr_play_say.c b/src/switch_ivr_play_say.c index d75af10a5e..c5b7a61000 100644 --- a/src/switch_ivr_play_say.c +++ b/src/switch_ivr_play_say.c @@ -493,7 +493,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se fh->pre_buffer_datalen = SWITCH_DEFAULT_FILE_BUFFER_LEN; } - if ((p = switch_channel_get_variable(channel, "RECORD_APPEND")) && switch_true(p)) { + if (switch_test_flag(fh, SWITCH_FILE_WRITE_APPEND) || ((p = switch_channel_get_variable(channel, "RECORD_APPEND")) && switch_true(p))) { file_flags |= SWITCH_FILE_WRITE_APPEND; } @@ -613,18 +613,24 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se break; } - if (args && (args->input_callback || args->buf || args->buflen)) { + if (args && (args->input_callback || args->buf || args->buflen || args->dmachine)) { /* dtmf handler function you can hook up to be executed when a digit is dialed during playback if you return anything but SWITCH_STATUS_SUCCESS the playback will stop. */ if (switch_channel_has_dtmf(channel)) { - if (!args->input_callback && !args->buf) { + if (!args->input_callback && !args->buf && !args->dmachine) { status = SWITCH_STATUS_BREAK; break; } switch_channel_dequeue_dtmf(channel, &dtmf); - if (args->input_callback) { + + if (args->dmachine) { + char ds[2] = {dtmf.digit, '\0'}; + if ((status = switch_ivr_dmachine_feed(args->dmachine, ds, NULL)) != SWITCH_STATUS_SUCCESS) { + break; + } + } else if (args->input_callback) { status = args->input_callback(session, (void *) &dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen); } else { *((char *) args->buf) = dtmf.digit; @@ -651,8 +657,14 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se break; } + if (args && args->dmachine) { + if ((status = switch_ivr_dmachine_ping(args->dmachine, NULL)) != SWITCH_STATUS_SUCCESS) { + break; + } + } + if (args && (args->read_frame_callback)) { - if (args->read_frame_callback(session, read_frame, args->user_data) != SWITCH_STATUS_SUCCESS) { + if ((status = args->read_frame_callback(session, read_frame, args->user_data)) != SWITCH_STATUS_SUCCESS) { break; } } @@ -810,16 +822,21 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_gentones(switch_core_session_t *sessi break; } + if (args && args->dmachine) { + if ((status = switch_ivr_dmachine_ping(args->dmachine, NULL)) != SWITCH_STATUS_SUCCESS) { + break; + } + } if (args && (args->read_frame_callback)) { - if (args->read_frame_callback(session, read_frame, args->user_data) != SWITCH_STATUS_SUCCESS) { + if ((status = args->read_frame_callback(session, read_frame, args->user_data)) != SWITCH_STATUS_SUCCESS) { break; } } switch_ivr_parse_all_events(session); - if (args && (args->input_callback || args->buf || args->buflen)) { + if (args && (args->input_callback || args->buf || args->buflen || args->dmachine)) { /* dtmf handler function you can hook up to be executed when a digit is dialed during gentones if you return anything but SWITCH_STATUS_SUCCESS the playback will stop. @@ -831,7 +848,13 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_gentones(switch_core_session_t *sessi break; } switch_channel_dequeue_dtmf(channel, &dtmf); - if (args->input_callback) { + + if (args->dmachine) { + char ds[2] = {dtmf.digit, '\0'}; + if ((status = switch_ivr_dmachine_feed(args->dmachine, ds, NULL)) != SWITCH_STATUS_SUCCESS) { + break; + } + } else if (args->input_callback) { status = args->input_callback(session, (void *) &dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen); } else { *((char *) args->buf) = dtmf.digit; @@ -841,7 +864,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_gentones(switch_core_session_t *sessi if (args->input_callback) { switch_event_t *event; - + if (switch_core_session_dequeue_event(session, &event, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) { status = args->input_callback(session, event, SWITCH_INPUT_TYPE_EVENT, args->buf, args->buflen); switch_event_destroy(&event); @@ -1224,7 +1247,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess switch_ivr_parse_all_events(session); - if (args && (args->input_callback || args->buf || args->buflen)) { + if (args && (args->input_callback || args->buf || args->buflen || args->dmachine)) { /* dtmf handler function you can hook up to be executed when a digit is dialed during playback if you return anything but SWITCH_STATUS_SUCCESS the playback will stop. @@ -1236,7 +1259,13 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess break; } switch_channel_dequeue_dtmf(channel, &dtmf); - if (args->input_callback) { + + if (args->dmachine) { + char ds[2] = {dtmf.digit, '\0'}; + if ((status = switch_ivr_dmachine_feed(args->dmachine, ds, NULL)) != SWITCH_STATUS_SUCCESS) { + break; + } + } else if (args->input_callback) { status = args->input_callback(session, (void *) &dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen); } else { *((char *) args->buf) = dtmf.digit; @@ -1405,10 +1434,16 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess break; } + if (args && args->dmachine) { + if ((status = switch_ivr_dmachine_ping(args->dmachine, NULL)) != SWITCH_STATUS_SUCCESS) { + break; + } + } + if (args && (args->read_frame_callback)) { int ok = 1; switch_set_flag(fh, SWITCH_FILE_CALLBACK); - if (args->read_frame_callback(session, read_frame, args->user_data) != SWITCH_STATUS_SUCCESS) { + if ((status = args->read_frame_callback(session, read_frame, args->user_data)) != SWITCH_STATUS_SUCCESS) { ok = 0; } switch_clear_flag(fh, SWITCH_FILE_CALLBACK); @@ -1919,7 +1954,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session switch_event_destroy(&event); } - if (args && (args->input_callback || args->buf || args->buflen)) { + if (args && (args->input_callback || args->buf || args->buflen || args->dmachine)) { /* dtmf handler function you can hook up to be executed when a digit is dialed during playback * if you return anything but SWITCH_STATUS_SUCCESS the playback will stop. */ @@ -1933,7 +1968,13 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session status = SWITCH_STATUS_BREAK; } else { switch_channel_dequeue_dtmf(channel, &dtmf); - if (args->input_callback) { + + if (args->dmachine) { + char ds[2] = {dtmf.digit, '\0'}; + if ((status = switch_ivr_dmachine_feed(args->dmachine, ds, NULL)) != SWITCH_STATUS_SUCCESS) { + break; + } + } else if (args->input_callback) { status = args->input_callback(session, (void *) &dtmf, SWITCH_INPUT_TYPE_DTMF, args->buf, args->buflen); } else { *((char *) args->buf) = dtmf.digit; @@ -1972,9 +2013,15 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session break; } + if (args && args->dmachine) { + if ((status = switch_ivr_dmachine_ping(args->dmachine, NULL)) != SWITCH_STATUS_SUCCESS) { + goto done; + } + } + if (args && (args->read_frame_callback)) { - if (args->read_frame_callback(session, read_frame, args->user_data) != SWITCH_STATUS_SUCCESS) { - break; + if ((status = args->read_frame_callback(session, read_frame, args->user_data)) != SWITCH_STATUS_SUCCESS) { + goto done; } } } @@ -2038,15 +2085,23 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session break; } + if (args && args->dmachine) { + if ((status = switch_ivr_dmachine_ping(args->dmachine, NULL)) != SWITCH_STATUS_SUCCESS) { + goto done; + } + } + if (args && (args->read_frame_callback)) { - if (args->read_frame_callback(session, read_frame, args->user_data) != SWITCH_STATUS_SUCCESS) { - break; + if ((status = args->read_frame_callback(session, read_frame, args->user_data)) != SWITCH_STATUS_SUCCESS) { + goto done; } } } } + done: + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "done speaking text\n"); flags = 0; switch_core_speech_flush_tts(sh);