switch_ivr_menu.c File Reference

#include <switch.h>

Include dependency graph for switch_ivr_menu.c:

Go to the source code of this file.

Data Structures

struct  switch_ivr_menu
struct  switch_ivr_menu_action
struct  switch_ivr_menu_xml_map
struct  switch_ivr_menu_xml_ctx
struct  iam_s

Typedefs

typedef switch_ivr_menu_xml_map switch_ivr_menu_xml_map_t

Functions

static switch_ivr_menu_tswitch_ivr_menu_find (switch_ivr_menu_t *stack, const char *name)
static void switch_ivr_menu_stack_add (switch_ivr_menu_t **top, switch_ivr_menu_t *bottom)
switch_status_t switch_ivr_menu_init (switch_ivr_menu_t **new_menu, switch_ivr_menu_t *main, const char *name, const char *greeting_sound, const char *short_greeting_sound, const char *invalid_sound, const char *exit_sound, const char *confirm_macro, const char *confirm_key, const char *tts_engine, const char *tts_voice, int confirm_attempts, int inter_timeout, int digit_len, int timeout, int max_failures, int max_timeouts, switch_memory_pool_t *pool)
 Create a new menu object.
switch_status_t switch_ivr_menu_bind_action (switch_ivr_menu_t *menu, switch_ivr_action_t ivr_action, const char *arg, const char *bind)
 switch_ivr_menu_bind_action: Bind a keystroke to an action.
switch_status_t switch_ivr_menu_bind_function (switch_ivr_menu_t *menu, switch_ivr_menu_action_function_t *function, const char *arg, const char *bind)
 Bind a keystroke to a callback function.
switch_status_t switch_ivr_menu_stack_free (switch_ivr_menu_t *stack)
 free a stack of menu objects.
static switch_status_t play_and_collect (switch_core_session_t *session, switch_ivr_menu_t *menu, char *sound, switch_size_t need)
switch_status_t switch_ivr_menu_execute (switch_core_session_t *session, switch_ivr_menu_t *stack, char *name, void *obj)
 Execute a menu.
static switch_ivr_menu_xml_map_tswitch_ivr_menu_stack_xml_find (switch_ivr_menu_xml_ctx_t *xml_ctx, const char *name)
static switch_status_t switch_ivr_menu_stack_xml_add (switch_ivr_menu_xml_ctx_t *xml_ctx, const char *name, int action, switch_ivr_menu_action_function_t *function)
switch_status_t switch_ivr_menu_str2action (const char *action_name, switch_ivr_action_t *action)
static switch_bool_t is_valid_action (const char *action)
switch_status_t switch_ivr_menu_stack_xml_init (switch_ivr_menu_xml_ctx_t **xml_menu_ctx, switch_memory_pool_t *pool)
switch_status_t switch_ivr_menu_stack_xml_add_custom (switch_ivr_menu_xml_ctx_t *xml_menu_ctx, const char *name, switch_ivr_menu_action_function_t *function)
switch_status_t switch_ivr_menu_stack_xml_build (switch_ivr_menu_xml_ctx_t *xml_menu_ctx, switch_ivr_menu_t **menu_stack, switch_xml_t xml_menus, switch_xml_t xml_menu)
 Build a menu stack from an xml source.

Variables

static struct iam_s iam []


Typedef Documentation

typedef struct switch_ivr_menu_xml_map switch_ivr_menu_xml_map_t


Function Documentation

static switch_bool_t is_valid_action ( const char *  action  )  [static]

Definition at line 707 of file switch_ivr_menu.c.

References iam, SWITCH_CHANNEL_LOG, SWITCH_FALSE, switch_log_printf(), SWITCH_LOG_WARNING, switch_str_nil, SWITCH_TRUE, and zstr.

Referenced by switch_ivr_menu_stack_xml_build().

00708 {
00709         int i;
00710 
00711         if (!zstr(action)) {
00712                 for (i = 0;; i++) {
00713                         if (!iam[i].name) {
00714                                 break;
00715                         }
00716 
00717                         if (!strcmp(iam[i].name, action)) {
00718                                 return SWITCH_TRUE;
00719                         }
00720                 }
00721         }
00722 
00723         switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid Action [%s]\n", switch_str_nil(action));
00724         return SWITCH_FALSE;
00725 }

static switch_status_t play_and_collect ( switch_core_session_t session,
switch_ivr_menu_t menu,
char *  sound,
switch_size_t  need 
) [static]

Definition at line 297 of file switch_ivr_menu.c.

