From 34338e5a564c4e40f3740f78e49cf0268d223f27 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 15 Nov 2011 11:28:05 -0600 Subject: [PATCH] FS-3692 --resolve --- src/include/switch_ivr.h | 15 ++++ .../applications/mod_dptools/mod_dptools.c | 47 ++++++++++ src/switch_ivr_async.c | 88 +++++++++++++++++++ 3 files changed, 150 insertions(+) diff --git a/src/include/switch_ivr.h b/src/include/switch_ivr.h index 03bbc2d753..6f883a933c 100644 --- a/src/include/switch_ivr.h +++ b/src/include/switch_ivr.h @@ -155,6 +155,21 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_collect_digits_count(switch_core_sess const char *terminators, char *terminator, uint32_t first_timeout, uint32_t digit_timeout, uint32_t abs_timeout); +/*! + \brief play a file to the session while doing speech recognition. + \param session the session to play and detect on + \param file the path to the file + \param mod_name the module name of the ASR library + \param grammar the grammar text, URI, or local file name + \param result of speech recognition, allocated from the session pool + \return SWITCH_STATUS_SUCCESS if all is well +*/ +SWITCH_DECLARE(switch_status_t) switch_ivr_play_and_detect_speech(switch_core_session_t *session, + const char *file, + const char *mod_name, + const char *grammar, + char **result); + /*! \brief Engage background Speech detection on a session \param session the session to attach diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c index 1857d1997d..09299d8f2e 100755 --- a/src/mod/applications/mod_dptools/mod_dptools.c +++ b/src/mod/applications/mod_dptools/mod_dptools.c @@ -30,6 +30,7 @@ * Bret McDanel * Luke Dashjr (OpenMethods, LLC) * Cesar Cepeda + * Chris Rienzo * * mod_dptools.c -- Raw Audio File Streaming Application Module * @@ -437,6 +438,51 @@ SWITCH_STANDARD_APP(detect_speech_function) } } +#define PLAY_AND_DETECT_SPEECH_SYNTAX " detect: {param1=val1,param2=val2}" +SWITCH_STANDARD_APP(play_and_detect_speech_function) +{ + switch_channel_t *channel = switch_core_session_get_channel(session); + char *argv[2]; + char *lbuf = NULL; + const char *response = "DONE"; + char *detect = NULL; + + switch_channel_set_variable(channel, "detect_speech_result", ""); + + if (zstr(data) || !(lbuf = switch_core_session_strdup(session, data)) || !(detect = strstr(lbuf, "detect:"))) { + /* bad input */ + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Usage: %s\n", PLAY_AND_DETECT_SPEECH_SYNTAX); + response = "USAGE ERROR"; + goto done; + } + + /* split input at "detect:" */ + detect[0] = '\0'; + detect += 7; + if (zstr(detect)) { + /* bad input */ + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Usage: %s\n", PLAY_AND_DETECT_SPEECH_SYNTAX); + response = "USAGE ERROR"; + goto done; + } + + /* need to have at 2 parameters for detect */ + if (switch_separate_string(detect, ' ', argv, (sizeof(argv) / sizeof(argv[0]))) == 2) { + char *file = lbuf; + char *engine = argv[0]; + char *grammar = argv[1]; + char *result = NULL; + switch_ivr_play_and_detect_speech(session, file, engine, grammar, &result); + switch_channel_set_variable(channel, "detect_speech_result", result); + } else { + /* bad input */ + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Usage: %s\n", PLAY_AND_DETECT_SPEECH_SYNTAX); + response = "USAGE ERROR"; + } + +done: + switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, response); +} #define SCHED_HEARTBEAT_SYNTAX "[0|]" SWITCH_STANDARD_APP(sched_heartbeat_function) @@ -4000,6 +4046,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load) SWITCH_ADD_APP(app_interface, "remove_bugs", "Remove media bugs", "Remove all media bugs from a channel.", remove_bugs_function, "", SAF_NONE); SWITCH_ADD_APP(app_interface, "break", "Break", "Set the break flag.", break_function, "", SAF_SUPPORT_NOMEDIA); SWITCH_ADD_APP(app_interface, "detect_speech", "Detect speech", "Detect speech on a channel.", detect_speech_function, DETECT_SPEECH_SYNTAX, SAF_NONE); + SWITCH_ADD_APP(app_interface, "play_and_detect_speech", "Play and do speech recognition", "Play and do speech recognition", play_and_detect_speech_function, PLAY_AND_DETECT_SPEECH_SYNTAX, SAF_NONE); SWITCH_ADD_APP(app_interface, "ivr", "Run an ivr menu", "Run an ivr menu.", ivr_application_function, "", SAF_NONE); SWITCH_ADD_APP(app_interface, "redirect", "Send session redirect", "Send a redirect message to a session.", redirect_function, "", SAF_SUPPORT_NOMEDIA); diff --git a/src/switch_ivr_async.c b/src/switch_ivr_async.c index 960a8d51cd..3812ce38a7 100644 --- a/src/switch_ivr_async.c +++ b/src/switch_ivr_async.c @@ -27,6 +27,7 @@ * Michael Jerris * Bret McDanel * Luke Dashjr (OpenMethods, LLC) + * Chris Rienzo * * switch_ivr_async.c -- IVR Library (async operations) * @@ -3143,7 +3144,94 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_bind_dtmf_meta_session(switch_core_se return SWITCH_STATUS_SUCCESS; } +typedef struct { + int done; + char *result; +} play_and_detect_speech_state_t; +static switch_status_t play_and_detect_input_callback(switch_core_session_t *session, void *input, switch_input_type_t input_type, void *data, unsigned int len) +{ + play_and_detect_speech_state_t *state = (play_and_detect_speech_state_t *)data; + switch_event_t *event; + switch_channel_t *channel = switch_core_session_get_channel(session); + if (input_type == SWITCH_INPUT_TYPE_EVENT) { + event = (switch_event_t *)input; + if (event->event_id == SWITCH_EVENT_DETECTED_SPEECH && !state->done) { + const char *speech_type = switch_event_get_header(event, "Speech-Type"); + if (!zstr(speech_type)) { + if (!strcasecmp(speech_type, "detected-speech")) { + const char *result; + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "(%s) DETECTED SPEECH\n", switch_channel_get_name(channel)); + result = switch_event_get_body(event); + if (!zstr(result)) { + state->result = switch_core_session_strdup(session, result); + } else { + state->result = ""; + } + state->done = 1; + return SWITCH_STATUS_BREAK; + } else if (!strcasecmp(speech_type, "begin-speaking")) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "(%s) START OF SPEECH\n", switch_channel_get_name(channel)); + return SWITCH_STATUS_BREAK; + } + } + } + } + return SWITCH_STATUS_SUCCESS; +} + +SWITCH_DECLARE(switch_status_t) switch_ivr_play_and_detect_speech(switch_core_session_t *session, const char *file, const char *mod_name, const char *grammar, char **result) +{ + switch_status_t status; + int recognizing = 0; + switch_input_args_t args = { 0 }; + play_and_detect_speech_state_t state = { 0, "" }; + switch_channel_t *channel = switch_core_session_get_channel(session); + + if (result == NULL) { + goto done; + } + + /* start speech detection */ + if (switch_ivr_detect_speech(session, mod_name, grammar, grammar, NULL, NULL) != SWITCH_STATUS_SUCCESS) { + goto done; + } + recognizing = 1; + + /* play the prompt, looking for detection result */ + args.input_callback = play_and_detect_input_callback; + args.buf = &state; + args.buflen = sizeof(state); + status = switch_ivr_play_file(session, NULL, file, &args); + if (status != SWITCH_STATUS_BREAK && status != SWITCH_STATUS_SUCCESS) { + goto done; + } + + /* wait for result if not done */ + if (!state.done) { + switch_ivr_detect_speech_start_input_timers(session); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "(%s) WAITING FOR RESULT\n", switch_channel_get_name(channel)); + while (!state.done && switch_channel_ready(channel)) { + status = switch_ivr_sleep(session, 5000, SWITCH_FALSE, &args); + if (status != SWITCH_STATUS_BREAK && status != SWITCH_STATUS_SUCCESS) { + goto done; + } + } + } + recognizing = !state.done; + +done: + if (recognizing) { + switch_ivr_pause_detect_speech(session); + } + + *result = state.result; + + if (!state.done) { + return SWITCH_STATUS_FALSE; + } + return SWITCH_STATUS_SUCCESS; +} struct speech_thread_handle { switch_core_session_t *session;