[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