References buf, switch_input_args_t::buf, switch_ivr_menu::buf, switch_input_args_t::buflen, switch_ivr_menu::confirm_attempts, switch_ivr_menu::confirm_key, switch_ivr_menu::confirm_macro, switch_ivr_menu::inlen, switch_ivr_menu::inter_timeout, switch_ivr_menu::ptr, switch_channel_expand_variables, switch_channel_get_variable, SWITCH_CHANNEL_SESSION_LOG, switch_core_session_get_channel(), switch_ivr_collect_digits_count(), switch_ivr_phrase_macro, switch_ivr_play_file(), SWITCH_LOG_DEBUG, switch_log_printf(), switch_safe_free, SWITCH_STATUS_FALSE, SWITCH_STATUS_SUCCESS, switch_ivr_menu::timeout, and zstr.

Referenced by switch_ivr_menu_execute().

00298 {
00299         char terminator;
00300         uint32_t len;
00301         char *ptr;
00302         switch_status_t status = SWITCH_STATUS_FALSE;
00303         switch_input_args_t args = { 0 };
00304         switch_channel_t *channel;
00305         char *sound_expanded = sound;
00306         switch_size_t menu_buf_len = 0;
00307         const char *terminator_str = "#";
00308 
00309         if (!session || !menu || zstr(sound)) {
00310                 return status;
00311         }
00312 
00313         if ((channel = switch_core_session_get_channel(session))) {
00314                 const char *tmp;
00315                 sound_expanded = switch_channel_expand_variables(channel, sound);
00316                 if ((tmp = switch_channel_get_variable(channel, "ivr_menu_terminator")) && !zstr(tmp)) {
00317                         terminator_str = tmp;
00318                 }
00319         }
00320 
00321         memset(menu->buf, 0, menu->inlen + 1);
00322         menu->ptr = menu->buf;
00323 
00324         if (!need) {
00325                 len = 1;
00326                 ptr = NULL;
00327         } else {
00328                 len = (uint32_t) menu->inlen + 1;
00329                 ptr = menu->ptr;
00330         }
00331         args.buf = ptr;
00332         args.buflen = len;
00333 
00334         status = switch_ivr_play_file(session, NULL, sound_expanded, &args);
00335 
00336         if (sound_expanded != sound) {
00337                 switch_safe_free(sound_expanded);
00338         }
00339 
00340         if (!need) {
00341                 return status;
00342         }
00343 
00344         menu_buf_len = strlen(menu->buf);
00345 
00346         menu->ptr += menu_buf_len;
00347         if (menu_buf_len < need) {
00348                 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "waiting for %u/%u digits t/o %d\n",
00349                                                   (uint32_t) (menu->inlen - strlen(menu->buf)), (uint32_t) need, menu->inter_timeout);
00350                 status = switch_ivr_collect_digits_count(session, menu->ptr, menu->inlen - strlen(menu->buf),
00351                                                                                                  need, terminator_str, &terminator, menu_buf_len ? menu->inter_timeout : menu->timeout,
00352                                                                                                  menu->inter_timeout, menu->timeout);
00353         }
00354 
00355         if (menu->confirm_macro && status == SWITCH_STATUS_SUCCESS && *menu->buf != '\0') {
00356                 switch_input_args_t confirm_args = { 0 }, *ap = NULL;
00357                 char buf[10] = "";
00358                 char terminator_key;
00359                 int att = menu->confirm_attempts;
00360 
00361                 while (att) {
00362                         confirm_args.buf = buf;
00363                         confirm_args.buflen = sizeof(buf);
00364                         memset(buf, 0, confirm_args.buflen);
00365 
00366                         if (menu->confirm_key) {
00367                                 ap = &confirm_args;
00368                         }
00369 
00370                         switch_ivr_phrase_macro(session, menu->confirm_macro, menu->buf, NULL, ap);
00371 
00372                         if (menu->confirm_key && *buf == '\0') {
00373                                 switch_ivr_collect_digits_count(session, buf, sizeof(buf), 1, terminator_str, &terminator_key, menu->timeout, 0, 0);
00374                         }
00375 
00376                         if (menu->confirm_key && *buf != '\0') {
00377                                 if (*menu->confirm_key == *buf) {
00378                                         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
00379                                                                           "approving digits '%s' via confirm key %s\n", menu->buf, menu->confirm_key);
00380                                         break;
00381                                 } else {
00382                                         att = 0;
00383                                         break;
00384                                 }
00385                         }
00386                         att--;
00387                 }
00388                 if (!att) {
00389                         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "rejecting digits '%s' via confirm key %s\n", menu->buf,
00390                                                           menu->confirm_key);
00391                         *menu->buf = '\0';
00392                 }
00393         }
00394 
00395         switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "digits '%s'\n", menu->buf);
00396 
00397         return status;
00398 }

