add ivr api not sure it works yet
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@3319 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
parent
c834ba6a71
commit
8f8396d741
|
@ -404,6 +404,109 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_transfer_variable(switch_core_session
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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 flags Optional parameters to set to influence the menu behaviour.
|
||||||
|
*\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,
|
||||||
|
unsigned int flags,
|
||||||
|
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);
|
||||||
|
|
||||||
|
SWITCH_DECLARE(int) switch_ivr_menu_set_flag(switch_ivr_menu_t *menu, unsigned int flags);
|
||||||
|
SWITCH_DECLARE(int) switch_ivr_menu_clear_flag(switch_ivr_menu_t *menu, unsigned int flags);
|
||||||
|
SWITCH_DECLARE(int) switch_ivr_menu_test_flag(switch_ivr_menu_t *menu, unsigned int flags);
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
|
||||||
SWITCH_END_EXTERN_C
|
SWITCH_END_EXTERN_C
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
366
src/switch_ivr.c
366
src/switch_ivr.c
|
@ -1264,9 +1264,9 @@ SWITCH_DECLARE(switch_status_t) switch_regex_match(char *target, char *expressio
|
||||||
pcre_prepared = pcre_compile(expression, 0, &error, &error_offset, NULL);
|
pcre_prepared = pcre_compile(expression, 0, &error, &error_offset, NULL);
|
||||||
|
|
||||||
//See if there was an error in the expression
|
//See if there was an error in the expression
|
||||||
if(error != NULL) {
|
if (error != NULL) {
|
||||||
//Clean up after ourselves
|
//Clean up after ourselves
|
||||||
if(pcre_prepared) {
|
if (pcre_prepared) {
|
||||||
pcre_free(pcre_prepared);
|
pcre_free(pcre_prepared);
|
||||||
pcre_prepared = NULL;
|
pcre_prepared = NULL;
|
||||||
}
|
}
|
||||||
|
@ -1282,7 +1282,7 @@ SWITCH_DECLARE(switch_status_t) switch_regex_match(char *target, char *expressio
|
||||||
match_count = pcre_exec(pcre_prepared, NULL, target, (int) strlen(target), 0, 0, offset_vectors, sizeof(offset_vectors) / sizeof(offset_vectors[0]));
|
match_count = pcre_exec(pcre_prepared, NULL, target, (int) strlen(target), 0, 0, offset_vectors, sizeof(offset_vectors) / sizeof(offset_vectors[0]));
|
||||||
|
|
||||||
//Clean up
|
//Clean up
|
||||||
if(pcre_prepared) {
|
if (pcre_prepared) {
|
||||||
pcre_free(pcre_prepared);
|
pcre_free(pcre_prepared);
|
||||||
pcre_prepared = NULL;
|
pcre_prepared = NULL;
|
||||||
}
|
}
|
||||||
|
@ -1290,7 +1290,7 @@ SWITCH_DECLARE(switch_status_t) switch_regex_match(char *target, char *expressio
|
||||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "number of matches: %d\n", match_count);
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "number of matches: %d\n", match_count);
|
||||||
|
|
||||||
//Was it a match made in heaven?
|
//Was it a match made in heaven?
|
||||||
if(match_count > 0) {
|
if (match_count > 0) {
|
||||||
return SWITCH_STATUS_SUCCESS;
|
return SWITCH_STATUS_SUCCESS;
|
||||||
} else {
|
} else {
|
||||||
return SWITCH_STATUS_FALSE;
|
return SWITCH_STATUS_FALSE;
|
||||||
|
@ -1341,19 +1341,19 @@ SWITCH_DECLARE(switch_status_t) switch_play_and_get_digits(switch_core_session_t
|
||||||
}
|
}
|
||||||
|
|
||||||
//we only get one digit out of playback, see if thats all we needed and what we got
|
//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
|
//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);
|
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
|
//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");
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Match found!\n");
|
||||||
//jobs done
|
//jobs done
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
//See if a bad input prompt was specified, if so, play it
|
//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);
|
status = switch_ivr_play_file(session, NULL, bad_input_audio_file, NULL, NULL, NULL, 0);
|
||||||
|
|
||||||
//Make sure we made it out alive
|
//Make sure we made it out alive
|
||||||
|
@ -1375,25 +1375,25 @@ SWITCH_DECLARE(switch_status_t) switch_play_and_get_digits(switch_core_session_t
|
||||||
status = switch_ivr_collect_digits_count(session, digit_buffer, digit_buffer_length, max_digits, valid_terminators, &terminator, timeout);
|
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
|
//Make sure we made it out alive
|
||||||
if(status != SWITCH_STATUS_SUCCESS) {
|
if (status != SWITCH_STATUS_SUCCESS) {
|
||||||
//Bail
|
//Bail
|
||||||
switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
|
switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
//see if we got enough
|
//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
|
//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);
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Checking regex [%s] on [%s]\n", digits_regex, digit_buffer);
|
||||||
//Test the regex
|
//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");
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Match found!\n");
|
||||||
//Jobs done
|
//Jobs done
|
||||||
return switch_channel_get_state(channel);
|
return switch_channel_get_state(channel);
|
||||||
} else {
|
} else {
|
||||||
//See if a bad input prompt was specified, if so, play it
|
//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);
|
status = switch_ivr_play_file(session, NULL, bad_input_audio_file, NULL, NULL, NULL, 0);
|
||||||
|
|
||||||
//Make sure we made it out alive
|
//Make sure we made it out alive
|
||||||
|
@ -3235,3 +3235,343 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_transfer_variable(switch_core_session
|
||||||
|
|
||||||
return SWITCH_STATUS_SUCCESS;
|
return SWITCH_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
unsigned int 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(int) switch_ivr_menu_set_flag(switch_ivr_menu_t *menu, unsigned int flags)
|
||||||
|
{
|
||||||
|
if (flags) {
|
||||||
|
menu->flags |= flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
return menu->flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
SWITCH_DECLARE(int) switch_ivr_menu_clear_flag(switch_ivr_menu_t *menu, unsigned int flags)
|
||||||
|
{
|
||||||
|
if (flags) {
|
||||||
|
menu->flags &= ~flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
return menu->flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
SWITCH_DECLARE(int) switch_ivr_menu_test_flag(switch_ivr_menu_t *menu, unsigned int flags)
|
||||||
|
{
|
||||||
|
return (menu->flags & flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
unsigned int flags,
|
||||||
|
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->flags |= flags;
|
||||||
|
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_ivr_menu_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_ivr_menu_test_flag(stack, SWITCH_IVR_MENU_FLAG_FALLTOMAIN)) { /* catch the fallback and recover */
|
||||||
|
switch_ivr_menu_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue