FreeSWITCH API Documentation  1.7.0
Data Structures | Macros | Typedefs | Functions | Variables
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
 

Macros

#define MENU_EVENT_ENTER   "menu::enter"
 
#define MENU_EVENT_EXIT   "menu::exit"
 

Typedefs

typedef struct
switch_ivr_menu_xml_map 
switch_ivr_menu_xml_map_t
 

Functions

static void ivr_send_event (switch_core_session_t *session, char *event_type, switch_ivr_menu_t *menu)
 
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 *transfer_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. More...
 
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. More...
 
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. More...
 
switch_status_t switch_ivr_menu_stack_free (switch_ivr_menu_t *stack)
 free a stack of menu objects. More...
 
static switch_status_t play_and_collect (switch_core_session_t *session, switch_ivr_menu_t *menu, char *sound, switch_size_t need)
 
static void exec_app (switch_core_session_t *session, char *app_str)
 
switch_status_t switch_ivr_menu_execute (switch_core_session_t *session, switch_ivr_menu_t *stack, char *name, void *obj)
 Execute a menu. More...
 
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. More...
 

Variables

static struct iam_s iam []
 

Macro Definition Documentation

#define MENU_EVENT_ENTER   "menu::enter"

Definition at line 78 of file switch_ivr_menu.c.

Referenced by switch_ivr_menu_execute().

#define MENU_EVENT_EXIT   "menu::exit"

Definition at line 79 of file switch_ivr_menu.c.

Referenced by switch_ivr_menu_execute().

Typedef Documentation

Function Documentation

static void exec_app ( switch_core_session_t session,
char *  app_str 
)
static

Definition at line 429 of file switch_ivr_menu.c.

References switch_channel_expand_variables, switch_core_session_execute_application, switch_core_session_get_channel(), and switch_core_session_strdup.

Referenced by audio_bridge_thread(), and switch_ivr_menu_execute().

430 {
432  char *app = switch_core_session_strdup(session, app_str);
433  char *data = strchr(app, ' ');
434  char *expanded = NULL;
435 
436  if (data) {
437  *data++ = '\0';
438  }
439 
440  expanded = switch_channel_expand_variables(channel, data);
441 
442  switch_core_session_execute_application(session, app, expanded);
443 
444  if (expanded && expanded != data) {
445  free(expanded);
446  }
447 
448 }
#define switch_core_session_execute_application(_a, _b, _c)
Execute an application on a session.
Definition: switch_core.h:1103
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
#define switch_channel_expand_variables(_channel, _in)
#define switch_core_session_strdup(_session, _todup)
Copy a string using memory allocation from a session's pool.
Definition: switch_core.h:717
static switch_bool_t is_valid_action ( const char *  action)
static

Definition at line 785 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().

786 {
787  int i;
788 
789  if (!zstr(action)) {
790  for (i = 0;; i++) {
791  if (!iam[i].name) {
792  break;
793  }
794 
795  if (!strcmp(iam[i].name, action)) {
796  return SWITCH_TRUE;
797  }
798  }
799  }
800 
801  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid Action [%s]\n", switch_str_nil(action));
802  return SWITCH_FALSE;
803 }
#define SWITCH_CHANNEL_LOG
#define zstr(x)
Definition: switch_utils.h:281
#define switch_str_nil(s)
Make a null string a blank string instead.
Definition: switch_utils.h:903
static struct iam_s iam[]
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
static void ivr_send_event ( switch_core_session_t session,
char *  event_type,
switch_ivr_menu_t menu 
)
static

Definition at line 81 of file switch_ivr_menu.c.

References switch_ivr_menu::name, switch_channel_event_set_data(), switch_core_session_get_channel(), switch_event_add_header_string(), switch_event_create_subclass, SWITCH_EVENT_CUSTOM, switch_event_fire, SWITCH_STACK_BOTTOM, and SWITCH_STATUS_SUCCESS.

Referenced by switch_ivr_menu_execute().

