RTS API Documentation  1.10.11
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

◆ MENU_EVENT_ENTER

#define MENU_EVENT_ENTER   "menu::enter"

Definition at line 78 of file switch_ivr_menu.c.

Referenced by switch_ivr_menu_execute().

◆ MENU_EVENT_EXIT

#define MENU_EVENT_EXIT   "menu::exit"

Definition at line 79 of file switch_ivr_menu.c.

Referenced by switch_ivr_menu_execute().

Typedef Documentation

◆ switch_ivr_menu_xml_map_t

Function Documentation

◆ exec_app()

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

Definition at line 430 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(), record_callback(), send_record_stop_event(), and switch_ivr_menu_execute().

431 {
433  char *app = switch_core_session_strdup(session, app_str);
434  char *data = strchr(app, ' ');
435  char *expanded = NULL;
436 
437  if (data) {
438  *data++ = '\0';
439  }
440 
441  expanded = switch_channel_expand_variables(channel, data);
442 
443  switch_core_session_execute_application(session, app, expanded);
444 
445  if (expanded && expanded != data) {
446  free(expanded);
447  }
448 
449 }
#define switch_core_session_execute_application(_a, _b, _c)
Execute an application on a session.
Definition: switch_core.h:1129
_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&#39;s pool.
Definition: switch_core.h:719

◆ is_valid_action()

static switch_bool_t is_valid_action ( const char *  action)
static

Definition at line 788 of file switch_ivr_menu.c.

References iam, switch_ivr_menu::name, 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().

789 {
790  int i;
791 
792  if (!zstr(action)) {
793  for (i = 0;; i++) {
794  if (!iam[i].name) {
795  break;
796  }
797 
798  if (!strcmp(iam[i].name, action)) {
799  return SWITCH_TRUE;
800  }
801  }
802  }
803 
804  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid Action [%s]\n", switch_str_nil(action));
805  return SWITCH_FALSE;
806 }
#define SWITCH_CHANNEL_LOG
#define zstr(x)
Definition: switch_utils.h:314
#define switch_str_nil(s)
Make a null string a blank string instead.
Definition: switch_utils.h:993
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.
const char *const name
Definition: switch_cJSON.h:250

◆ ivr_send_event()

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:413
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.

◆ play_and_collect()

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 327 of file switch_ivr_menu.c.

References switch_ivr_menu::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().

