[Freeswitch-svn] [commit] r3873 - freeswitch/branches/knhor/trunk/src/mod/applications/mod_conference
Freeswitch SVN
knhor at freeswitch.org
Sat Dec 30 15:04:41 EST 2006
Author: knhor
Date: Sat Dec 30 15:04:41 2006
New Revision: 3873
Modified:
freeswitch/branches/knhor/trunk/src/mod/applications/mod_conference/mod_conference.c
Log:
move caller control digit parser from the conference to the caller
Modified: freeswitch/branches/knhor/trunk/src/mod/applications/mod_conference/mod_conference.c
==============================================================================
--- freeswitch/branches/knhor/trunk/src/mod/applications/mod_conference/mod_conference.c (original)
+++ freeswitch/branches/knhor/trunk/src/mod/applications/mod_conference/mod_conference.c Sat Dec 30 15:04:41 2006
@@ -55,7 +55,7 @@
//#define OPTION_IVR_MENU_SUPPORT */
/* define this if you want your xmpp users to be able to admin the conferences via chat */
-//#define ENABLE_CHAT_ADMIN
+#define ENABLE_CHAT_ADMIN
typedef enum {
FILE_STOP_CURRENT,
@@ -178,12 +178,12 @@
char *kicked_sound;
char *caller_id_name;
char *caller_id_number;
- switch_ivr_digit_stream_parser_t *dtmf_parser;
char *pin;
char *pin_sound;
char *bad_pin_sound;
char *profile_name;
char *domain;
+ char *caller_controls;
uint32_t flags;
switch_call_cause_t bridge_hangup_cause;
switch_mutex_t *flag_mutex;
@@ -198,6 +198,7 @@
uint32_t count;
int32_t energy_level;
uint8_t min;
+ conf_xml_cfg_t xml_cfg;
// switch_hash_t *chat_admin;
// switch_hash_t *chat_id;
} conference_obj_t;
@@ -239,6 +240,7 @@
switch_audio_resampler_t *read_resampler;
conference_file_node_t *fnode;
conference_relationship_t *relationships;
+ switch_ivr_digit_stream_parser_t *dtmf_parser;
switch_ivr_digit_stream_t *digit_stream;
struct conference_member *next;
};
@@ -295,7 +297,7 @@
static switch_status_t conference_member_play_file(conference_member_t *member, char *file, uint32_t leadin);
static switch_status_t conference_member_say(conference_member_t *member, char *text, uint32_t leadin);
static uint32_t conference_member_stop_file(conference_member_t *member, file_stop_t stop);
-static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_memory_pool_t *pool);
+static conference_obj_t *conference_new(char *name, conf_xml_cfg_t *xml_cfg, switch_memory_pool_t *pool);
static switch_status_t chat_send(char *proto, char *from, char *to, char *subject, char *body, char *hint);
static void launch_conference_record_thread(conference_obj_t *conference, char *path);
@@ -885,8 +887,6 @@
switch_thread_rwlock_unlock(conference->rwlock);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Write Lock OFF\n");
- switch_ivr_digit_stream_parser_destroy(conference->dtmf_parser);
-
if (conference->pool) {
switch_memory_pool_t *pool = conference->pool;
switch_core_destroy_memory_pool(&pool);
@@ -1389,6 +1389,256 @@
};
#define CCFNTBL_QTY (sizeof(ccfntbl)/sizeof(ccfntbl[0]))
+#ifdef OPTION_IVR_MENU_SUPPORT
+static switch_ivr_action_t caller_control_ivr_handler(switch_ivr_menu_t *menu, char *param, char *buf, size_t buflen, void *obj)
+{
+ switch_ivr_action_t action = SWITCH_IVR_ACTION_NOOP;
+
+ if (!switch_strlen_zero(param)) {
+ if (obj != NULL) {
+ int i, found;
+ char *action_name = strdup(param);
+
+ if (action_name != NULL) {
+ char *sep = (action_name != NULL ? strchr(action_name, ' ') : NULL);
+
+ /* split the action from any parameters */
+ if (sep != NULL) {
+ *sep = '\0';
+ }
+
+ /* find and execute the caller control handler */
+ for(i = 0, found = 0; !found && i<CCFNTBL_QTY; i++) {
+ found = (ccfntbl[i].action != CALLER_CONTROL_MENU && strcasecmp(ccfntbl[i].key, action_name) == 0);
+ if (found) {
+ if (obj != NULL) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "invoking caller control menu action '%s'\n", ccfntbl[i].key);
+ ccfntbl[i].handler((conference_member_t *)obj, (sep != NULL ? sep+1 : NULL));
+ if (ccfntbl[i].action == CALLER_CONTROL_HANGUP) {
+ action = SWITCH_IVR_ACTION_DIE;
+ }
+ }
+ }
+ }
+
+ free(action_name);
+ }
+
+ if (!found) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "unknown caller control menu action '%s'\n", param);
+ }
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "unable to invoke caller control menu action '%s', NULL member!\n", param);
+ }
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "NULL or empty param!\n");
+ }
+
+ return action;
+}
+
+/*
+ static switch_status_t ivr_menu_callback_play_file(char *file, uint32_t leadin, void *member)
+ {
+ switch_status_t status;
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "ivr_menu_callback_play_file\n");
+ status = conference_member_play_file((conference_member_t *)member, file, leadin);
+ if (status != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ivr_menu_callback_play_file ERROR\n");
+ }
+
+ return status;
+ }
+
+ static switch_status_t ivr_menu_callback_say(char *file, uint32_t leadin, void *member)
+ {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "ivr_menu_callback_say\n");
+ return conference_member_say((conference_member_t *)member, file, leadin);
+ }
+*/
+
+static switch_status_t caller_control_ivr_build(caller_control_menu_ctx_t **ctx,
+ conference_obj_t *conference,
+ switch_xml_t menu_group,
+ char *menu_name)
+{
+ switch_status_t status = SWITCH_STATUS_FALSE;
+ switch_xml_t xml_menus;
+ switch_xml_t xml_menu;
+
+ assert(conference != NULL);
+ assert(ctx != NULL);
+ assert(menu_group != NULL);
+ assert(menu_name != NULL);
+ assert(xml_menus != NULL);
+
+ xml_menus = switch_xml_child(menu_group, "menus");
+ xml_menu = (xml_menus != NULL ? switch_xml_find_child(xml_menus, "menu", "name", menu_name) : NULL);
+
+
+
+ /* if we found the requested menu in our menu_group */
+ if (xml_menu != NULL && xml_menu != NULL) {
+ *ctx = (caller_control_menu_ctx_t *)switch_core_alloc(conference->pool, sizeof(caller_control_menu_ctx_t));
+
+ if (*ctx != NULL) {
+ memset(*ctx, 0, sizeof(caller_control_menu_ctx_t));
+
+ /* setup an xml parser context, and a menu stack context for the specified menu in our memory pool */
+ status = switch_ivr_menu_stack_xml_init(&(*ctx)->xml_ctx, conference->pool);
+ if (status == SWITCH_STATUS_SUCCESS) {
+ (*ctx)->name = switch_core_strdup(conference->pool, menu_name);
+
+ /* add our xml menu handler to the xml stack parser */
+ status = switch_ivr_menu_stack_xml_add_custom((*ctx)->xml_ctx, "control", &caller_control_ivr_handler);
+ if (status != SWITCH_STATUS_SUCCESS)
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "unable to add custom xml handler\n");
+
+ /* parse the xml stack to build the menu stack */
+ status = switch_ivr_menu_stack_xml_build((*ctx)->xml_ctx, &(*ctx)->menu_stack, xml_menus, xml_menu, conference->timer_name);
+ if (status != SWITCH_STATUS_SUCCESS)
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "unable to build xml menu stack\n");
+
+ /*
+ // instruct ivr menu to use our file play and tts routines
+ status = switch_ivr_menu_set_fileplay_callback((*ctx)->menu_stack, &ivr_menu_callback_play_file);
+ if (status != SWITCH_STATUS_SUCCESS)
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "unable to set file play calback\n");
+ status = switch_ivr_menu_set_tts_callback((*ctx)->menu_stack, &ivr_menu_callback_say);
+ if (status != SWITCH_STATUS_SUCCESS)
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "unable to set tts calback\n");
+ */
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "unable to init xml menu context\n");
+ }
+ if (status != SWITCH_STATUS_SUCCESS)
+ *ctx = NULL;
+ }
+ } else {
+ if (xml_menus == NULL)
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "caller control menu unable to find xml menus\n");
+ if (xml_menu == NULL)
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "caller control menu unable to find xml menu '%s'\n", menu_name);
+ }
+
+ return status;
+}
+#endif
+
+static switch_status_t caller_control_build_default(conference_member_t *member)
+{
+ switch_status_t status = SWITCH_STATUS_FALSE;
+ uint32_t i;
+ caller_control_action_t *action;
+
+ assert(member != NULL);
+
+ for(i = 0, status = SWITCH_STATUS_SUCCESS; status == SWITCH_STATUS_SUCCESS && i<CCFNTBL_QTY; i++) {
+ if (!switch_strlen_zero(ccfntbl[i].digits)) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Installing default caller control action '%s' bound to '%s'.\n",
+ ccfntbl[i].key,
+ ccfntbl[i].digits);
+ action = (caller_control_action_t *)switch_core_alloc(member->pool, sizeof(caller_control_action_t));
+ if (action != NULL) {
+ action->fndesc = &ccfntbl[i];
+ action->data = NULL;
+ status = switch_ivr_digit_stream_parser_set_event(member->dtmf_parser, ccfntbl[i].digits, action);
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "unable to alloc memory for caller control binding '%s' to '%s'\n",
+ ccfntbl[i].key, ccfntbl[i].digits);
+ status = SWITCH_STATUS_MEMERR;
+ }
+ }
+ }
+
+
+ return status;
+}
+
+static switch_status_t caller_control_build_custom(conference_member_t *member, switch_xml_t xml_controls, switch_xml_t xml_menus)
+{
+ switch_status_t status = SWITCH_STATUS_FALSE;
+ switch_xml_t xml_kvp;
+
+ assert(member != NULL);
+ assert(xml_controls != NULL);
+
+ /* parse the controls tree for caller control digit strings */
+ for (xml_kvp = switch_xml_child(xml_controls, "control"); xml_kvp; xml_kvp = xml_kvp->next) {
+ char *key = (char *) switch_xml_attr(xml_kvp, "action");
+ char *val = (char *) switch_xml_attr(xml_kvp, "digits");
+ char *data = (char *)switch_xml_attr_soft(xml_kvp, "data");
+
+ if (!switch_strlen_zero(key) && !switch_strlen_zero(val)) {
+ uint32_t i;
+
+ /* scan through all of the valid actions, and if found, */
+ /* set the new caller control action digit string, then */
+ /* stop scanning the table, and go to the next xml kvp. */
+ for(i = 0, status = SWITCH_STATUS_NOOP; i<CCFNTBL_QTY && status == SWITCH_STATUS_NOOP; i++) {
+
+ if (strcasecmp(ccfntbl[i].key, key) == 0) {
+ status = SWITCH_STATUS_SUCCESS;
+#ifdef OPTION_IVR_MENU_SUPPORT
+ if (xml_menus != NULL && ccfntbl[i].action == CALLER_CONTROL_MENU) {
+ char *menu_group_name = strdup(data);
+ char *menu_name = (menu_group_name != NULL ? strchr(menu_group_name, '/') : NULL);
+
+ /* format: "menu_group_name/menu_name" */
+ /* separate the menu name from the menu group */
+ if (menu_name != NULL) {
+ *(menu_name++) = '\0';
+ }
+ /* if there is a menu name, build the menu */
+ if (menu_name != NULL) {
+ caller_control_menu_ctx_t *menu_ctx = NULL;
+ switch_xml_t menu_group = switch_xml_find_child(xml_menus, "group", "name", menu_group_name);
+
+ status = caller_control_ivr_build(&menu_ctx, conference, menu_group, menu_name);
+ data = (char *)menu_ctx;
+ } else {
+ status = SWITCH_STATUS_FALSE;
+ }
+
+ if (status != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "unable to build menu '%s' bound to '%s'\n", data, val);
+ }
+
+ /* clean up */
+ if (menu_group_name != NULL) {
+ free(menu_group_name);
+ }
+ }
+#endif
+
+ if (status == SWITCH_STATUS_SUCCESS) {
+ caller_control_action_t *action;
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Installing caller control action '%s' bound to '%s'.\n", key, val);
+ action = (caller_control_action_t *)switch_core_alloc(member->pool, sizeof(caller_control_action_t));
+ if (action != NULL) {
+ action->fndesc = &ccfntbl[i];
+ action->data = (void *)data;
+ status = switch_ivr_digit_stream_parser_set_event(member->dtmf_parser, val, action);
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "unable to alloc memory for caller control binding '%s' to '%s'\n", ccfntbl[i].key, ccfntbl[i].digits);
+ status = SWITCH_STATUS_MEMERR;
+ }
+ }
+ }
+ }
+ if (status == SWITCH_STATUS_NOOP) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid caller control action name '%s'.\n", key);
+ }
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid caller control config entry pair action = '%s' digits = '%s'\n", key, val);
+ }
+ }
+
+ return status;
+}
+
/* marshall frames from the conference (or file or tts output) to the call leg */
/* NB. this starts the input thread after some initial setup for the call leg */
static void conference_loop_output(conference_member_t *member)
@@ -1429,8 +1679,33 @@
/* Start the input thread */
launch_conference_loop_input(member, switch_core_session_get_pool(member->session));
+ /* caller control configuration chores */
+ if (switch_ivr_digit_stream_parser_new(member->pool, &member->dtmf_parser) == SWITCH_STATUS_SUCCESS) {
+ switch_status_t status = SWITCH_STATUS_FALSE;
+
+ /* if no controls, or default controls specified, install default */
+ if (member->conference->caller_controls == NULL || *member->conference->caller_controls == '\0' || strcasecmp(member->conference->caller_controls, "default") == 0) {
+ status = caller_control_build_default(member);
+ } else if (strcasecmp(member->conference->caller_controls, "none") != 0) {
+ /* try to build caller control if the group has been specified and != "none" */
+ switch_xml_t xml_controls = switch_xml_find_child(member->conference->xml_cfg.controls, "group", "name", member->conference->caller_controls);
+#ifdef OPTION_IVR_MENU_SUPPORT
+ status = caller_control_build_custom(member, xml_controls, member->conference->xml_cfg.menus);
+#else
+ status = caller_control_build_custom(member, xml_controls, NULL);
+#endif
+ if (status != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to install caller controls group '%s'\n", member->conference->caller_controls);
+ }
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "no caller controls intalled.\n");
+ }
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to allocate caller control digit parser.\n");
+ }
+
/* build a digit stream object */
- if (member->conference->dtmf_parser != NULL && switch_ivr_digit_stream_new(member->conference->dtmf_parser, &member->digit_stream) != SWITCH_STATUS_SUCCESS) {
+ if (member->dtmf_parser != NULL && switch_ivr_digit_stream_new(member->dtmf_parser, &member->digit_stream) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Warning Will Robinson, there is no digit parser stream object\n");
}
@@ -1482,15 +1757,15 @@
if (switch_channel_has_dtmf(channel)) {
switch_channel_dequeue_dtmf(channel, dtmf, sizeof(dtmf));
- if (member->conference->dtmf_parser != NULL) {
+ if (member->dtmf_parser != NULL) {
for (digit = dtmf; *digit && caller_action == NULL; digit++) {
- caller_action = (caller_control_action_t *)switch_ivr_digit_stream_parser_feed(member->conference->dtmf_parser, member->digit_stream, *digit);
+ caller_action = (caller_control_action_t *)switch_ivr_digit_stream_parser_feed(member->dtmf_parser, member->digit_stream, *digit);
}
}
/* otherwise, clock the parser so that it can handle digit timeout detection */
- } else if (member->conference->dtmf_parser != NULL) {
- caller_action = (caller_control_action_t *)switch_ivr_digit_stream_parser_feed(member->conference->dtmf_parser, member->digit_stream, '\0');
+ } else if (member->dtmf_parser != NULL) {
+ caller_action = (caller_control_action_t *)switch_ivr_digit_stream_parser_feed(member->dtmf_parser, member->digit_stream, '\0');
}
/* if a caller action has been detected, handle it */
@@ -1618,6 +1893,10 @@
switch_ivr_digit_stream_destroy(member->digit_stream);
}
+ if (member->dtmf_parser != NULL) {
+ switch_ivr_digit_stream_parser_destroy(member->dtmf_parser);
+ }
+
switch_clear_flag_locked(member, MFLAG_RUNNING);
switch_core_timer_destroy(&timer);
@@ -2888,18 +3167,17 @@
}
/* Create the conference object. */
- new_conference = conference_new(conf_name, xml_cfg, pool);
-
- /* Release the config registry handle */
- if (xml_cfg.cxml) {
- switch_xml_free(xml_cfg.cxml);
- }
+ new_conference = conference_new(conf_name, &xml_cfg, pool);
if (!new_conference) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n");
if (pool != NULL) {
switch_core_destroy_memory_pool(&pool);
}
+ /* Release the config registry handle */
+ if (xml_cfg.cxml) {
+ switch_xml_free(xml_cfg.cxml);
+ }
goto done;
}
@@ -3454,7 +3732,7 @@
}
/* Create the conference object. */
- conference = conference_new(conf_name, xml_cfg, pool);
+ conference = conference_new(conf_name, &xml_cfg, pool);
if (!conference) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n");
@@ -3481,7 +3759,7 @@
freepool = pool;
/* couldn't find the conference, create one */
} else {
- conference = conference_new(conf_name, xml_cfg, pool);
+ conference = conference_new(conf_name, &xml_cfg, pool);
if (!conference) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n");
@@ -3568,12 +3846,6 @@
}
}
- /* Release the config registry handle */
- if (xml_cfg.cxml) {
- switch_xml_free(xml_cfg.cxml);
- xml_cfg.cxml = NULL;
- }
-
/* if we're using "bridge:" make an outbound call and bridge it in */
if (!switch_strlen_zero(bridgeto) && strcasecmp(bridgeto, "none")) {
if (conference_outcall(conference, session, bridgeto, 60, NULL, NULL, NULL) != SWITCH_STATUS_SUCCESS) {
@@ -3875,258 +4147,8 @@
/*.chat_interface */ &conference_chat_interface
};
-#ifdef OPTION_IVR_MENU_SUPPORT
-static switch_ivr_action_t conference_caller_control_menu_handler(switch_ivr_menu_t *menu, char *param, char *buf, size_t buflen, void *obj)
-{
- switch_ivr_action_t action = SWITCH_IVR_ACTION_NOOP;
-
- if (!switch_strlen_zero(param)) {
- if (obj != NULL) {
- int i, found;
- char *action_name = strdup(param);
-
- if (action_name != NULL) {
- char *sep = (action_name != NULL ? strchr(action_name, ' ') : NULL);
-
- /* split the action from any parameters */
- if (sep != NULL) {
- *sep = '\0';
- }
-
- /* find and execute the caller control handler */
- for(i = 0, found = 0; !found && i<CCFNTBL_QTY; i++) {
- found = (ccfntbl[i].action != CALLER_CONTROL_MENU && strcasecmp(ccfntbl[i].key, action_name) == 0);
- if (found) {
- if (obj != NULL) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "invoking caller control menu action '%s'\n", ccfntbl[i].key);
- ccfntbl[i].handler((conference_member_t *)obj, (sep != NULL ? sep+1 : NULL));
- if (ccfntbl[i].action == CALLER_CONTROL_HANGUP) {
- action = SWITCH_IVR_ACTION_DIE;
- }
- }
- }
- }
-
- free(action_name);
- }
-
- if (!found) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "unknown caller control menu action '%s'\n", param);
- }
- } else {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "unable to invoke caller control menu action '%s', NULL member!\n", param);
- }
- } else {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "NULL or empty param!\n");
- }
-
- return action;
-}
-
-/*
- static switch_status_t ivr_menu_callback_play_file(char *file, uint32_t leadin, void *member)
- {
- switch_status_t status;
-
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "ivr_menu_callback_play_file\n");
- status = conference_member_play_file((conference_member_t *)member, file, leadin);
- if (status != SWITCH_STATUS_SUCCESS) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ivr_menu_callback_play_file ERROR\n");
- }
-
- return status;
- }
-
- static switch_status_t ivr_menu_callback_say(char *file, uint32_t leadin, void *member)
- {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "ivr_menu_callback_say\n");
- return conference_member_say((conference_member_t *)member, file, leadin);
- }
-*/
-
-static switch_status_t conference_caller_control_menu_build(caller_control_menu_ctx_t **ctx,
- conference_obj_t *conference,
- switch_xml_t menu_group,
- char *menu_name)
-{
- switch_status_t status = SWITCH_STATUS_FALSE;
- switch_xml_t xml_menus;
- switch_xml_t xml_menu;
-
- assert(conference != NULL);
- assert(ctx != NULL);
- assert(menu_group != NULL);
- assert(menu_name != NULL);
- assert(xml_menus != NULL);
-
- xml_menus = switch_xml_child(menu_group, "menus");
- xml_menu = (xml_menus != NULL ? switch_xml_find_child(xml_menus, "menu", "name", menu_name) : NULL);
-
-
-
- /* if we found the requested menu in our menu_group */
- if (xml_menu != NULL && xml_menu != NULL) {
- *ctx = (caller_control_menu_ctx_t *)switch_core_alloc(conference->pool, sizeof(caller_control_menu_ctx_t));
-
- if (*ctx != NULL) {
- memset(*ctx, 0, sizeof(caller_control_menu_ctx_t));
-
- /* setup an xml parser context, and a menu stack context for the specified menu in our memory pool */
- status = switch_ivr_menu_stack_xml_init(&(*ctx)->xml_ctx, conference->pool);
- if (status == SWITCH_STATUS_SUCCESS) {
- (*ctx)->name = switch_core_strdup(conference->pool, menu_name);
-
- /* add our xml menu handler to the xml stack parser */
- status = switch_ivr_menu_stack_xml_add_custom((*ctx)->xml_ctx, "control", &conference_caller_control_menu_handler);
- if (status != SWITCH_STATUS_SUCCESS)
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "unable to add custom xml handler\n");
-
- /* parse the xml stack to build the menu stack */
- status = switch_ivr_menu_stack_xml_build((*ctx)->xml_ctx, &(*ctx)->menu_stack, xml_menus, xml_menu, conference->timer_name);
- if (status != SWITCH_STATUS_SUCCESS)
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "unable to build xml menu stack\n");
-
- /*
- // instruct ivr menu to use our file play and tts routines
- status = switch_ivr_menu_set_fileplay_callback((*ctx)->menu_stack, &ivr_menu_callback_play_file);
- if (status != SWITCH_STATUS_SUCCESS)
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "unable to set file play calback\n");
- status = switch_ivr_menu_set_tts_callback((*ctx)->menu_stack, &ivr_menu_callback_say);
- if (status != SWITCH_STATUS_SUCCESS)
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "unable to set tts calback\n");
- */
- } else {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "unable to init xml menu context\n");
- }
- if (status != SWITCH_STATUS_SUCCESS)
- *ctx = NULL;
- }
- } else {
- if (xml_menus == NULL)
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "caller control menu unable to find xml menus\n");
- if (xml_menu == NULL)
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "caller control menu unable to find xml menu '%s'\n", menu_name);
- }
-
- return status;
-}
-#endif
-
-static switch_status_t conf_default_controls(conference_obj_t *conference)
-{
- switch_status_t status = SWITCH_STATUS_FALSE;
- uint32_t i;
- caller_control_action_t *action;
-
- assert(conference != NULL);
-
- for(i = 0, status = SWITCH_STATUS_SUCCESS; status == SWITCH_STATUS_SUCCESS && i<CCFNTBL_QTY; i++) {
- if (!switch_strlen_zero(ccfntbl[i].digits)) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Installing default caller control action '%s' bound to '%s'.\n",
- ccfntbl[i].key,
- ccfntbl[i].digits);
- action = (caller_control_action_t *)switch_core_alloc(conference->pool, sizeof(caller_control_action_t));
- if (action != NULL) {
- action->fndesc = &ccfntbl[i];
- action->data = NULL;
- status = switch_ivr_digit_stream_parser_set_event(conference->dtmf_parser, ccfntbl[i].digits, action);
- } else {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "unable to alloc memory for caller control binding '%s' to '%s'\n",
- ccfntbl[i].key, ccfntbl[i].digits);
- status = SWITCH_STATUS_MEMERR;
- }
- }
- }
-
-
- return status;
-}
-
-static switch_status_t conference_new_install_caller_controls_custom(conference_obj_t *conference, switch_xml_t xml_controls, switch_xml_t xml_menus)
-{
- switch_status_t status = SWITCH_STATUS_FALSE;
- switch_xml_t xml_kvp;
-
- assert(conference != NULL);
- assert(xml_controls != NULL);
-
- /* parse the controls tree for caller control digit strings */
- for (xml_kvp = switch_xml_child(xml_controls, "control"); xml_kvp; xml_kvp = xml_kvp->next) {
- char *key = (char *) switch_xml_attr(xml_kvp, "action");
- char *val = (char *) switch_xml_attr(xml_kvp, "digits");
- char *data = (char *)switch_xml_attr_soft(xml_kvp, "data");
-
- if (!switch_strlen_zero(key) && !switch_strlen_zero(val)) {
- uint32_t i;
-
- /* scan through all of the valid actions, and if found, */
- /* set the new caller control action digit string, then */
- /* stop scanning the table, and go to the next xml kvp. */
- for(i = 0, status = SWITCH_STATUS_NOOP; i<CCFNTBL_QTY && status == SWITCH_STATUS_NOOP; i++) {
-
- if (strcasecmp(ccfntbl[i].key, key) == 0) {
- status = SWITCH_STATUS_SUCCESS;
-#ifdef OPTION_IVR_MENU_SUPPORT
- if (xml_menus != NULL && ccfntbl[i].action == CALLER_CONTROL_MENU) {
- char *menu_group_name = strdup(data);
- char *menu_name = (menu_group_name != NULL ? strchr(menu_group_name, '/') : NULL);
-
- /* format: "menu_group_name/menu_name" */
- /* separate the menu name from the menu group */
- if (menu_name != NULL) {
- *(menu_name++) = '\0';
- }
- /* if there is a menu name, build the menu */
- if (menu_name != NULL) {
- caller_control_menu_ctx_t *menu_ctx = NULL;
- switch_xml_t menu_group = switch_xml_find_child(xml_menus, "group", "name", menu_group_name);
-
- status = conference_caller_control_menu_build(&menu_ctx, conference, menu_group, menu_name);
- data = (char *)menu_ctx;
- } else {
- status = SWITCH_STATUS_FALSE;
- }
-
- if (status != SWITCH_STATUS_SUCCESS) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "unable to build menu '%s' bound to '%s'\n", data, val);
- }
-
- /* clean up */
- if (menu_group_name != NULL) {
- free(menu_group_name);
- }
- }
-#endif
-
- if (status == SWITCH_STATUS_SUCCESS) {
- caller_control_action_t *action;
-
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Installing caller control action '%s' bound to '%s'.\n", key, val);
- action = (caller_control_action_t *)switch_core_alloc(conference->pool, sizeof(caller_control_action_t));
- if (action != NULL) {
- action->fndesc = &ccfntbl[i];
- action->data = (void *)data;
- status = switch_ivr_digit_stream_parser_set_event(conference->dtmf_parser, val, action);
- } else {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "unable to alloc memory for caller control binding '%s' to '%s'\n", ccfntbl[i].key, ccfntbl[i].digits);
- status = SWITCH_STATUS_MEMERR;
- }
- }
- }
- }
- if (status == SWITCH_STATUS_NOOP) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid caller control action name '%s'.\n", key);
- }
- } else {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid caller control config entry pair action = '%s' digits = '%s'\n", key, val);
- }
- }
-
- return status;
-}
-
/* create a new conferene with a specific profile */
-static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_memory_pool_t *pool)
+static conference_obj_t *conference_new(char *name, conf_xml_cfg_t *xml_cfg, switch_memory_pool_t *pool)
{
conference_obj_t *conference;
switch_xml_t xml_kvp;
@@ -4162,7 +4184,7 @@
}
/* parse the profile tree for param values */
- for (xml_kvp = switch_xml_child(cfg.profile, "param"); xml_kvp; xml_kvp = xml_kvp->next) {
+ for (xml_kvp = switch_xml_child(xml_cfg->profile, "param"); xml_kvp; xml_kvp = xml_kvp->next) {
char *var = (char *) switch_xml_attr_soft(xml_kvp, "name");
char *val = (char *) switch_xml_attr_soft(xml_kvp, "value");
char buf[128] = "";
@@ -4335,6 +4357,10 @@
conference->energy_level = atoi(energy_level);
}
+ if (!switch_strlen_zero(caller_controls)) {
+ conference->caller_controls = switch_core_strdup(conference->pool, caller_controls);
+ }
+
conference->name = switch_core_strdup(conference->pool, name);
if (domain) {
conference->domain = switch_core_strdup(conference->pool, domain);
@@ -4343,31 +4369,9 @@
}
conference->rate = rate;
conference->interval = interval;
- conference->dtmf_parser = NULL;
-
- /* caller control configuration chores */
- if (switch_ivr_digit_stream_parser_new(conference->pool, &conference->dtmf_parser) == SWITCH_STATUS_SUCCESS) {
- /* if no controls, or default controls specified, install default */
- if (caller_controls == NULL || *caller_controls == '\0' || strcasecmp(caller_controls, "default") == 0) {
- status = conf_default_controls(conference);
- } else if (strcasecmp(caller_controls, "none") != 0) {
- /* try to build caller control if the group has been specified and != "none" */
- switch_xml_t xml_controls = switch_xml_find_child(cfg.controls, "group", "name", caller_controls);
-#ifdef OPTION_IVR_MENU_SUPPORT
- status = conference_new_install_caller_controls_custom(conference, xml_controls, cfg.menus);
-#else
- status = conference_new_install_caller_controls_custom(conference, xml_controls, NULL);
-#endif
- if (status != SWITCH_STATUS_SUCCESS) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to install caller controls group '%s'\n", caller_controls);
- }
- } else {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "no caller controls intalled.\n");
- }
- } else {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to allocate caller control digit parser.\n");
- }
+ /* copy the xml config sections to the new conference */
+ memcpy(&conference->xml_cfg,xml_cfg,sizeof(conf_xml_cfg_t));
/* Activate the conference mutex for exclusivity */
switch_mutex_init(&conference->mutex, SWITCH_MUTEX_NESTED, conference->pool);
More information about the Freeswitch-svn
mailing list