82 {
84  switch_event_t *event = NULL;
86  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Menu-Name", menu->name);
87  switch_channel_event_set_data(channel, event);
88  switch_event_fire(&event);
89  }
90 }
#define switch_event_fire(event)
Fire an event filling in most of the arguements with obvious values.
Definition: switch_event.h:412
void switch_channel_event_set_data(_In_ switch_channel_t *channel, _In_ switch_event_t *event)
Add information about a given channel to an event object.
Representation of an event.
Definition: switch_event.h:80
#define switch_event_create_subclass(_e, _eid, _sn)
Definition: switch_event.h:153
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
switch_status_t switch_event_add_header_string(switch_event_t *event, switch_stack_t stack, const char *header_name, const char *data)
Add a string header to an event.
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 326 of file switch_ivr_menu.c.

References switch_ivr_menu::buf, buf, switch_input_args_t::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, memset(), 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().

327 {
328  char terminator;
329  uint32_t len;
330  char *ptr;
332  switch_input_args_t args = { 0 };
333  switch_channel_t *channel;
334  char *sound_expanded = sound;
335  switch_size_t menu_buf_len = 0;
336  const char *terminator_str = "#";
337 
338  if (!session || !menu || zstr(sound)) {
339  return status;
340  }
341 
342  if ((channel = switch_core_session_get_channel(session))) {
343  const char *tmp;
344  sound_expanded = switch_channel_expand_variables(channel, sound);
345  if ((tmp = switch_channel_get_variable(channel, "ivr_menu_terminator")) && !zstr(tmp)) {
346  terminator_str = tmp;
347  }
348  }
349 
350  memset(menu->buf, 0, menu->inlen + 1);
351  menu->ptr = menu->buf;
352 
353  if (!need) {
354  len = 1;
355  ptr = NULL;
356  } else {
357  len = (uint32_t) menu->inlen + 1;
358  ptr = menu->ptr;
359  }
360  args.buf = ptr;
361  args.buflen = len;
362 
363  status = switch_ivr_play_file(session, NULL, sound_expanded, &args);
364 
365  if (sound_expanded != sound) {
366  switch_safe_free(sound_expanded);
367  }
368 
369  if (!need) {
370  return status;
371  }
372 
373  menu_buf_len = strlen(menu->buf);
374 
375  menu->ptr += menu_buf_len;
376  if (menu_buf_len < need) {
377  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "waiting for %u/%u digits t/o %d\n",
378  (uint32_t) (menu->inlen - strlen(menu->buf)), (uint32_t) need, menu->inter_timeout);
379  status = switch_ivr_collect_digits_count(session, menu->ptr, menu->inlen - strlen(menu->buf),
380  need, terminator_str, &terminator, menu_buf_len ? menu->inter_timeout : menu->timeout,
381  menu->inter_timeout, menu->timeout);
382  }
383 
384  if (menu->confirm_macro && status == SWITCH_STATUS_SUCCESS && *menu->buf != '\0') {
385  switch_input_args_t confirm_args = { 0 }, *ap = NULL;
386  char buf[10] = "";
387  char terminator_key;
388  int att = menu->confirm_attempts;
389 
390  while (att) {
391  confirm_args.buf = buf;
392  confirm_args.buflen = sizeof(buf);
393  memset(buf, 0, confirm_args.buflen);
394 
395  if (menu->confirm_key) {
396  ap = &confirm_args;
397  }
398 
399  switch_ivr_phrase_macro(session, menu->confirm_macro, menu->buf, NULL, ap);
400 
401  if (menu->confirm_key && *buf == '\0') {
402  switch_ivr_collect_digits_count(session, buf, sizeof(buf), 1, terminator_str, &terminator_key, menu->timeout, 0, 0);
403  }
404 
405  if (menu->confirm_key && *buf != '\0') {
406  if (*menu->confirm_key == *buf) {
408  "approving digits '%s' via confirm key %s\n", menu->buf, menu->confirm_key);
409  break;
410  } else {
411  att = 0;
412  break;
413  }
414  }
415  att--;
416  }
417  if (!att) {
418  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "rejecting digits '%s' via confirm key %s\n", menu->buf,
419  menu->confirm_key);
420  *menu->buf = '\0';
421  }
422  }
423 
424  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "digits '%s'\n", menu->buf);
425 
426  return status;
427 }
#define SWITCH_CHANNEL_SESSION_LOG(x)
switch_status_t switch_ivr_play_file(switch_core_session_t *session, switch_file_handle_t *fh, const char *file, switch_input_args_t *args)
play a file from the disk to the session
#define zstr(x)
Definition: switch_utils.h:281
switch_size_t inlen
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
switch_status_t switch_ivr_collect_digits_count(switch_core_session_t *session, char *buf, switch_size_t buflen, switch_size_t maxdigits, const char *terminators, char *terminator, uint32_t first_timeout, uint32_t digit_timeout, uint32_t abs_timeout)
Wait for specified number of DTMF digits, untile terminator is received or until the channel hangs up...
Definition: switch_ivr.c:1287
switch_byte_t switch_byte_t * buf
#define switch_channel_get_variable(_c, _v)
#define switch_safe_free(it)
Free a pointer and set it to NULL unless it already is NULL.
Definition: switch_utils.h:789
uintptr_t switch_size_t
#define switch_channel_expand_variables(_channel, _in)
switch_status_t
Common return values.
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
#define switch_ivr_phrase_macro(session, macro_name, data, lang, args)
Definition: switch_ivr.h:903
memset(buf, 0, buflen)
static switch_ivr_menu_t* switch_ivr_menu_find ( switch_ivr_menu_t stack,
const char *  name 
)
static