328 {
329  char terminator;
330  uint32_t len;
331  char *ptr;
333  switch_input_args_t args = { 0 };
334  switch_channel_t *channel;
335  char *sound_expanded = sound;
336  switch_size_t menu_buf_len = 0;
337  const char *terminator_str = "#";
338 
339  if (!session || !menu || zstr(sound)) {
340  return status;
341  }
342 
343  if ((channel = switch_core_session_get_channel(session))) {
344  const char *tmp;
345  sound_expanded = switch_channel_expand_variables(channel, sound);
346  if ((tmp = switch_channel_get_variable(channel, "ivr_menu_terminator")) && !zstr(tmp)) {
347  terminator_str = tmp;
348  }
349  }
350 
351  memset(menu->buf, 0, menu->inlen + 1);
352  menu->ptr = menu->buf;
353 
354  if (!need) {
355  len = 1;
356  ptr = NULL;
357  } else {
358  len = (uint32_t) menu->inlen + 1;
359  ptr = menu->ptr;
360  }
361  args.buf = ptr;
362  args.buflen = len;
363 
364  status = switch_ivr_play_file(session, NULL, sound_expanded, &args);
365 
366  if (sound_expanded != sound) {
367  switch_safe_free(sound_expanded);
368  }
369 
370  if (!need) {
371  return status;
372  }
373 
374  menu_buf_len = strlen(menu->buf);
375 
376  menu->ptr += menu_buf_len;
377  if (menu_buf_len < need) {
378  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "waiting for %u/%u digits t/o %d\n",
379  (uint32_t) (menu->inlen - strlen(menu->buf)), (uint32_t) need, menu->inter_timeout);
380  status = switch_ivr_collect_digits_count(session, menu->ptr, menu->inlen - strlen(menu->buf),
381  need, terminator_str, &terminator, menu_buf_len ? menu->inter_timeout : menu->timeout,
382  menu->inter_timeout, menu->timeout);
383  }
384 
385  if (menu->confirm_macro && status == SWITCH_STATUS_SUCCESS && *menu->buf != '\0') {
386  switch_input_args_t confirm_args = { 0 }, *ap = NULL;
387  char buf[10] = "";
388  char terminator_key;
389  int att = menu->confirm_attempts;
390 
391  while (att) {
392  confirm_args.buf = buf;
393  confirm_args.buflen = sizeof(buf);
394  memset(buf, 0, confirm_args.buflen);
395 
396  if (menu->confirm_key) {
397  ap = &confirm_args;
398  }
399 
400  switch_ivr_phrase_macro(session, menu->confirm_macro, menu->buf, NULL, ap);
401 
402  if (menu->confirm_key && *buf == '\0') {
403  switch_ivr_collect_digits_count(session, buf, sizeof(buf), 1, terminator_str, &terminator_key, menu->timeout, 0, 0);
404  }
405 
406  if (menu->confirm_key && *buf != '\0') {
407  if (*menu->confirm_key == *buf) {
409  "approving digits '%s' via confirm key %s\n", menu->buf, menu->confirm_key);
410  break;
411  } else {
412  att = 0;
413  break;
414  }
415  }
416  att--;
417  }
418  if (!att) {
419  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "rejecting digits '%s' via confirm key %s\n", menu->buf,
420  menu->confirm_key);
421  *menu->buf = '\0';
422  }
423  }
424 
425  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "digits '%s'\n", menu->buf);
426 
427  return status;
428 }
#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:314
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:1342
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:885
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:936
memset(buf, 0, buflen)

◆ switch_ivr_menu_find()

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 }
const char *const name
Definition: switch_cJSON.h:250
struct switch_ivr_menu * next

◆ switch_ivr_menu_stack_add()

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, and switch_ivr_menu::ptr.

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

◆ switch_ivr_menu_stack_xml_add()

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 720 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().

722 {
724 
725  /* if this action/function does not exist yet */
726  if (xml_ctx != NULL && name != NULL && xml_ctx->pool != NULL && switch_ivr_menu_stack_xml_find(xml_ctx, name) == NULL) {
728 
729  if (map != NULL) {
730  map->name = switch_core_strdup(xml_ctx->pool, name);
731  map->action = action;
732  map->function = function;
733 
734  if (map->name != NULL) {
735  /* insert map item at top of list */
736  map->next = xml_ctx->map;
737  xml_ctx->map = map;
738  status = SWITCH_STATUS_SUCCESS;
739  } else {
740  status = SWITCH_STATUS_MEMERR;
741  }
742  } else {
743  status = SWITCH_STATUS_MEMERR;
744  }
745 
746  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "switch_ivr_menu_stack_xml_add binding '%s'\n", name);
747  } else {
748  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to add binding %s\n", name);
749  }
750 
751  return status;
752 }
#define SWITCH_CHANNEL_LOG
#define switch_core_strdup(_pool, _todup)
Copy a string using memory allocation from a given pool.
Definition: switch_core.h:733
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:684
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.
const char *const name
Definition: switch_cJSON.h:250
struct switch_ivr_menu_xml_map * map
switch_ivr_action_t action

◆ switch_ivr_menu_stack_xml_find()

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 708 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().

709 {
710  switch_ivr_menu_xml_map_t *map = (xml_ctx != NULL ? xml_ctx->map : NULL);
711  int rc = -1;
712 
713  while (map != NULL && (rc = strcasecmp(map->name, name)) != 0) {
714  map = map->next;
715  }
716 
717  return (rc == 0 ? map : NULL);
718 }
struct switch_ivr_menu_xml_map * next
const char *const name
Definition: switch_cJSON.h:250
struct switch_ivr_menu_xml_map * map

Variable Documentation

◆ iam

struct iam_s iam[]
static