From ab568f3589e28c7287561c58fc083965d73d6968 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 8 Jun 2009 21:52:50 +0000 Subject: [PATCH] patch git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@13694 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- libs/speex/config.h.in | 6 +- patches/asr.diff | 562 ++++++++++++++++++ src/include/switch_core.h | 53 +- src/include/switch_ivr.h | 16 +- src/include/switch_module_interfaces.h | 11 +- src/mod/applications/mod_limit/Makefile | 1 + src/mod/applications/mod_voicemail/Makefile | 1 + .../mod_pocketsphinx/mod_pocketsphinx.c | 8 +- src/switch_core_asr.c | 105 +++- src/switch_core_speech.c | 60 +- src/switch_ivr_async.c | 14 +- 11 files changed, 791 insertions(+), 46 deletions(-) create mode 100644 patches/asr.diff diff --git a/libs/speex/config.h.in b/libs/speex/config.h.in index 8aec7e0ace..c22661a5c8 100644 --- a/libs/speex/config.h.in +++ b/libs/speex/config.h.in @@ -96,13 +96,13 @@ /* Define to the version of this package. */ #undef PACKAGE_VERSION -/* The size of a `int', as computed by sizeof. */ +/* The size of `int', as computed by sizeof. */ #undef SIZEOF_INT -/* The size of a `long', as computed by sizeof. */ +/* The size of `long', as computed by sizeof. */ #undef SIZEOF_LONG -/* The size of a `short', as computed by sizeof. */ +/* The size of `short', as computed by sizeof. */ #undef SIZEOF_SHORT /* Version extra */ diff --git a/patches/asr.diff b/patches/asr.diff new file mode 100644 index 0000000000..cf5dce5a4a --- /dev/null +++ b/patches/asr.diff @@ -0,0 +1,562 @@ +Index: src/switch_ivr_async.c +=================================================================== +--- src/switch_ivr_async.c (revision 13692) ++++ src/switch_ivr_async.c (working copy) +@@ -2027,14 +2027,14 @@ + return SWITCH_STATUS_FALSE; + } + +-SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech_load_grammar(switch_core_session_t *session, char *grammar, char *path) ++SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech_load_grammar(switch_core_session_t *session, char *grammar, char *name) + { + switch_channel_t *channel = switch_core_session_get_channel(session); + switch_asr_flag_t flags = SWITCH_ASR_FLAG_NONE; + struct speech_thread_handle *sth = switch_channel_get_private(channel, SWITCH_SPEECH_KEY); + + if (sth) { +- if (switch_core_asr_load_grammar(sth->ah, grammar, path) != SWITCH_STATUS_SUCCESS) { ++ if (switch_core_asr_load_grammar(sth->ah, grammar, name) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Error loading Grammar\n"); + switch_core_asr_close(sth->ah, &flags); + switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); +@@ -2045,14 +2045,14 @@ + return SWITCH_STATUS_FALSE; + } + +-SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech_unload_grammar(switch_core_session_t *session, const char *grammar) ++SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech_unload_grammar(switch_core_session_t *session, const char *name) + { + switch_channel_t *channel = switch_core_session_get_channel(session); + switch_asr_flag_t flags = SWITCH_ASR_FLAG_NONE; + struct speech_thread_handle *sth = switch_channel_get_private(channel, SWITCH_SPEECH_KEY); + + if (sth) { +- if (switch_core_asr_unload_grammar(sth->ah, grammar) != SWITCH_STATUS_SUCCESS) { ++ if (switch_core_asr_unload_grammar(sth->ah, name) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Error unloading Grammar\n"); + switch_core_asr_close(sth->ah, &flags); + switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); +@@ -2065,7 +2065,7 @@ + + SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech(switch_core_session_t *session, + const char *mod_name, +- const char *grammar, const char *path, const char *dest, switch_asr_handle_t *ah) ++ const char *grammar, const char *name, const char *dest, switch_asr_handle_t *ah) + { + switch_channel_t *channel = switch_core_session_get_channel(session); + switch_status_t status; +@@ -2085,7 +2085,7 @@ + } + + if (sth) { +- if (switch_core_asr_load_grammar(sth->ah, grammar, path) != SWITCH_STATUS_SUCCESS) { ++ if (switch_core_asr_load_grammar(sth->ah, grammar, name) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Error loading Grammar\n"); + switch_core_asr_close(sth->ah, &flags); + return SWITCH_STATUS_FALSE; +@@ -2100,7 +2100,7 @@ + read_impl.actual_samples_per_second, dest, &flags, + switch_core_session_get_pool(session)) == SWITCH_STATUS_SUCCESS) { + +- if (switch_core_asr_load_grammar(ah, grammar, path) != SWITCH_STATUS_SUCCESS) { ++ if (switch_core_asr_load_grammar(ah, grammar, name) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Error loading Grammar\n"); + switch_core_asr_close(ah, &flags); + switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); +Index: src/switch_core_asr.c +=================================================================== +--- src/switch_core_asr.c (revision 13692) ++++ src/switch_core_asr.c (working copy) +@@ -26,6 +26,7 @@ + * Anthony Minessale II + * Michael Jerris + * Paul D. Tinsley ++ * Christopher M. Rienzo + * + * + * switch_core_asr.c -- Main Core Library (Speech Detection Interface) +@@ -79,30 +80,74 @@ + return ah->asr_interface->asr_open(ah, codec, rate, dest, flags); + } + +-SWITCH_DECLARE(switch_status_t) switch_core_asr_load_grammar(switch_asr_handle_t *ah, const char *grammar, const char *path) ++SWITCH_DECLARE(switch_status_t) switch_core_asr_load_grammar(switch_asr_handle_t *ah, const char *grammar, const char *name) + { +- char *epath = NULL; +- switch_status_t status; ++ switch_status_t status = SWITCH_STATUS_SUCCESS; ++ char *param_string = NULL; ++ char *data = NULL; ++ char *lgrammar = NULL; + + switch_assert(ah != NULL); + +- if (!switch_is_file_path(path)) { +- epath = switch_mprintf("%s%s%s", SWITCH_GLOBAL_dirs.grammar_dir, SWITCH_PATH_SEPARATOR, path); +- path = epath; ++ if (switch_strlen_zero(grammar)) { ++ status = SWITCH_STATUS_FALSE; ++ goto done; + } + +- status = ah->asr_interface->asr_load_grammar(ah, grammar, path); +- switch_safe_free(epath); ++ /* Set ASR parameters from params in the grammar string ++ * Params are defined as follows {name1=val1,name2=val2,name3=val3}grammar text ++ */ ++ lgrammar = strdup(grammar); ++ data = lgrammar; + ++ /* strip leading spaces */ ++ while (data && *data == ' ') { ++ data++; ++ } ++ if (switch_strlen_zero(data)) { ++ status = SWITCH_STATUS_FALSE; ++ goto done; ++ } ++ ++ /* extract params */ ++ if (*data == '{') { ++ param_string = data + 1; ++ data = switch_find_end_paren(data, '{', '}'); ++ if (switch_strlen_zero(data)) { ++ status = SWITCH_STATUS_FALSE; ++ goto done; ++ } else { ++ *data = '\0'; ++ data++; ++ } ++ } ++ ++ /* set ASR params */ ++ if (!switch_strlen_zero(param_string)) { ++ char *param[256] = { 0 }; ++ switch_separate_string(param_string, ',', param, (sizeof(param) / sizeof(param[0]))); ++ for (int i = 0; param[i]; ++i) { ++ char *param_pair[2] = { 0 }; ++ if(switch_separate_string(param[i], '=', param_pair, (sizeof(param_pair) / sizeof(param_pair[0]))) == 2) { ++ switch_core_asr_text_param(ah, param_pair[0], param_pair[1]); ++ } ++ } ++ } ++ ++ status = ah->asr_interface->asr_load_grammar(ah, data, name); ++ ++ done: ++ ++ switch_safe_free(lgrammar); + return status; + } + +-SWITCH_DECLARE(switch_status_t) switch_core_asr_unload_grammar(switch_asr_handle_t *ah, const char *grammar) ++SWITCH_DECLARE(switch_status_t) switch_core_asr_unload_grammar(switch_asr_handle_t *ah, const char *name) + { + switch_status_t status; + + switch_assert(ah != NULL); +- status = ah->asr_interface->asr_unload_grammar(ah, grammar); ++ status = ah->asr_interface->asr_unload_grammar(ah, name); + + return status; + } +@@ -158,6 +203,46 @@ + return ah->asr_interface->asr_get_results(ah, xmlstr, flags); + } + ++SWITCH_DECLARE(switch_status_t) switch_core_asr_start_input_timers(switch_asr_handle_t *ah) ++{ ++ switch_status_t status = SWITCH_STATUS_SUCCESS; ++ ++ switch_assert(ah != NULL); ++ ++ if (ah->asr_interface->asr_start_input_timers) { ++ status = ah->asr_interface->asr_start_input_timers(ah); ++ } ++ ++ return status; ++} ++ ++SWITCH_DECLARE(void) switch_core_asr_text_param(switch_asr_handle_t *ah, char *param, const char *val) ++{ ++ switch_assert(ah != NULL); ++ ++ if (ah->asr_interface->asr_text_param) { ++ ah->asr_interface->asr_text_param(ah, param, val); ++ } ++} ++ ++SWITCH_DECLARE(void) switch_core_asr_numeric_param(switch_asr_handle_t *ah, char *param, int val) ++{ ++ switch_assert(ah != NULL); ++ ++ if (ah->asr_interface->asr_numeric_param) { ++ ah->asr_interface->asr_numeric_param(ah, param, val); ++ } ++} ++ ++SWITCH_DECLARE(void) switch_core_asr_float_param(switch_asr_handle_t *ah, char *param, double val) ++{ ++ switch_assert(ah != NULL); ++ ++ if (ah->asr_interface->asr_float_param) { ++ ah->asr_interface->asr_float_param(ah, param, val); ++ } ++} ++ + /* For Emacs: + * Local Variables: + * mode:c +Index: src/mod/asr_tts/mod_pocketsphinx/mod_pocketsphinx.c +=================================================================== +--- src/mod/asr_tts/mod_pocketsphinx/mod_pocketsphinx.c (revision 13692) ++++ src/mod/asr_tts/mod_pocketsphinx/mod_pocketsphinx.c (working copy) +@@ -111,7 +111,7 @@ + } + + /*! function to load a grammar to the asr interface */ +-static switch_status_t pocketsphinx_asr_load_grammar(switch_asr_handle_t *ah, const char *grammar, const char *path) ++static switch_status_t pocketsphinx_asr_load_grammar(switch_asr_handle_t *ah, const char *grammar, const char *name) + { + char *jsgf, *dic, *model, *rate = NULL; + pocketsphinx_t *ps = (pocketsphinx_t *) ah->private_info; +@@ -199,7 +199,7 @@ + } + + /*! function to unload a grammar to the asr interface */ +-static switch_status_t pocketsphinx_asr_unload_grammar(switch_asr_handle_t *ah, const char *grammar) ++static switch_status_t pocketsphinx_asr_unload_grammar(switch_asr_handle_t *ah, const char *name) + { + return SWITCH_STATUS_SUCCESS; + } +@@ -506,6 +506,10 @@ + asr_interface->asr_pause = pocketsphinx_asr_pause; + asr_interface->asr_check_results = pocketsphinx_asr_check_results; + asr_interface->asr_get_results = pocketsphinx_asr_get_results; ++ asr_interface->asr_start_input_timers = NULL; ++ asr_interface->asr_text_param = NULL; ++ asr_interface->asr_numeric_param = NULL; ++ asr_interface->asr_float_param = NULL; + + err_set_logfp(NULL); + +Index: src/mod/applications/mod_voicemail/Makefile +=================================================================== +--- src/mod/applications/mod_voicemail/Makefile (revision 13692) ++++ src/mod/applications/mod_voicemail/Makefile (working copy) +@@ -1,3 +1,4 @@ + BASE=../../../.. + include $(BASE)/build/modmake.rules + LOCAL_CFLAGS += `if test -f $(BASE)/.libs/libfreeswitch_la-switch_odbc.o ; then echo -DSWITCH_HAVE_ODBC; fi ;` ++LOCAL_LIBADD += -liodbc +Index: src/mod/applications/mod_limit/Makefile +=================================================================== +--- src/mod/applications/mod_limit/Makefile (revision 13692) ++++ src/mod/applications/mod_limit/Makefile (working copy) +@@ -1,3 +1,4 @@ + BASE=../../../.. + include $(BASE)/build/modmake.rules + LOCAL_CFLAGS += `if test -f $(BASE)/.libs/libfreeswitch_la-switch_odbc.o ; then echo -DSWITCH_HAVE_ODBC; fi ;` ++LOCAL_LIBADD += -liodbc +Index: src/switch_core_speech.c +=================================================================== +--- src/switch_core_speech.c (revision 13692) ++++ src/switch_core_speech.c (working copy) +@@ -22,10 +22,11 @@ + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): +- * ++ * + * Anthony Minessale II + * Michael Jerris + * Paul D. Tinsley ++ * Christopher M. Rienzo + * + * + * switch_core_speech.c -- Main Core Library (speech functions) +@@ -92,9 +93,64 @@ + + SWITCH_DECLARE(switch_status_t) switch_core_speech_feed_tts(switch_speech_handle_t *sh, char *text, switch_speech_flag_t *flags) + { ++ switch_status_t status = SWITCH_STATUS_SUCCESS; ++ char *param_string = NULL; ++ char *data = NULL; ++ char *ltext = NULL; ++ + switch_assert(sh != NULL); + +- return sh->speech_interface->speech_feed_tts(sh, text, flags); ++ if (switch_strlen_zero(text)) { ++ status = SWITCH_STATUS_FALSE; ++ goto done; ++ } ++ ++ /* Set TTS parameters from params in the text string ++ * Params are defined as follows {name1=val1,name2=val2,name3=val3}text to speak ++ */ ++ ltext = strdup(text); ++ data = ltext; ++ ++ /* strip leading spaces */ ++ while (data && *data == ' ') { ++ data++; ++ } ++ if (switch_strlen_zero(data)) { ++ status = SWITCH_STATUS_FALSE; ++ goto done; ++ } ++ ++ /* extract params */ ++ if (*data == '{') { ++ param_string = data + 1; ++ data = switch_find_end_paren(data, '{', '}'); ++ if (switch_strlen_zero(data)) { ++ status = SWITCH_STATUS_FALSE; ++ goto done; ++ } else { ++ *data = '\0'; ++ data++; ++ } ++ } ++ ++ /* set TTS params */ ++ if (!switch_strlen_zero(param_string)) { ++ char *param[256] = { 0 }; ++ switch_separate_string(param_string, ',', param, (sizeof(param) / sizeof(param[0]))); ++ for (int i = 0; param[i]; ++i) { ++ char *param_pair[2] = { 0 }; ++ if(switch_separate_string(param[i], '=', param_pair, (sizeof(param_pair) / sizeof(param_pair[0]))) == 2) { ++ switch_core_speech_text_param_tts(sh, param_pair[0], param_pair[1]); ++ } ++ } ++ } ++ ++ status = sh->speech_interface->speech_feed_tts(sh, data, flags); ++ ++ done: ++ ++ switch_safe_free(ltext); ++ return status; + } + + SWITCH_DECLARE(void) switch_core_speech_flush_tts(switch_speech_handle_t *sh) +Index: src/include/switch_module_interfaces.h +=================================================================== +--- src/include/switch_module_interfaces.h (revision 13692) ++++ src/include/switch_module_interfaces.h (working copy) +@@ -342,9 +342,9 @@ + /*! function to open the asr interface */ + switch_status_t (*asr_open) (switch_asr_handle_t *ah, const char *codec, int rate, const char *dest, switch_asr_flag_t *flags); + /*! function to load a grammar to the asr interface */ +- switch_status_t (*asr_load_grammar) (switch_asr_handle_t *ah, const char *grammar, const char *path); ++ switch_status_t (*asr_load_grammar) (switch_asr_handle_t *ah, const char *grammar, const char *name); + /*! function to unload a grammar to the asr interface */ +- switch_status_t (*asr_unload_grammar) (switch_asr_handle_t *ah, const char *grammar); ++ switch_status_t (*asr_unload_grammar) (switch_asr_handle_t *ah, const char *name); + /*! function to close the asr interface */ + switch_status_t (*asr_close) (switch_asr_handle_t *ah, switch_asr_flag_t *flags); + /*! function to feed audio to the ASR */ +@@ -357,6 +357,11 @@ + switch_status_t (*asr_check_results) (switch_asr_handle_t *ah, switch_asr_flag_t *flags); + /*! function to read results from the ASR */ + switch_status_t (*asr_get_results) (switch_asr_handle_t *ah, char **xmlstr, switch_asr_flag_t *flags); ++ /*! function to start ASR input timers */ ++ switch_status_t (*asr_start_input_timers) (switch_asr_handle_t *ah); ++ void (*asr_text_param) (switch_asr_handle_t *ah, char *param, const char *val); ++ void (*asr_numeric_param) (switch_asr_handle_t *ah, char *param, int val); ++ void (*asr_float_param) (switch_asr_handle_t *ah, char *param, double val); + switch_thread_rwlock_t *rwlock; + int refs; + switch_mutex_t *reflock; +@@ -409,7 +414,7 @@ + }; + + +-/*! an abstract representation of a asr/tts speech interface. */ ++/*! an abstract representation of a tts speech interface. */ + struct switch_speech_handle { + /*! the interface of the module that implemented the current speech interface */ + switch_speech_interface_t *speech_interface; +Index: src/include/switch_ivr.h +=================================================================== +--- src/include/switch_ivr.h (revision 13692) ++++ src/include/switch_ivr.h (working copy) +@@ -148,15 +148,15 @@ + \brief Engage background Speech detection on a session + \param session the session to attach + \param mod_name the module name of the ASR library +- \param grammar the grammar name +- \param path the path to the grammar file ++ \param grammar the grammar text, URI, or local file name ++ \param name the grammar name + \param dest the destination address + \param ah an ASR handle to use (NULL to create one) + \return SWITCH_STATUS_SUCCESS if all is well + */ + SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech(switch_core_session_t *session, + const char *mod_name, +- const char *grammar, const char *path, const char *dest, switch_asr_handle_t *ah); ++ const char *grammar, const char *name, const char *dest, switch_asr_handle_t *ah); + + /*! + \brief Stop background Speech detection on a session +@@ -182,19 +182,19 @@ + /*! + \brief Load a grammar on a background speech detection handle + \param session The session to change the grammar on +- \param grammar the grammar name +- \param path the grammar path ++ \param grammar the grammar text, URI, or local file name ++ \param name the grammar name + \return SWITCH_STATUS_SUCCESS if all is well + */ +-SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech_load_grammar(switch_core_session_t *session, char *grammar, char *path); ++SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech_load_grammar(switch_core_session_t *session, char *grammar, char *name); + + /*! + \brief Unload a grammar on a background speech detection handle + \param session The session to change the grammar on +- \param grammar the grammar name ++ \param name the grammar name + \return SWITCH_STATUS_SUCCESS if all is well + */ +-SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech_unload_grammar(switch_core_session_t *session, const char *grammar); ++SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech_unload_grammar(switch_core_session_t *session, const char *name); + + /*! + \brief Record a session to disk +Index: src/include/switch_core.h +=================================================================== +--- src/include/switch_core.h (revision 13692) ++++ src/include/switch_core.h (working copy) +@@ -1623,19 +1623,19 @@ + /*! + \brief Load a grammar to an asr handle + \param ah the handle to load to +- \param grammar the name of the grammar +- \param path the path to the grammaar file ++ \param grammar the grammar text, file path, or URI ++ \param name the grammar name + \return SWITCH_STATUS_SUCCESS + */ +-SWITCH_DECLARE(switch_status_t) switch_core_asr_load_grammar(switch_asr_handle_t *ah, const char *grammar, const char *path); ++SWITCH_DECLARE(switch_status_t) switch_core_asr_load_grammar(switch_asr_handle_t *ah, const char *grammar, const char *name); + + /*! + \brief Unload a grammar from an asr handle + \param ah the handle to unload the grammar from +- \param grammar the grammar to unload ++ \param name the name of the grammar to unload + \return SWITCH_STATUS_SUCCESS + */ +-SWITCH_DECLARE(switch_status_t) switch_core_asr_unload_grammar(switch_asr_handle_t *ah, const char *grammar); ++SWITCH_DECLARE(switch_status_t) switch_core_asr_unload_grammar(switch_asr_handle_t *ah, const char *name); + + /*! + \brief Pause detection on an asr handle +@@ -1651,6 +1651,37 @@ + */ + SWITCH_DECLARE(switch_status_t) switch_core_asr_resume(switch_asr_handle_t *ah); + ++/*! ++ \brief Start input timers on an asr handle ++ \param ah the handle to start timers on ++ \return SWITCH_STATUS_SUCCESS ++*/ ++SWITCH_DECLARE(switch_status_t) switch_core_asr_start_input_timers(switch_asr_handle_t *ah); ++ ++/*! ++ \brief Set a text parameter on an asr handle ++ \param sh the asr handle ++ \param param the parameter ++ \param val the value ++*/ ++SWITCH_DECLARE(void) switch_core_asr_text_param(switch_asr_handle_t *ah, char *param, const char *val); ++ ++/*! ++ \brief Set a numeric parameter on an asr handle ++ \param sh the asr handle ++ \param param the parameter ++ \param val the value ++*/ ++SWITCH_DECLARE(void) switch_core_asr_numeric_param(switch_asr_handle_t *ah, char *param, int val); ++ ++/*! ++ \brief Set a float parameter on an asr handle ++ \param sh the asr handle ++ \param param the parameter ++ \param val the value ++*/ ++SWITCH_DECLARE(void) switch_core_asr_float_param(switch_asr_handle_t *ah, char *param, double val); ++ + ///\} + + +@@ -1659,7 +1690,7 @@ + ///\{ + /*! + \brief Open a directory handle +- \param dh a direcotry handle to use ++ \param dh a directory handle to use + \param module_name the directory module to use + \param source the source of the db (ip, hostname, path etc) + \param dsn the username or designation of the lookup +@@ -1672,7 +1703,7 @@ + + /*! + \brief Query a directory handle +- \param dh a direcotry handle to use ++ \param dh a directory handle to use + \param base the base to query against + \param query a string of filters or query data + \return SWITCH_STATUS_SUCCESS if the query is successful +@@ -1681,23 +1712,23 @@ + + /*! + \brief Obtain the next record in a lookup +- \param dh a direcotry handle to use ++ \param dh a directory handle to use + \return SWITCH_STATUS_SUCCESS if another record exists + */ + SWITCH_DECLARE(switch_status_t) switch_core_directory_next(switch_directory_handle_t *dh); + + /*! + \brief Obtain the next name/value pair in the current record +- \param dh a direcotry handle to use ++ \param dh a directory handle to use + \param var a pointer to pointer of the name to fill in +- \param val a pointer to poinbter of the value to fill in ++ \param val a pointer to pointer of the value to fill in + \return SWITCH_STATUS_SUCCESS if an item exists + */ + SWITCH_DECLARE(switch_status_t) switch_core_directory_next_pair(switch_directory_handle_t *dh, char **var, char **val); + + /*! + \brief Close an open directory handle +- \param dh a direcotry handle to close ++ \param dh a directory handle to close + \return SWITCH_STATUS_SUCCESS if handle was closed + */ + SWITCH_DECLARE(switch_status_t) switch_core_directory_close(switch_directory_handle_t *dh); +Index: libs/speex/config.h.in +=================================================================== +--- libs/speex/config.h.in (revision 13692) ++++ libs/speex/config.h.in (working copy) +@@ -96,13 +96,13 @@ + /* Define to the version of this package. */ + #undef PACKAGE_VERSION + +-/* The size of a `int', as computed by sizeof. */ ++/* The size of `int', as computed by sizeof. */ + #undef SIZEOF_INT + +-/* The size of a `long', as computed by sizeof. */ ++/* The size of `long', as computed by sizeof. */ + #undef SIZEOF_LONG + +-/* The size of a `short', as computed by sizeof. */ ++/* The size of `short', as computed by sizeof. */ + #undef SIZEOF_SHORT + + /* Version extra */ diff --git a/src/include/switch_core.h b/src/include/switch_core.h index 16063b41a3..53bc92835f 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -1623,19 +1623,19 @@ SWITCH_DECLARE(switch_status_t) switch_core_asr_get_results(switch_asr_handle_t /*! \brief Load a grammar to an asr handle \param ah the handle to load to - \param grammar the name of the grammar - \param path the path to the grammaar file + \param grammar the grammar text, file path, or URI + \param name the grammar name \return SWITCH_STATUS_SUCCESS */ -SWITCH_DECLARE(switch_status_t) switch_core_asr_load_grammar(switch_asr_handle_t *ah, const char *grammar, const char *path); +SWITCH_DECLARE(switch_status_t) switch_core_asr_load_grammar(switch_asr_handle_t *ah, const char *grammar, const char *name); /*! \brief Unload a grammar from an asr handle \param ah the handle to unload the grammar from - \param grammar the grammar to unload + \param name the name of the grammar to unload \return SWITCH_STATUS_SUCCESS */ -SWITCH_DECLARE(switch_status_t) switch_core_asr_unload_grammar(switch_asr_handle_t *ah, const char *grammar); +SWITCH_DECLARE(switch_status_t) switch_core_asr_unload_grammar(switch_asr_handle_t *ah, const char *name); /*! \brief Pause detection on an asr handle @@ -1651,6 +1651,37 @@ SWITCH_DECLARE(switch_status_t) switch_core_asr_pause(switch_asr_handle_t *ah); */ SWITCH_DECLARE(switch_status_t) switch_core_asr_resume(switch_asr_handle_t *ah); +/*! + \brief Start input timers on an asr handle + \param ah the handle to start timers on + \return SWITCH_STATUS_SUCCESS +*/ +SWITCH_DECLARE(switch_status_t) switch_core_asr_start_input_timers(switch_asr_handle_t *ah); + +/*! + \brief Set a text parameter on an asr handle + \param sh the asr handle + \param param the parameter + \param val the value +*/ +SWITCH_DECLARE(void) switch_core_asr_text_param(switch_asr_handle_t *ah, char *param, const char *val); + +/*! + \brief Set a numeric parameter on an asr handle + \param sh the asr handle + \param param the parameter + \param val the value +*/ +SWITCH_DECLARE(void) switch_core_asr_numeric_param(switch_asr_handle_t *ah, char *param, int val); + +/*! + \brief Set a float parameter on an asr handle + \param sh the asr handle + \param param the parameter + \param val the value +*/ +SWITCH_DECLARE(void) switch_core_asr_float_param(switch_asr_handle_t *ah, char *param, double val); + ///\} @@ -1659,7 +1690,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_asr_resume(switch_asr_handle_t *ah); ///\{ /*! \brief Open a directory handle - \param dh a direcotry handle to use + \param dh a directory handle to use \param module_name the directory module to use \param source the source of the db (ip, hostname, path etc) \param dsn the username or designation of the lookup @@ -1672,7 +1703,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_directory_open(switch_directory_hand /*! \brief Query a directory handle - \param dh a direcotry handle to use + \param dh a directory handle to use \param base the base to query against \param query a string of filters or query data \return SWITCH_STATUS_SUCCESS if the query is successful @@ -1681,23 +1712,23 @@ SWITCH_DECLARE(switch_status_t) switch_core_directory_query(switch_directory_han /*! \brief Obtain the next record in a lookup - \param dh a direcotry handle to use + \param dh a directory handle to use \return SWITCH_STATUS_SUCCESS if another record exists */ SWITCH_DECLARE(switch_status_t) switch_core_directory_next(switch_directory_handle_t *dh); /*! \brief Obtain the next name/value pair in the current record - \param dh a direcotry handle to use + \param dh a directory handle to use \param var a pointer to pointer of the name to fill in - \param val a pointer to poinbter of the value to fill in + \param val a pointer to pointer of the value to fill in \return SWITCH_STATUS_SUCCESS if an item exists */ SWITCH_DECLARE(switch_status_t) switch_core_directory_next_pair(switch_directory_handle_t *dh, char **var, char **val); /*! \brief Close an open directory handle - \param dh a direcotry handle to close + \param dh a directory handle to close \return SWITCH_STATUS_SUCCESS if handle was closed */ SWITCH_DECLARE(switch_status_t) switch_core_directory_close(switch_directory_handle_t *dh); diff --git a/src/include/switch_ivr.h b/src/include/switch_ivr.h index 375c231ddf..712f9b861e 100644 --- a/src/include/switch_ivr.h +++ b/src/include/switch_ivr.h @@ -148,15 +148,15 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_collect_digits_count(switch_core_sess \brief Engage background Speech detection on a session \param session the session to attach \param mod_name the module name of the ASR library - \param grammar the grammar name - \param path the path to the grammar file + \param grammar the grammar text, URI, or local file name + \param name the grammar name \param dest the destination address \param ah an ASR handle to use (NULL to create one) \return SWITCH_STATUS_SUCCESS if all is well */ SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech(switch_core_session_t *session, const char *mod_name, - const char *grammar, const char *path, const char *dest, switch_asr_handle_t *ah); + const char *grammar, const char *name, const char *dest, switch_asr_handle_t *ah); /*! \brief Stop background Speech detection on a session @@ -182,19 +182,19 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_resume_detect_speech(switch_core_sess /*! \brief Load a grammar on a background speech detection handle \param session The session to change the grammar on - \param grammar the grammar name - \param path the grammar path + \param grammar the grammar text, URI, or local file name + \param name the grammar name \return SWITCH_STATUS_SUCCESS if all is well */ -SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech_load_grammar(switch_core_session_t *session, char *grammar, char *path); +SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech_load_grammar(switch_core_session_t *session, char *grammar, char *name); /*! \brief Unload a grammar on a background speech detection handle \param session The session to change the grammar on - \param grammar the grammar name + \param name the grammar name \return SWITCH_STATUS_SUCCESS if all is well */ -SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech_unload_grammar(switch_core_session_t *session, const char *grammar); +SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech_unload_grammar(switch_core_session_t *session, const char *name); /*! \brief Record a session to disk diff --git a/src/include/switch_module_interfaces.h b/src/include/switch_module_interfaces.h index 13a5b7a1e7..a4e5022387 100644 --- a/src/include/switch_module_interfaces.h +++ b/src/include/switch_module_interfaces.h @@ -342,9 +342,9 @@ struct switch_asr_interface { /*! function to open the asr interface */ switch_status_t (*asr_open) (switch_asr_handle_t *ah, const char *codec, int rate, const char *dest, switch_asr_flag_t *flags); /*! function to load a grammar to the asr interface */ - switch_status_t (*asr_load_grammar) (switch_asr_handle_t *ah, const char *grammar, const char *path); + switch_status_t (*asr_load_grammar) (switch_asr_handle_t *ah, const char *grammar, const char *name); /*! function to unload a grammar to the asr interface */ - switch_status_t (*asr_unload_grammar) (switch_asr_handle_t *ah, const char *grammar); + switch_status_t (*asr_unload_grammar) (switch_asr_handle_t *ah, const char *name); /*! function to close the asr interface */ switch_status_t (*asr_close) (switch_asr_handle_t *ah, switch_asr_flag_t *flags); /*! function to feed audio to the ASR */ @@ -357,6 +357,11 @@ struct switch_asr_interface { switch_status_t (*asr_check_results) (switch_asr_handle_t *ah, switch_asr_flag_t *flags); /*! function to read results from the ASR */ switch_status_t (*asr_get_results) (switch_asr_handle_t *ah, char **xmlstr, switch_asr_flag_t *flags); + /*! function to start ASR input timers */ + switch_status_t (*asr_start_input_timers) (switch_asr_handle_t *ah); + void (*asr_text_param) (switch_asr_handle_t *ah, char *param, const char *val); + void (*asr_numeric_param) (switch_asr_handle_t *ah, char *param, int val); + void (*asr_float_param) (switch_asr_handle_t *ah, char *param, double val); switch_thread_rwlock_t *rwlock; int refs; switch_mutex_t *reflock; @@ -409,7 +414,7 @@ struct switch_speech_interface { }; -/*! an abstract representation of a asr/tts speech interface. */ +/*! an abstract representation of a tts speech interface. */ struct switch_speech_handle { /*! the interface of the module that implemented the current speech interface */ switch_speech_interface_t *speech_interface; diff --git a/src/mod/applications/mod_limit/Makefile b/src/mod/applications/mod_limit/Makefile index 215d377458..ab5673257d 100644 --- a/src/mod/applications/mod_limit/Makefile +++ b/src/mod/applications/mod_limit/Makefile @@ -1,3 +1,4 @@ BASE=../../../.. include $(BASE)/build/modmake.rules LOCAL_CFLAGS += `if test -f $(BASE)/.libs/libfreeswitch_la-switch_odbc.o ; then echo -DSWITCH_HAVE_ODBC; fi ;` +LOCAL_LIBADD += -liodbc diff --git a/src/mod/applications/mod_voicemail/Makefile b/src/mod/applications/mod_voicemail/Makefile index 215d377458..ab5673257d 100644 --- a/src/mod/applications/mod_voicemail/Makefile +++ b/src/mod/applications/mod_voicemail/Makefile @@ -1,3 +1,4 @@ BASE=../../../.. include $(BASE)/build/modmake.rules LOCAL_CFLAGS += `if test -f $(BASE)/.libs/libfreeswitch_la-switch_odbc.o ; then echo -DSWITCH_HAVE_ODBC; fi ;` +LOCAL_LIBADD += -liodbc diff --git a/src/mod/asr_tts/mod_pocketsphinx/mod_pocketsphinx.c b/src/mod/asr_tts/mod_pocketsphinx/mod_pocketsphinx.c index 42a9f54367..7dfb4a3458 100644 --- a/src/mod/asr_tts/mod_pocketsphinx/mod_pocketsphinx.c +++ b/src/mod/asr_tts/mod_pocketsphinx/mod_pocketsphinx.c @@ -111,7 +111,7 @@ static switch_status_t pocketsphinx_asr_open(switch_asr_handle_t *ah, const char } /*! function to load a grammar to the asr interface */ -static switch_status_t pocketsphinx_asr_load_grammar(switch_asr_handle_t *ah, const char *grammar, const char *path) +static switch_status_t pocketsphinx_asr_load_grammar(switch_asr_handle_t *ah, const char *grammar, const char *name) { char *jsgf, *dic, *model, *rate = NULL; pocketsphinx_t *ps = (pocketsphinx_t *) ah->private_info; @@ -199,7 +199,7 @@ static switch_status_t pocketsphinx_asr_load_grammar(switch_asr_handle_t *ah, co } /*! function to unload a grammar to the asr interface */ -static switch_status_t pocketsphinx_asr_unload_grammar(switch_asr_handle_t *ah, const char *grammar) +static switch_status_t pocketsphinx_asr_unload_grammar(switch_asr_handle_t *ah, const char *name) { return SWITCH_STATUS_SUCCESS; } @@ -506,6 +506,10 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_pocketsphinx_load) asr_interface->asr_pause = pocketsphinx_asr_pause; asr_interface->asr_check_results = pocketsphinx_asr_check_results; asr_interface->asr_get_results = pocketsphinx_asr_get_results; + asr_interface->asr_start_input_timers = NULL; + asr_interface->asr_text_param = NULL; + asr_interface->asr_numeric_param = NULL; + asr_interface->asr_float_param = NULL; err_set_logfp(NULL); diff --git a/src/switch_core_asr.c b/src/switch_core_asr.c index 03b26ddd38..32cdb9d09b 100644 --- a/src/switch_core_asr.c +++ b/src/switch_core_asr.c @@ -26,6 +26,7 @@ * Anthony Minessale II * Michael Jerris * Paul D. Tinsley + * Christopher M. Rienzo * * * switch_core_asr.c -- Main Core Library (Speech Detection Interface) @@ -79,30 +80,74 @@ SWITCH_DECLARE(switch_status_t) switch_core_asr_open(switch_asr_handle_t *ah, return ah->asr_interface->asr_open(ah, codec, rate, dest, flags); } -SWITCH_DECLARE(switch_status_t) switch_core_asr_load_grammar(switch_asr_handle_t *ah, const char *grammar, const char *path) +SWITCH_DECLARE(switch_status_t) switch_core_asr_load_grammar(switch_asr_handle_t *ah, const char *grammar, const char *name) { - char *epath = NULL; - switch_status_t status; + switch_status_t status = SWITCH_STATUS_SUCCESS; + char *param_string = NULL; + char *data = NULL; + char *lgrammar = NULL; switch_assert(ah != NULL); - if (!switch_is_file_path(path)) { - epath = switch_mprintf("%s%s%s", SWITCH_GLOBAL_dirs.grammar_dir, SWITCH_PATH_SEPARATOR, path); - path = epath; + if (switch_strlen_zero(grammar)) { + status = SWITCH_STATUS_FALSE; + goto done; } - status = ah->asr_interface->asr_load_grammar(ah, grammar, path); - switch_safe_free(epath); + /* Set ASR parameters from params in the grammar string + * Params are defined as follows {name1=val1,name2=val2,name3=val3}grammar text + */ + lgrammar = strdup(grammar); + data = lgrammar; + /* strip leading spaces */ + while (data && *data == ' ') { + data++; + } + if (switch_strlen_zero(data)) { + status = SWITCH_STATUS_FALSE; + goto done; + } + + /* extract params */ + if (*data == '{') { + param_string = data + 1; + data = switch_find_end_paren(data, '{', '}'); + if (switch_strlen_zero(data)) { + status = SWITCH_STATUS_FALSE; + goto done; + } else { + *data = '\0'; + data++; + } + } + + /* set ASR params */ + if (!switch_strlen_zero(param_string)) { + char *param[256] = { 0 }; + switch_separate_string(param_string, ',', param, (sizeof(param) / sizeof(param[0]))); + for (int i = 0; param[i]; ++i) { + char *param_pair[2] = { 0 }; + if(switch_separate_string(param[i], '=', param_pair, (sizeof(param_pair) / sizeof(param_pair[0]))) == 2) { + switch_core_asr_text_param(ah, param_pair[0], param_pair[1]); + } + } + } + + status = ah->asr_interface->asr_load_grammar(ah, data, name); + + done: + + switch_safe_free(lgrammar); return status; } -SWITCH_DECLARE(switch_status_t) switch_core_asr_unload_grammar(switch_asr_handle_t *ah, const char *grammar) +SWITCH_DECLARE(switch_status_t) switch_core_asr_unload_grammar(switch_asr_handle_t *ah, const char *name) { switch_status_t status; switch_assert(ah != NULL); - status = ah->asr_interface->asr_unload_grammar(ah, grammar); + status = ah->asr_interface->asr_unload_grammar(ah, name); return status; } @@ -158,6 +203,46 @@ SWITCH_DECLARE(switch_status_t) switch_core_asr_get_results(switch_asr_handle_t return ah->asr_interface->asr_get_results(ah, xmlstr, flags); } +SWITCH_DECLARE(switch_status_t) switch_core_asr_start_input_timers(switch_asr_handle_t *ah) +{ + switch_status_t status = SWITCH_STATUS_SUCCESS; + + switch_assert(ah != NULL); + + if (ah->asr_interface->asr_start_input_timers) { + status = ah->asr_interface->asr_start_input_timers(ah); + } + + return status; +} + +SWITCH_DECLARE(void) switch_core_asr_text_param(switch_asr_handle_t *ah, char *param, const char *val) +{ + switch_assert(ah != NULL); + + if (ah->asr_interface->asr_text_param) { + ah->asr_interface->asr_text_param(ah, param, val); + } +} + +SWITCH_DECLARE(void) switch_core_asr_numeric_param(switch_asr_handle_t *ah, char *param, int val) +{ + switch_assert(ah != NULL); + + if (ah->asr_interface->asr_numeric_param) { + ah->asr_interface->asr_numeric_param(ah, param, val); + } +} + +SWITCH_DECLARE(void) switch_core_asr_float_param(switch_asr_handle_t *ah, char *param, double val) +{ + switch_assert(ah != NULL); + + if (ah->asr_interface->asr_float_param) { + ah->asr_interface->asr_float_param(ah, param, val); + } +} + /* For Emacs: * Local Variables: * mode:c diff --git a/src/switch_core_speech.c b/src/switch_core_speech.c index f156a81230..6e4e8917cb 100644 --- a/src/switch_core_speech.c +++ b/src/switch_core_speech.c @@ -22,10 +22,11 @@ * the Initial Developer. All Rights Reserved. * * Contributor(s): - * + * * Anthony Minessale II * Michael Jerris * Paul D. Tinsley + * Christopher M. Rienzo * * * switch_core_speech.c -- Main Core Library (speech functions) @@ -92,9 +93,64 @@ SWITCH_DECLARE(switch_status_t) switch_core_speech_open(switch_speech_handle_t * SWITCH_DECLARE(switch_status_t) switch_core_speech_feed_tts(switch_speech_handle_t *sh, char *text, switch_speech_flag_t *flags) { + switch_status_t status = SWITCH_STATUS_SUCCESS; + char *param_string = NULL; + char *data = NULL; + char *ltext = NULL; + switch_assert(sh != NULL); - return sh->speech_interface->speech_feed_tts(sh, text, flags); + if (switch_strlen_zero(text)) { + status = SWITCH_STATUS_FALSE; + goto done; + } + + /* Set TTS parameters from params in the text string + * Params are defined as follows {name1=val1,name2=val2,name3=val3}text to speak + */ + ltext = strdup(text); + data = ltext; + + /* strip leading spaces */ + while (data && *data == ' ') { + data++; + } + if (switch_strlen_zero(data)) { + status = SWITCH_STATUS_FALSE; + goto done; + } + + /* extract params */ + if (*data == '{') { + param_string = data + 1; + data = switch_find_end_paren(data, '{', '}'); + if (switch_strlen_zero(data)) { + status = SWITCH_STATUS_FALSE; + goto done; + } else { + *data = '\0'; + data++; + } + } + + /* set TTS params */ + if (!switch_strlen_zero(param_string)) { + char *param[256] = { 0 }; + switch_separate_string(param_string, ',', param, (sizeof(param) / sizeof(param[0]))); + for (int i = 0; param[i]; ++i) { + char *param_pair[2] = { 0 }; + if(switch_separate_string(param[i], '=', param_pair, (sizeof(param_pair) / sizeof(param_pair[0]))) == 2) { + switch_core_speech_text_param_tts(sh, param_pair[0], param_pair[1]); + } + } + } + + status = sh->speech_interface->speech_feed_tts(sh, data, flags); + + done: + + switch_safe_free(ltext); + return status; } SWITCH_DECLARE(void) switch_core_speech_flush_tts(switch_speech_handle_t *sh) diff --git a/src/switch_ivr_async.c b/src/switch_ivr_async.c index d575947094..282762d732 100644 --- a/src/switch_ivr_async.c +++ b/src/switch_ivr_async.c @@ -2027,14 +2027,14 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_resume_detect_speech(switch_core_sess return SWITCH_STATUS_FALSE; } -SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech_load_grammar(switch_core_session_t *session, char *grammar, char *path) +SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech_load_grammar(switch_core_session_t *session, char *grammar, char *name) { switch_channel_t *channel = switch_core_session_get_channel(session); switch_asr_flag_t flags = SWITCH_ASR_FLAG_NONE; struct speech_thread_handle *sth = switch_channel_get_private(channel, SWITCH_SPEECH_KEY); if (sth) { - if (switch_core_asr_load_grammar(sth->ah, grammar, path) != SWITCH_STATUS_SUCCESS) { + if (switch_core_asr_load_grammar(sth->ah, grammar, name) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Error loading Grammar\n"); switch_core_asr_close(sth->ah, &flags); switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); @@ -2045,14 +2045,14 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech_load_grammar(switch_cor return SWITCH_STATUS_FALSE; } -SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech_unload_grammar(switch_core_session_t *session, const char *grammar) +SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech_unload_grammar(switch_core_session_t *session, const char *name) { switch_channel_t *channel = switch_core_session_get_channel(session); switch_asr_flag_t flags = SWITCH_ASR_FLAG_NONE; struct speech_thread_handle *sth = switch_channel_get_private(channel, SWITCH_SPEECH_KEY); if (sth) { - if (switch_core_asr_unload_grammar(sth->ah, grammar) != SWITCH_STATUS_SUCCESS) { + if (switch_core_asr_unload_grammar(sth->ah, name) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Error unloading Grammar\n"); switch_core_asr_close(sth->ah, &flags); switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); @@ -2065,7 +2065,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech_unload_grammar(switch_c SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech(switch_core_session_t *session, const char *mod_name, - const char *grammar, const char *path, const char *dest, switch_asr_handle_t *ah) + const char *grammar, const char *name, const char *dest, switch_asr_handle_t *ah) { switch_channel_t *channel = switch_core_session_get_channel(session); switch_status_t status; @@ -2085,7 +2085,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech(switch_core_session_t * } if (sth) { - if (switch_core_asr_load_grammar(sth->ah, grammar, path) != SWITCH_STATUS_SUCCESS) { + if (switch_core_asr_load_grammar(sth->ah, grammar, name) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Error loading Grammar\n"); switch_core_asr_close(sth->ah, &flags); return SWITCH_STATUS_FALSE; @@ -2100,7 +2100,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech(switch_core_session_t * read_impl.actual_samples_per_second, dest, &flags, switch_core_session_get_pool(session)) == SWITCH_STATUS_SUCCESS) { - if (switch_core_asr_load_grammar(ah, grammar, path) != SWITCH_STATUS_SUCCESS) { + if (switch_core_asr_load_grammar(ah, grammar, name) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Error loading Grammar\n"); switch_core_asr_close(ah, &flags); switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);