Definition at line 92 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().

93 {
94  switch_ivr_menu_t *ret;
95  for (ret = stack; ret; ret = ret->next) {
96  if (!name || !strcmp(ret->name, name))
97  break;
98  }
99  return ret;
100 }
struct switch_ivr_menu * next
static void switch_ivr_menu_stack_add ( switch_ivr_menu_t **  top,
switch_ivr_menu_t bottom 
)
static

Definition at line 102 of file switch_ivr_menu.c.

References switch_ivr_menu::next.

Referenced by switch_ivr_menu_init().

103 {
104  switch_ivr_menu_t *ptr;
105 
106  for (ptr = *top; ptr && ptr->next; ptr = ptr->next);
107 
108  if (ptr) {
109  ptr->next = bottom;
110  } else {
111  *top = bottom;
112  }
113 
114 }
struct switch_ivr_menu * next
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 717 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().

719 {
721 
722  /* if this action/function does not exist yet */
723  if (xml_ctx != NULL && name != NULL && xml_ctx->pool != NULL && switch_ivr_menu_stack_xml_find(xml_ctx, name) == NULL) {
725 
726  if (map != NULL) {
727  map->name = switch_core_strdup(xml_ctx->pool, name);
728  map->action = action;
729  map->function = function;
730 
731  if (map->name != NULL) {
732  /* insert map item at top of list */
733  map->next = xml_ctx->map;
734  xml_ctx->map = map;
735  status = SWITCH_STATUS_SUCCESS;
736  } else {
737  status = SWITCH_STATUS_MEMERR;
738  }
739  } else {
740  status = SWITCH_STATUS_MEMERR;
741  }
742 
743  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "switch_ivr_menu_stack_xml_add binding '%s'\n", name);
744  } else {
745  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to add binding %s\n", name);
746  }
747 
748  return status;
749 }
#define SWITCH_CHANNEL_LOG
#define switch_core_strdup(_pool, _todup)
Copy a string using memory allocation from a given pool.
Definition: switch_core.h:729
static switch_ivr_menu_xml_map_t * switch_ivr_menu_stack_xml_find(switch_ivr_menu_xml_ctx_t *xml_ctx, const char *name)
#define switch_core_alloc(_pool, _mem)
Allocate memory directly from a memory pool.
Definition: switch_core.h:682
switch_memory_pool_t * pool
struct switch_ivr_menu_xml_map * next
switch_status_t
Common return values.
switch_ivr_menu_action_function_t * function
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
struct switch_ivr_menu_xml_map * map
switch_ivr_action_t action
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 705 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().

706 {
707  switch_ivr_menu_xml_map_t *map = (xml_ctx != NULL ? xml_ctx->map : NULL);
708  int rc = -1;
709 
710  while (map != NULL && (rc = strcasecmp(map->name, name)) != 0) {
711  map = map->next;
712  }
713 
714  return (rc == 0 ? map : NULL);
715 }
struct switch_ivr_menu_xml_map * next
struct switch_ivr_menu_xml_map * map

Variable Documentation

struct iam_s iam[]
static