[commit] r3326 - in freeswitch/branches/knhor/trunk: . src src/include src/mod/languages/mod_spidermonkey
Author: knhor Date: Sun Nov 12 00:08:38 2006 New Revision: 3326 Modified: freeswitch/branches/knhor/trunk/ (props changed) freeswitch/branches/knhor/trunk/src/include/switch_ivr.h freeswitch/branches/knhor/trunk/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c freeswitch/branches/knhor/trunk/src/switch_ivr.c Log: Merged revisions 3317-3325 via svnmerge from trunk Modified: freeswitch/branches/knhor/trunk/src/include/switch_ivr.h ============================================================================== --- freeswitch/branches/knhor/trunk/src/include/switch_ivr.h (original) +++ freeswitch/branches/knhor/trunk/src/include/switch_ivr.h Sun Nov 12 00:08:38 2006 @@ -75,8 +75,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_collect_digits_callback(switch_core_session_t *session, switch_input_callback_function_t dtmf_callback, void *buf, - unsigned int buflen, - unsigned int timeout); + uint32_t buflen, + uint32_t timeout); /*! \brief Wait for specified number of DTMF digits, untile terminator is received or until the channel hangs up. @@ -91,11 +91,11 @@ */ SWITCH_DECLARE(switch_status_t) switch_ivr_collect_digits_count(switch_core_session_t *session, char *buf, - unsigned int buflen, - unsigned int maxdigits, + uint32_t buflen, + uint32_t maxdigits, const char *terminators, char *terminator, - unsigned int timeout); + uint32_t timeout); /*! \brief Engage background Speech detection on a session @@ -187,7 +187,7 @@ char *timer_name, switch_input_callback_function_t dtmf_callback, void *buf, - unsigned int buflen); + uint32_t buflen); @@ -207,7 +207,7 @@ char *file, switch_input_callback_function_t dtmf_callback, void *buf, - unsigned int buflen); + uint32_t buflen); /*! \brief Function to evaluate an expression against a string @@ -234,15 +234,15 @@ \note to test for digit capture failure look for \\0 in the first position of the buffer */ SWITCH_DECLARE(switch_status_t) switch_play_and_get_digits(switch_core_session_t *session, - unsigned int min_digits, - unsigned int max_digits, - unsigned int max_tries, - unsigned int timeout, + uint32_t min_digits, + uint32_t max_digits, + uint32_t max_tries, + uint32_t timeout, char* valid_terminators, char* audio_file, char* bad_input_audio_file, void* digit_buffer, - unsigned int digit_buffer_length, + uint32_t digit_buffer_length, char* digits_regex); SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session_t *session, @@ -252,7 +252,7 @@ switch_input_callback_function_t dtmf_callback, char *text, void *buf, - unsigned int buflen); + uint32_t buflen); /*! \brief Speak given text with given tts engine @@ -275,7 +275,7 @@ switch_input_callback_function_t dtmf_callback, char *text, void *buf, - unsigned int buflen); + uint32_t buflen); /*! \brief Make an outgoing call @@ -458,6 +458,103 @@ \return SWITCH_STATUS_SUCCESS if all is well */ SWITCH_DECLARE(switch_status_t) switch_ivr_digit_stream_parser_set_terminator(switch_ivr_digit_stream_parser_t *parser, char digit); + +/** @} */ + +/** + * @defgroup switch_ivr_menu IVR Menu Library + * @ingroup switch_ivr + * IVR menu functions + * + * @{ + */ + +typedef enum { + SWITCH_IVR_MENU_FLAG_FALLTOMAIN = (1 << 0), + SWITCH_IVR_MENU_FLAG_FREEPOOL = (1 << 1), + SWITCH_IVR_MENU_FLAG_STACK = (1 << 2), +} switch_ivr_menu_flags; +/* Actions are either set in switch_ivr_menu_bind_function or returned by a callback */ +typedef enum { + SWITCH_IVR_ACTION_DIE, /* Exit the menu. */ + SWITCH_IVR_ACTION_EXECMENU, /* Goto another menu in the stack. */ + SWITCH_IVR_ACTION_EXECAPP, /* Execute an application. */ + SWITCH_IVR_ACTION_PLAYSOUND, /* Play a sound. */ + SWITCH_IVR_ACTION_BACK, /* Go back 1 menu. */ + SWITCH_IVR_ACTION_TOMAIN, /* Go back to the top level menu. */ + SWITCH_IVR_ACTION_TRANSFER, /* Transfer caller to another ext. */ +} switch_ivr_action_t; +struct switch_ivr_menu; +typedef switch_ivr_action_t switch_ivr_menu_action_function_t(struct switch_ivr_menu *, char *, size_t, void *); +typedef struct switch_ivr_menu switch_ivr_menu_t; +typedef struct switch_ivr_menu_action switch_ivr_menu_action_t; +/******************************************************************************************************/ + +/*! + *\brief Create a new menu object. + *\param new the pointer to the new menu + *\param main The top level menu, (NULL if this is the top level one). + *\param name A pointer to the name of this menu. + *\param greeting_sound Optional pointer to a main sound (press 1 for this 2 for that). + *\param short_greeting_sound Optional pointer to a shorter main sound for subsequent loops. + *\param invalid_sound Optional pointer to a sound to play after invalid input. + *\param timeout A number of milliseconds to pause before looping. + *\param max_failures Maximum number of failures to withstand before hangingup This resets everytime you enter the menu. + *\param inlen The max len of the input (1 for 1 digit menu opts, 2 for 2 digit etc.) + *\param pool memory pool (NULL to create one) + *\return SWUTCH_STATUS_SUCCESS if the menu was created + */ +SWITCH_DECLARE(switch_status_t) switch_ivr_menu_init(switch_ivr_menu_t **new, + switch_ivr_menu_t *main, + char *name, + char *greeting_sound, + char *short_greeting_sound, + char *invalid_sound, + int timeout, + int max_failures, + int inlen, + switch_memory_pool_t *pool); + +/*! + *\brief switch_ivr_menu_bind_action: Bind a keystroke to an action. + *\param menu The menu obj you wish to bind to. + *\param ivr_action switch_ivr_action_t enum of what you want to do. + *\param arg Optional (sometimes necessary) string arguement. + *\param bind KeyStrokes to bind the action to. + *\return SWUTCH_STATUS_SUCCESS if the action was binded + */ +SWITCH_DECLARE(switch_status_t) switch_ivr_menu_bind_action(switch_ivr_menu_t *menu, switch_ivr_action_t ivr_action, char *arg, char *bind); + + +/*! + *\brief Bind a keystroke to a callback function. + *\param menu The menu obj you wish to bind to. + *\param function The function to call [int proto(struct switch_ivr_menu *, char *, size_t, void *)] + *\param bind KeyStrokes to bind the action to. + *\note The function is passed a buffer to fill in with any required argument data. + *\note The function is also passed an optional void pointer to an object set upon menu execution. (think threads) + *\note The function returns an switch_ivr_action_t enum of what you want to do. and looks to your buffer for args. + *\return SWUTCH_STATUS_SUCCESS if the function was binded + */ +SWITCH_DECLARE(switch_status_t) switch_ivr_menu_bind_function(switch_ivr_menu_t *menu, switch_ivr_menu_action_function_t *function, char *bind); + + +/*! + *\brief Execute a menu. + *\param session The session running the menu. + *\param stack The top-level menu object (the first one you created.) + *\param name A pointer to the name of the menu. + *\param obj A void pointer to an object you want to make avaliable to your callback functions that you may have binded with switch_ivr_menu_bind_function. + *\return SWITCH_STATUS_SUCCESS if all is well + */ +SWITCH_DECLARE(switch_status_t) switch_ivr_menu_execute(switch_core_session_t *session, switch_ivr_menu_t *stack, char *name, void *obj); + +/*! + *\brief free a stack of menu objects. + *\param stack The top level menu you wish to destroy. + *\return SWITCH_STATUS_SUCCESS if the object was a top level menu and it was freed + */ +SWITCH_DECLARE(switch_status_t) switch_ivr_menu_free_stack(switch_ivr_menu_t *stack); /** @} */ Modified: freeswitch/branches/knhor/trunk/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c ============================================================================== --- freeswitch/branches/knhor/trunk/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c (original) +++ freeswitch/branches/knhor/trunk/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c Sun Nov 12 00:08:38 2006 @@ -415,7 +415,7 @@ apr_dso_handle_t *dso = NULL; apr_status_t status = SWITCH_STATUS_SUCCESS; apr_dso_handle_sym_t function_handle = NULL; - spidermonkey_init_t spidermonkey_init; + spidermonkey_init_t spidermonkey_init = NULL; const sm_module_interface_t *module_interface, *mp; int loading = 1; Modified: freeswitch/branches/knhor/trunk/src/switch_ivr.c ============================================================================== --- freeswitch/branches/knhor/trunk/src/switch_ivr.c (original) +++ freeswitch/branches/knhor/trunk/src/switch_ivr.c Sun Nov 12 00:08:38 2006 @@ -176,13 +176,13 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_collect_digits_callback(switch_core_session_t *session, switch_input_callback_function_t input_callback, void *buf, - unsigned int buflen, - unsigned int timeout) + uint32_t buflen, + uint32_t timeout) { switch_channel_t *channel; switch_status_t status = SWITCH_STATUS_SUCCESS; switch_time_t started = 0; - unsigned int elapsed; + uint32_t elapsed; channel = switch_core_session_get_channel(session); assert(channel != NULL); @@ -201,7 +201,7 @@ char dtmf[128]; if (timeout) { - elapsed = (unsigned int)((switch_time_now() - started) / 1000); + elapsed = (uint32_t)((switch_time_now() - started) / 1000); if (elapsed >= timeout) { break; } @@ -243,17 +243,17 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_collect_digits_count(switch_core_session_t *session, char *buf, - unsigned int buflen, - unsigned int maxdigits, + uint32_t buflen, + uint32_t maxdigits, const char *terminators, char *terminator, - unsigned int timeout) + uint32_t timeout) { - unsigned int i = 0, x = (unsigned int) strlen(buf); + uint32_t i = 0, x = (uint32_t) strlen(buf); switch_channel_t *channel; switch_status_t status = SWITCH_STATUS_SUCCESS; switch_time_t started = 0; - unsigned int elapsed; + uint32_t elapsed; channel = switch_core_session_get_channel(session); assert(channel != NULL); @@ -278,7 +278,7 @@ switch_event_t *event; if (timeout) { - elapsed = (unsigned int)((switch_time_now() - started) / 1000); + elapsed = (uint32_t)((switch_time_now() - started) / 1000); if (elapsed >= timeout) { break; } @@ -292,7 +292,7 @@ if (switch_channel_has_dtmf(channel)) { char dtmf[128]; switch_channel_dequeue_dtmf(channel, dtmf, sizeof(dtmf)); - for(i =0 ; i < (unsigned int) strlen(dtmf); i++) { + for(i =0 ; i < (uint32_t) strlen(dtmf); i++) { if (strchr(terminators, dtmf[i])) { *terminator = dtmf[i]; @@ -327,7 +327,7 @@ char *file, switch_input_callback_function_t input_callback, void *buf, - unsigned int buflen) + uint32_t buflen) { switch_channel_t *channel; char dtmf[128]; @@ -911,7 +911,7 @@ char *timer_name, switch_input_callback_function_t input_callback, void *buf, - unsigned int buflen) + uint32_t buflen) { switch_channel_t *channel; int16_t abuf[FILE_STARTSAMPLES]; @@ -1264,9 +1264,9 @@ pcre_prepared = pcre_compile(expression, 0, &error, &error_offset, NULL); //See if there was an error in the expression - if(error != NULL) { + if (error != NULL) { //Clean up after ourselves - if(pcre_prepared) { + if (pcre_prepared) { pcre_free(pcre_prepared); pcre_prepared = NULL; } @@ -1282,7 +1282,7 @@ match_count = pcre_exec(pcre_prepared, NULL, target, (int) strlen(target), 0, 0, offset_vectors, sizeof(offset_vectors) / sizeof(offset_vectors[0])); //Clean up - if(pcre_prepared) { + if (pcre_prepared) { pcre_free(pcre_prepared); pcre_prepared = NULL; } @@ -1290,7 +1290,7 @@ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "number of matches: %d\n", match_count); //Was it a match made in heaven? - if(match_count > 0) { + if (match_count > 0) { return SWITCH_STATUS_SUCCESS; } else { return SWITCH_STATUS_FALSE; @@ -1298,15 +1298,15 @@ } SWITCH_DECLARE(switch_status_t) switch_play_and_get_digits(switch_core_session_t *session, - unsigned int min_digits, - unsigned int max_digits, - unsigned int max_tries, - unsigned int timeout, + uint32_t min_digits, + uint32_t max_digits, + uint32_t max_tries, + uint32_t timeout, char* valid_terminators, char* prompt_audio_file, char* bad_input_audio_file, void* digit_buffer, - unsigned int digit_buffer_length, + uint32_t digit_buffer_length, char* digits_regex) { @@ -1341,19 +1341,19 @@ } //we only get one digit out of playback, see if thats all we needed and what we got - if(max_digits == 1 && status == SWITCH_STATUS_BREAK) { + if (max_digits == 1 && status == SWITCH_STATUS_BREAK) { //Check the digit if we have a regex - if(digits_regex != NULL) { + if (digits_regex != NULL) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Checking regex [%s] on [%s]\n", digits_regex, digit_buffer); //Make sure the digit is allowed - if(switch_regex_match(digit_buffer, digits_regex) == SWITCH_STATUS_SUCCESS) { + if (switch_regex_match(digit_buffer, digits_regex) == SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Match found!\n"); //jobs done break; } else { //See if a bad input prompt was specified, if so, play it - if(strlen(bad_input_audio_file) > 0) { + if (strlen(bad_input_audio_file) > 0) { status = switch_ivr_play_file(session, NULL, bad_input_audio_file, NULL, NULL, NULL, 0); //Make sure we made it out alive @@ -1375,25 +1375,25 @@ status = switch_ivr_collect_digits_count(session, digit_buffer, digit_buffer_length, max_digits, valid_terminators, &terminator, timeout); //Make sure we made it out alive - if(status != SWITCH_STATUS_SUCCESS) { + if (status != SWITCH_STATUS_SUCCESS) { //Bail switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING); break; } //see if we got enough - if(min_digits <= strlen(digit_buffer)) { + if (min_digits <= strlen(digit_buffer)) { //See if we need to test a regex - if(digits_regex != NULL) { + if (digits_regex != NULL) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Checking regex [%s] on [%s]\n", digits_regex, digit_buffer); //Test the regex - if(switch_regex_match(digit_buffer, digits_regex) == SWITCH_STATUS_SUCCESS) { + if (switch_regex_match(digit_buffer, digits_regex) == SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Match found!\n"); //Jobs done return switch_channel_get_state(channel); } else { //See if a bad input prompt was specified, if so, play it - if(strlen(bad_input_audio_file) > 0) { + if (strlen(bad_input_audio_file) > 0) { status = switch_ivr_play_file(session, NULL, bad_input_audio_file, NULL, NULL, NULL, 0); //Make sure we made it out alive @@ -1423,7 +1423,7 @@ switch_input_callback_function_t input_callback, char *text, void *buf, - unsigned int buflen) + uint32_t buflen) { switch_channel_t *channel; short abuf[960]; @@ -1614,7 +1614,7 @@ switch_input_callback_function_t input_callback, char *text, void *buf, - unsigned int buflen) + uint32_t buflen) { switch_channel_t *channel; int interval = 0; @@ -1640,7 +1640,7 @@ if (switch_core_speech_open(&sh, tts_name, voice_name, - (unsigned int)rate, + (uint32_t)rate, &flags, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid TTS module!\n"); @@ -3376,6 +3376,319 @@ parser->terminator = digit; status = SWITCH_STATUS_SUCCESS; } + + return status; +} + +struct switch_ivr_menu_action; + +struct switch_ivr_menu { + char *name; + char *greeting_sound; + char *short_greeting_sound; + char *invalid_sound; + int max_failures; + int timeout; + int inlen; + uint32_t flags; + struct switch_ivr_menu_action *actions; + struct switch_ivr_menu *next; + switch_memory_pool_t *pool; +}; + + +struct switch_ivr_menu_action { + switch_ivr_menu_action_function_t *function; + switch_ivr_action_t ivr_action; + char *arg; + char *bind; + struct switch_ivr_menu_action *next; +}; + +static switch_ivr_menu_t *switch_ivr_find_menu(switch_ivr_menu_t *stack, char *name) { + switch_ivr_menu_t *ret; + for(ret = stack; ret ; ret = ret->next) { + if (!name || !strcmp(ret->name, name)) + break; + } + return ret; +} + + +static void switch_ivr_menu_stack(switch_ivr_menu_t **top, switch_ivr_menu_t *bottom) +{ + switch_ivr_menu_t *ptr; + + for(ptr = *top ; ptr && ptr->next ; ptr = ptr->next); + + if (ptr) { + ptr->next = bottom; + } else { + *top = bottom; + } + +} + +SWITCH_DECLARE(switch_status_t) switch_ivr_menu_init(switch_ivr_menu_t **new, + switch_ivr_menu_t *main, + char *name, + char *greeting_sound, + char *short_greeting_sound, + char *invalid_sound, + int timeout, + int max_failures, + int inlen, + switch_memory_pool_t *pool) +{ + switch_ivr_menu_t *menu; + uint8_t newpool = 0; + + if (!pool) { + if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "OH OH no pool\n"); + return SWITCH_STATUS_MEMERR; + } + newpool = 1; + } + + if (!(menu = switch_core_alloc(pool, sizeof(*menu)))) { + if (newpool) { + switch_core_destroy_memory_pool(&pool); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n"); + return SWITCH_STATUS_MEMERR; + } + } + menu->pool = pool; + + menu->name = switch_core_strdup(menu->pool, name); + menu->greeting_sound = switch_core_strdup(menu->pool, greeting_sound); + menu->short_greeting_sound = switch_core_strdup(menu->pool, short_greeting_sound); + menu->invalid_sound = switch_core_strdup(menu->pool, invalid_sound); + menu->max_failures = max_failures; + menu->timeout = timeout; + menu->actions = NULL; + menu->inlen = inlen; + if (newpool) { + menu->flags |= SWITCH_IVR_MENU_FLAG_FREEPOOL; + } + + if (menu->timeout <= 0) + menu->timeout = 10000; + if (menu->inlen <= 0) + menu->inlen = 1; + + if (main) { + switch_ivr_menu_stack(&main, menu); + } else { + menu->flags |= SWITCH_IVR_MENU_FLAG_STACK; + } + + *new = menu; + + return SWITCH_STATUS_SUCCESS; +} + + +SWITCH_DECLARE(switch_status_t) switch_ivr_menu_bind_action(switch_ivr_menu_t *menu, switch_ivr_action_t ivr_action, char *arg, char *bind) +{ + switch_ivr_menu_action_t *action; + + if ((action = switch_core_alloc(menu->pool, sizeof(*action)))) { + action->bind = bind; + action->next = menu->actions; + action->arg = arg; + action->ivr_action = ivr_action; + menu->actions = action; + return SWITCH_STATUS_SUCCESS; + } + + return SWITCH_STATUS_MEMERR; +} + + +SWITCH_DECLARE(switch_status_t) switch_ivr_menu_bind_function(switch_ivr_menu_t *menu, switch_ivr_menu_action_function_t *function, char *bind) +{ + switch_ivr_menu_action_t *action; + + + if ((action = switch_core_alloc(menu->pool, sizeof(*action)))) { + action->bind = bind; + action->function = function; + action->next = menu->actions; + menu->actions = action; + return SWITCH_STATUS_SUCCESS; + } + + return SWITCH_STATUS_MEMERR; +} + +SWITCH_DECLARE(switch_status_t) switch_ivr_menu_free_stack(switch_ivr_menu_t *stack) +{ + switch_memory_pool_t *pool; + + if (!switch_test_flag(stack, SWITCH_IVR_MENU_FLAG_STACK) || switch_test_flag(stack, SWITCH_IVR_MENU_FLAG_FREEPOOL)) { + return SWITCH_STATUS_FALSE; + } + + pool = stack->pool; + switch_core_destroy_memory_pool(&pool); + pool = NULL; + + return SWITCH_STATUS_SUCCESS; + +} + +SWITCH_DECLARE(switch_status_t) switch_ivr_menu_execute(switch_core_session_t *session, switch_ivr_menu_t *stack, char *name, void *obj) +{ + int reps = 0, errs = 0, match = 0, running = 1; + char *greeting_sound = NULL, *aptr; + char *buf, arg[512]; + switch_ivr_action_t todo = SWITCH_IVR_ACTION_DIE; + switch_ivr_menu_action_t *ap; + switch_ivr_menu_t *menu; + switch_channel_t *channel; + switch_status_t status = SWITCH_STATUS_SUCCESS; + + channel = switch_core_session_get_channel(session); + assert(channel != NULL); + + + if (!(menu = switch_ivr_find_menu(stack, name))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Menu!\n"); + return -1; + } + + if (!(buf = malloc(menu->inlen))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No Memory!\n"); + return -1; + } + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Executing IVR menu %s\n", menu->name); + + for (reps = 0 ; (running && status == SWITCH_STATUS_SUCCESS && errs < menu->max_failures) ; reps++) { + + if (!switch_channel_ready(channel)) { + break; + } + + + if (reps > 0 && menu->short_greeting_sound) { + greeting_sound = menu->short_greeting_sound; + } else { + greeting_sound = menu->greeting_sound; + } + + match = 0; + aptr = NULL; + memset(buf, 0, menu->inlen); + memset(arg, 0, sizeof(arg)); + + if (switch_play_and_get_digits(session, + menu->inlen, + menu->inlen, + 1, + menu->timeout, "#", + greeting_sound, + NULL, + buf, + menu->inlen, + NULL) != SWITCH_STATUS_SUCCESS) { + break; + } + + if (!switch_strlen_zero(buf)) { + for(ap = menu->actions; ap ; ap = ap->next) { + if (!strcmp(buf, ap->bind)) { + char *membuf; + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "IVR menu %s matched %s\n", menu->name, buf); + match++; + errs = 0; + if (ap->function) { + todo = ap->function(menu, arg, sizeof(arg), obj); + aptr = arg; + } else { + todo = ap->ivr_action; + aptr = ap->arg; + } + + switch(todo) { + case SWITCH_IVR_ACTION_DIE: + status = SWITCH_STATUS_FALSE; + break; + case SWITCH_IVR_ACTION_PLAYSOUND: + status = switch_ivr_play_file(session, NULL, aptr, NULL, NULL, NULL, 0); + break; + case SWITCH_IVR_ACTION_TRANSFER: + switch_ivr_session_transfer(session, aptr, NULL, NULL); + running = 0; + break; + case SWITCH_IVR_ACTION_EXECMENU: + reps = -1; + status = switch_ivr_menu_execute(session, stack, aptr, obj); + break; + case SWITCH_IVR_ACTION_EXECAPP: { + const switch_application_interface_t *application_interface; + if ((membuf = strdup(aptr))) { + char *app_name = membuf; + char *app_arg = strchr(app_name, ' '); + + if (app_arg) { + *app_arg = '\0'; + app_arg++; + } + + if (app_name && app_arg) { + if ((application_interface = switch_loadable_module_get_application_interface(app_name))) { + if (application_interface->application_function) { + application_interface->application_function(session, app_arg); + } + } + } + } + } + break; + case SWITCH_IVR_ACTION_BACK: + running = 0; + status = SWITCH_STATUS_SUCCESS; + break; + case SWITCH_IVR_ACTION_TOMAIN: + switch_set_flag(stack, SWITCH_IVR_MENU_FLAG_FALLTOMAIN); + status = SWITCH_STATUS_BREAK; + break; + default: + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid TODO!\n"); + break; + } + } + } + + + if (switch_test_flag(menu, SWITCH_IVR_MENU_FLAG_STACK)) { /* top level */ + if (switch_test_flag(stack, SWITCH_IVR_MENU_FLAG_FALLTOMAIN)) { /* catch the fallback and recover */ + switch_clear_flag(stack, SWITCH_IVR_MENU_FLAG_FALLTOMAIN); + status = SWITCH_STATUS_SUCCESS; + running = 1; + continue; + } + } + } + if (!match) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "IVR menu %s caught invalid input %s\n", menu->name, buf); + + if (menu->invalid_sound) { + status = switch_ivr_play_file(session, NULL, aptr, NULL, NULL, NULL, 0); + } + errs++; + + if (status == SWITCH_STATUS_SUCCESS) { + status = switch_ivr_sleep(session, 1000); + } + } + + } + + switch_safe_free(buf); return status; }
participants (1)
-
Freeswitch SVN