static switch_ivr_menu_t* switch_ivr_menu_find ( switch_ivr_menu_t stack,
const char *  name 
) [static]

Definition at line 72 of file switch_ivr_menu.c.

References switch_ivr_menu::name, and switch_ivr_menu::next.

Referenced by switch_ivr_menu_execute(), and switch_ivr_menu_stack_xml_build().

00073 {
00074         switch_ivr_menu_t *ret;
00075         for (ret = stack; ret; ret = ret->next) {
00076                 if (!name || !strcmp(ret->name, name))
00077                         break;
00078         }
00079         return ret;
00080 }

static void switch_ivr_menu_stack_add ( switch_ivr_menu_t **  top,
switch_ivr_menu_t bottom 
) [static]

Definition at line 82 of file switch_ivr_menu.c.

References switch_ivr_menu::next.

Referenced by switch_ivr_menu_init().

00083 {
00084         switch_ivr_menu_t *ptr;
00085 
00086         for (ptr = *top; ptr && ptr->next; ptr = ptr->next);
00087 
00088         if (ptr) {
00089                 ptr->next = bottom;
00090         } else {
00091                 *top = bottom;
00092         }
00093 
00094 }

static switch_status_t switch_ivr_menu_stack_xml_add ( switch_ivr_menu_xml_ctx_t xml_ctx,
const char *  name,
int  action,
switch_ivr_menu_action_function_t function 
) [static]

Definition at line 639 of file switch_ivr_menu.c.

References switch_ivr_menu_xml_map::action, switch_ivr_menu_xml_map::function, switch_ivr_menu_xml_ctx::map, switch_ivr_menu_xml_map::name, switch_ivr_menu_xml_map::next, switch_ivr_menu_xml_ctx::pool, SWITCH_CHANNEL_LOG, switch_core_alloc, switch_core_strdup, switch_ivr_menu_stack_xml_find(), SWITCH_LOG_DEBUG, SWITCH_LOG_ERROR, switch_log_printf(), SWITCH_STATUS_FALSE, SWITCH_STATUS_MEMERR, and SWITCH_STATUS_SUCCESS.

Referenced by switch_ivr_menu_stack_xml_add_custom(), and switch_ivr_menu_stack_xml_init().

00641 {
00642         switch_status_t status = SWITCH_STATUS_FALSE;
00643 
00644         /* if this action/function does not exist yet */
00645         if (xml_ctx != NULL && name != NULL && xml_ctx->pool != NULL && switch_ivr_menu_stack_xml_find(xml_ctx, name) == NULL) {
00646                 switch_ivr_menu_xml_map_t *map = switch_core_alloc(xml_ctx->pool, sizeof(switch_ivr_menu_xml_map_t));
00647 
00648                 if (map != NULL) {
00649                         map->name = switch_core_strdup(xml_ctx->pool, name);
00650                         map->action = action;
00651                         map->function = function;
00652 
00653                         if (map->name != NULL) {
00654                                 /* insert map item at top of list */
00655                                 map->next = xml_ctx->map;
00656                                 xml_ctx->map = map;
00657                                 status = SWITCH_STATUS_SUCCESS;
00658                         } else {
00659                                 status = SWITCH_STATUS_MEMERR;
00660                         }
00661                 } else {
00662                         status = SWITCH_STATUS_MEMERR;
00663                 }
00664 
00665                 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "switch_ivr_menu_stack_xml_add binding '%s'\n", name);
00666         } else {
00667                 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to add binding %s\n", name);
00668         }
00669 
00670         return status;
00671 }

static switch_ivr_menu_xml_map_t* switch_ivr_menu_stack_xml_find ( switch_ivr_menu_xml_ctx_t xml_ctx,
const char *  name 
) [static]

Definition at line 627 of file switch_ivr_menu.c.

References switch_ivr_menu_xml_ctx::map, switch_ivr_menu_xml_map::name, and switch_ivr_menu_xml_map::next.

Referenced by switch_ivr_menu_stack_xml_add().

00628 {
00629         switch_ivr_menu_xml_map_t *map = (xml_ctx != NULL ? xml_ctx->map : NULL);
00630         int rc = -1;
00631 
00632         while (map != NULL && (rc = strcasecmp(map->name, name)) != 0) {
00633                 map = map->next;
00634         }
00635 
00636         return (rc == 0 ? map : NULL);
00637 }


Variable Documentation

struct iam_s iam[] [static]

Referenced by is_valid_action(), switch_ivr_menu_stack_xml_init(), and switch_ivr_menu_str2action().


Generated on Sun May 20 04:00:11 2012 for FreeSWITCH API Documentation by  doxygen 1.4.7