[Freeswitch-svn] [commit] r3440 - freeswitch/branches/knhor/trunk/src/mod/applications/mod_conference

Freeswitch SVN knhor at freeswitch.org
Wed Nov 22 20:40:14 EST 2006


Author: knhor
Date: Wed Nov 22 20:40:14 2006
New Revision: 3440

Modified:
   freeswitch/branches/knhor/trunk/src/mod/applications/mod_conference/mod_conference.c

Log:
mostly complete support or ivr menus with caller control callbacks


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	Wed Nov 22 20:40:14 2006
@@ -56,12 +56,23 @@
 	FILE_STOP_ALL
 } file_stop_t;
 
+/* Global Values */
+static struct {
+	switch_memory_pool_t *conference_pool;
+	switch_mutex_t *conference_mutex;
+	switch_hash_t *conference_hash;
+	switch_mutex_t *id_mutex;
+	switch_mutex_t *hash_mutex;
+	uint32_t id_pool;
+	int32_t running;
+	uint32_t threads;
+} globals;
+
 typedef enum {
-	CALLER_CONTROL_NOEVENT,
 	CALLER_CONTROL_MUTE,
 	CALLER_CONTROL_DEAF_MUTE,
 	CALLER_CONTROL_ENERGY_UP,
-	CALLER_CONTROL_ENERGY_EQU_CONFERENCE,
+	CALLER_CONTROL_ENERGY_EQU_CONF,
 	CALLER_CONTROL_ENERGEY_DN,
 	CALLER_CONTROL_VOL_TALK_UP,
 	CALLER_CONTROL_VOL_TALK_ZERO,
@@ -70,44 +81,23 @@
 	CALLER_CONTROL_VOL_LISTEN_ZERO,
 	CALLER_CONTROL_VOL_LISTEN_DN,
 	CALLER_CONTROL_HANGUP,
+	CALLER_CONTROL_MENU,
 } caller_control_t;
 
-static struct _caller_control_actions_struct {
-	char *key;
-	char *default_digits;
-	caller_control_t action;
-} caller_control_actions[] = {
-	{"mute",		"0",	CALLER_CONTROL_MUTE},
-	{"deaf mute",		"*",	CALLER_CONTROL_DEAF_MUTE},
-	{"energy up",		"9",	CALLER_CONTROL_ENERGY_UP},
-	{"energy equ",		"8",	CALLER_CONTROL_ENERGY_EQU_CONFERENCE},
-	{"energy dn",		"7",	CALLER_CONTROL_ENERGEY_DN},
-	{"vol talk up",		"3",	CALLER_CONTROL_VOL_TALK_UP},
-	{"vol talk zero",	"2",	CALLER_CONTROL_VOL_TALK_ZERO},
-	{"vol talk dn",		"1",	CALLER_CONTROL_VOL_TALK_DN},
-	{"vol listen up",	"6",	CALLER_CONTROL_VOL_LISTEN_UP},
-	{"vol listen zero",	"5",	CALLER_CONTROL_VOL_LISTEN_ZERO},
-	{"vol listen dn",	"4",	CALLER_CONTROL_VOL_LISTEN_DN},
-	{"hangup",		"#",	CALLER_CONTROL_HANGUP},
-};
-#define CALLER_CONTROL_ACTIONS_QTY (sizeof(caller_control_actions)/sizeof(caller_control_actions[0]))
-
-/* Global Values */
-static struct {
-	switch_memory_pool_t *conference_pool;
-	switch_mutex_t *conference_mutex;
-	switch_hash_t *conference_hash;
-	switch_mutex_t *id_mutex;
-	switch_mutex_t *hash_mutex;
-	uint32_t id_pool;
-	int32_t running;
-	uint32_t threads;
-} globals;
-
-// forward declaration for conference_obj structure
+// forward declaration for conference_obj and caller_control
 struct conference_member;
 typedef struct conference_member conference_member_t;
 
+typedef struct caller_control_actions {
+	void (*handler)(conference_member_t *, void *);
+	void *data;
+} caller_control_action_t;
+
+typedef struct caller_control_menu_info {
+	switch_ivr_menu_t *stack;
+	char *name;
+} caller_control_menu_info_t;
+
 typedef enum {
 	MFLAG_RUNNING = (1 << 0),
 	MFLAG_CAN_SPEAK = (1 << 1),
@@ -117,7 +107,6 @@
 	MFLAG_NOCHANNEL = (1 << 5)
 } member_flag_t;
 
-
 typedef enum {
 	CFLAG_RUNNING = (1 << 0),
 	CFLAG_DYNAMIC = (1 << 1),
@@ -137,7 +126,7 @@
 	NODE_TYPE_SPEECH
 } node_type_t;
 
-struct confernce_file_node {
+typedef struct confernce_file_node {
 	switch_file_handle_t fh;
 	switch_speech_handle_t sh;
 	node_type_t type;
@@ -145,12 +134,10 @@
 	switch_memory_pool_t *pool;
 	uint32_t leadin;
 	struct confernce_file_node *next;
-};
+} confernce_file_node_t;
 
-typedef struct confernce_file_node confernce_file_node_t;
-
 /* Conference Object */
-struct conference_obj {
+typedef struct conference_obj {
 	char *name;
 	char *timer_name;
 	char *tts_engine;
@@ -186,16 +173,14 @@
 	uint32_t count;
 	int32_t energy_level;
 	uint8_t min;
-};
-typedef struct conference_obj conference_obj_t;
+} conference_obj_t;
 
 /* Relationship with another member */
-struct conference_relationship {
+typedef struct conference_relationship {
 	uint32_t id;
 	uint32_t flags;
 	struct conference_relationship *next;
-};
-typedef struct conference_relationship conference_relationship_t;
+} conference_relationship_t;
 
 /* Conference Member Object */
 struct conference_member {
@@ -231,12 +216,11 @@
 };
 
 /* Record Node */
-struct conference_record {
+typedef struct conference_record {
 	conference_obj_t *conference;
 	char *path;
 	switch_memory_pool_t *pool;
-};
-typedef struct conference_record conference_record_t;
+} conference_record_t;
 
 // API command parser
 typedef struct api_command {
@@ -272,7 +256,6 @@
 static void conference_function(switch_core_session_t *session, char *data);
 static void launch_conference_thread(conference_obj_t *conference);
 static void *SWITCH_THREAD_FUNC input_thread_run(switch_thread_t *thread, void *obj);
-static void launch_input_thread(conference_member_t *member, switch_memory_pool_t *pool);
 static switch_status_t conference_local_play_file(switch_core_session_t *session, char *path, uint32_t leadin, char *buf, switch_size_t len);
 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_obj_t *conference, conference_member_t *member, char *text, uint32_t leadin);
@@ -807,7 +790,7 @@
 	return NULL;
 }
 
-static void conference_loop_fn_mute_toggle(conference_member_t *member)
+static void conference_loop_fn_mute_toggle(conference_member_t *member, void *data)
 {
 	if (switch_test_flag(member, MFLAG_CAN_SPEAK)) {
 		conf_api_sub_mute(member, NULL, NULL);
@@ -817,7 +800,7 @@
 	}
 }
 
-static void conference_loop_fn_deafmute_toggle(conference_member_t *member)
+static void conference_loop_fn_deafmute_toggle(conference_member_t *member, void *data)
 {
 	if (switch_test_flag(member, MFLAG_CAN_SPEAK)) {
 		conf_api_sub_mute(member, NULL, NULL);
@@ -828,7 +811,7 @@
 	}
 }
 
-static void conference_loop_fn_energy_up(conference_member_t *member)
+static void conference_loop_fn_energy_up(conference_member_t *member, void *data)
 {
 	char msg[512];
 
@@ -842,7 +825,7 @@
 	conference_member_say(member->conference, member, msg, 0);
 }
 
-static void conference_loop_fn_energy_equ_conference(conference_member_t *member)
+static void conference_loop_fn_energy_equ_conf(conference_member_t *member, void *data)
 {
 	char msg[512];
 
@@ -853,7 +836,7 @@
 	conference_member_say(member->conference, member, msg, 0);
 }
 					
-static void conference_loop_fn_energy_dn(conference_member_t *member)
+static void conference_loop_fn_energy_dn(conference_member_t *member, void *data)
 {
 	char msg[512];
 
@@ -867,7 +850,7 @@
 	conference_member_say(member->conference, member, msg, 0);
 }
 
-static void conference_loop_fn_volume_talk_up(conference_member_t *member)
+static void conference_loop_fn_volume_talk_up(conference_member_t *member, void *data)
 {
 	char msg[512];
 
@@ -879,7 +862,7 @@
 	conference_member_say(member->conference, member, msg, 0);
 }
 
-static void conference_loop_fn_volume_talk_zero(conference_member_t *member)
+static void conference_loop_fn_volume_talk_zero(conference_member_t *member, void *data)
 {
 	char msg[512];
 
@@ -890,7 +873,7 @@
 	conference_member_say(member->conference, member, msg, 0);
 }
 
-static void conference_loop_fn_volume_talk_dn(conference_member_t *member)
+static void conference_loop_fn_volume_talk_dn(conference_member_t *member, void *data)
 {
 	char msg[512];
 
@@ -902,7 +885,7 @@
 	conference_member_say(member->conference, member, msg, 0);
 }
 
-static void conference_loop_fn_volume_listen_up(conference_member_t *member)
+static void conference_loop_fn_volume_listen_up(conference_member_t *member, void *data)
 {
 	char msg[512];
 
@@ -914,7 +897,7 @@
 	conference_member_say(member->conference, member, msg, 0);
 }
 
-static void conference_loop_fn_volume_listen_zero(conference_member_t *member)
+static void conference_loop_fn_volume_listen_zero(conference_member_t *member, void *data)
 {
 	char msg[512];
 
@@ -925,7 +908,7 @@
 	conference_member_say(member->conference, member, msg, 0);
 }
 
-static void conference_loop_fn_volume_listen_dn(conference_member_t *member)
+static void conference_loop_fn_volume_listen_dn(conference_member_t *member, void *data)
 {
 	char msg[512];
 
@@ -937,11 +920,34 @@
 	conference_member_say(member->conference, member, msg, 0);
 }
 
-static void conference_loop_fn_hangup(conference_member_t *member)
+static void conference_loop_fn_hangup(conference_member_t *member, void *data)
 {
 	switch_clear_flag_locked(member, MFLAG_RUNNING);
 }
 
+typedef struct caller_control_menu_ctx {
+	switch_ivr_menu_xml_ctx_t *xml_ctx;
+	switch_ivr_menu_t *menu_stack;
+	char *name;
+} caller_control_menu_ctx_t;
+
+static void conference_loop_fn_menu(conference_member_t *member, void *data)
+{
+	if (data != NULL) {
+		caller_control_menu_ctx_t *menu_ctx = (caller_control_menu_ctx_t *)data;
+
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "conference_loop_fn_menu handler '%s'\n",menu_ctx->name);
+		if (menu_ctx->menu_stack != NULL && menu_ctx->xml_ctx != NULL) {
+			switch_ivr_menu_execute(member->session,menu_ctx->menu_stack,menu_ctx->name,NULL);
+		} else {
+			if(menu_ctx->menu_stack == NULL)
+				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "conference_loop_fn_menu handler NULL menu_stack\n");
+			if(menu_ctx->xml_ctx == NULL)
+				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "conference_loop_fn_menu handler NULL xml_ctx\n");
+		}
+	}
+}
+
 /* Create a thread for the conference and launch it */
 static void launch_input_thread(conference_member_t *member, switch_memory_pool_t *pool)
 {
@@ -1038,51 +1044,13 @@
 			switch_channel_dequeue_dtmf(channel, dtmf, sizeof(dtmf));
 
 			if(member->conference->dtmf_parser != NULL) {
-				for (digit = dtmf; *digit; digit++) {
-					int *action = (int *)switch_ivr_digit_stream_parser_feed(member->conference->dtmf_parser, *digit);
+				caller_control_action_t *action;
 
-					if (action != NULL) {
-						switch(*action) {
-							case CALLER_CONTROL_NOEVENT:
-								// the digit string collected so far has not been recognized
-								break;
-							case CALLER_CONTROL_MUTE:
-								conference_loop_fn_mute_toggle(member);
-								break;
-							case CALLER_CONTROL_DEAF_MUTE:
-								conference_loop_fn_deafmute_toggle(member);
-								break;
-							case CALLER_CONTROL_ENERGY_UP:
-								conference_loop_fn_energy_up(member);
-								break;
-							case CALLER_CONTROL_ENERGY_EQU_CONFERENCE:
-								conference_loop_fn_energy_equ_conference(member);
-								break;
-							case CALLER_CONTROL_ENERGEY_DN:
-								conference_loop_fn_energy_dn(member);
-								break;
-							case CALLER_CONTROL_VOL_TALK_UP:
-								conference_loop_fn_volume_talk_up(member);
-								break;
-							case CALLER_CONTROL_VOL_TALK_ZERO:
-								conference_loop_fn_volume_talk_zero(member);
-								break;
-							case CALLER_CONTROL_VOL_TALK_DN:
-								conference_loop_fn_volume_talk_dn(member);
-								break;
-							case CALLER_CONTROL_VOL_LISTEN_UP:
-								conference_loop_fn_volume_listen_up(member);
-								break;
-							case CALLER_CONTROL_VOL_LISTEN_ZERO:
-								conference_loop_fn_volume_listen_zero(member);
-								break;
-							case CALLER_CONTROL_VOL_LISTEN_DN:
-								conference_loop_fn_volume_listen_dn(member);
-								break;
-							case CALLER_CONTROL_HANGUP:
-								conference_loop_fn_hangup(member);
-							break;
-						}
+				for (digit = dtmf; *digit; digit++) {
+					action = (caller_control_action_t *)switch_ivr_digit_stream_parser_feed(member->conference->dtmf_parser, *digit);
+				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "digit_stream_parser_feed result != NULL %u\n",action != NULL);
+					if (action != NULL && action->handler != NULL) {
+						action->handler(member,action->data);
 					}
 				}
 			}
@@ -3254,11 +3222,71 @@
 	/*.chat_interface */ &conference_chat_interface
 };
 
+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 (param != NULL) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "caller control menu action '%s'\n",param);
+	}
+
+	return action;
+}
+
+static switch_status_t conference_caller_control_menu_build(caller_control_menu_ctx_t **ctx, conference_obj_t *conference, switch_xml_t profile, char *menu_name)
+{
+	switch_status_t status = SWITCH_STATUS_FALSE;
+
+	if (ctx != NULL && conference != NULL && profile != NULL && menu_name != NULL) {
+		switch_xml_t xml_menus = switch_xml_child(profile, "menus");
+		switch_xml_t xml_menu = (xml_menus != NULL ? switch_xml_find_child(xml_menus, "menu", "name", menu_name) : NULL);
+
+		// if we found the requested menu in our profile
+		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");
+				} 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);
+		}
+	} else {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "null parameters!\n");
+	}
+
+	return status;
+}
+
 /* create a new conferene with a specific profile */
 static conference_obj_t *conference_new(char *name, switch_xml_t profile, switch_memory_pool_t *pool)
 {
 	conference_obj_t *conference;
 	switch_xml_t xml_kvp;
+	switch_xml_t xml_controls;
+	switch_xml_t xml_menus;
+	char *controls_set = NULL;
 	char *rate_name = NULL;
 	char *interval_name = NULL;
 	char *timer_name = NULL;
@@ -3470,46 +3498,125 @@
 	conference->rate = rate;
 	conference->interval = interval;
 
-	if(switch_ivr_digit_stream_parser_new(conference->pool,&conference->dtmf_parser) == SWITCH_STATUS_SUCCESS) {
-		int i;
+	xml_controls = switch_xml_child(profile, "controls");
+	controls_set = (xml_controls != NULL ? (char *) switch_xml_attr_soft(xml_controls, "set") : NULL);
 
-		// count the number of caller control definitons in the profile
-		for (i=0,xml_kvp = switch_xml_child(profile, "control"); xml_kvp; xml_kvp = xml_kvp->next) {
-			i++;
-		}
-		// map in the default control handler strings only if the profile has no caller control definitions
-		if (i == 0) {
-			for(i=0,status=SWITCH_STATUS_SUCCESS; status == SWITCH_STATUS_SUCCESS && i<CALLER_CONTROL_ACTIONS_QTY; i++) {
-				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Installing default caller control action name '%s' bound to '%s' digits.\n",
-					caller_control_actions[i].key,caller_control_actions[i].default_digits);
-				status = switch_ivr_digit_stream_parser_set_event(conference->dtmf_parser,caller_control_actions[i].default_digits,(void *)&(caller_control_actions[i].action));
-			}
-		}
+	// try to build caller control if the set has been specified and != "none"
+	if (xml_controls != NULL && controls_set != NULL && strcasecmp(controls_set,"none") != 0) {
+		struct default_caller_control_table {
+			char *key;
+			char *digits;
+			caller_control_t action;
+			void (*handler)(conference_member_t *, void *);
+		} dcctbl[] = {
+			{"mute",		"0",	CALLER_CONTROL_MUTE,		conference_loop_fn_mute_toggle},
+			{"deaf mute",		"*",	CALLER_CONTROL_DEAF_MUTE,	conference_loop_fn_deafmute_toggle},
+			{"energy up",		"9",	CALLER_CONTROL_ENERGY_UP,	conference_loop_fn_energy_up},
+			{"energy equ",		"8",	CALLER_CONTROL_ENERGY_EQU_CONF,	conference_loop_fn_energy_equ_conf},
+			{"energy dn",		"7",	CALLER_CONTROL_ENERGEY_DN,	conference_loop_fn_energy_dn},
+			{"vol talk up",		"3",	CALLER_CONTROL_VOL_TALK_UP,	conference_loop_fn_volume_talk_up},
+			{"vol talk zero",	"2",	CALLER_CONTROL_VOL_TALK_ZERO,	conference_loop_fn_volume_talk_zero},
+			{"vol talk dn",		"1",	CALLER_CONTROL_VOL_TALK_DN,	conference_loop_fn_volume_talk_dn},
+			{"vol listen up",	"6",	CALLER_CONTROL_VOL_LISTEN_UP,	conference_loop_fn_volume_listen_up},
+			{"vol listen zero",	"5",	CALLER_CONTROL_VOL_LISTEN_ZERO,	conference_loop_fn_volume_listen_zero},
+			{"vol listen dn",	"4",	CALLER_CONTROL_VOL_LISTEN_DN,	conference_loop_fn_volume_listen_dn},
+			{"hangup",		"#",	CALLER_CONTROL_HANGUP,		conference_loop_fn_hangup},
+			{"menu",		NULL,	CALLER_CONTROL_MENU,		conference_loop_fn_menu},
+		};
+		int dcctbl_qty = (sizeof(dcctbl)/sizeof(dcctbl[0]));
 
-		// parse the profile tree for caller control digit strings
-		for (xml_kvp = switch_xml_child(profile, "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");
+		if(switch_ivr_digit_stream_parser_new(conference->pool,&conference->dtmf_parser) == SWITCH_STATUS_SUCCESS) {
+			
+			// map in the default control handler strings if specified
+			if (strcasecmp(controls_set,"default") == 0) {
+				int i;
+				caller_control_action_t *action;
 
-			if(key != NULL && val != NULL && *key && *val) {
-				// 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<CALLER_CONTROL_ACTIONS_QTY && status == SWITCH_STATUS_NOOP; i++) {
-					if(strcasecmp(caller_control_actions[i].key,key) == 0) {
-						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Installing caller control action name '%s' bound to '%s' digits.\n",key,val);
-						status = switch_ivr_digit_stream_parser_set_event(conference->dtmf_parser,val,(void *)&caller_control_actions[i].action);
+				for(i=0,status=SWITCH_STATUS_SUCCESS; status == SWITCH_STATUS_SUCCESS && i<dcctbl_qty; i++) {
+					switch(dcctbl[i].action)
+					{
+						case CALLER_CONTROL_MENU:
+							// default caller control, has no menu specification
+							break;
+						default:
+							switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Installing default caller control action '%s' bound to '%s'.\n",
+														dcctbl[i].key,
+														dcctbl[i].digits);
+							action = (caller_control_action_t *)switch_core_alloc(conference->pool,sizeof(caller_control_action_t));
+							if (action != NULL) {
+								action->handler = dcctbl[i].handler;
+								action->data = NULL;
+								status = switch_ivr_digit_stream_parser_set_event(conference->dtmf_parser,dcctbl[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",dcctbl[i].key,dcctbl[i].digits);
+								status = SWITCH_STATUS_MEMERR;
+							}
+							break;
 					}
 				}
-				if(status == SWITCH_STATUS_NOOP) {
-					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid caller control action name '%s'.\n",key);
+			} else if (strcasecmp(controls_set,"custom") == 0) {
+				// 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");
+
+					if(!switch_strlen_zero(key) && !switch_strlen_zero(val)) {
+						int i;
+						caller_control_action_t *action;
+
+						// 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<dcctbl_qty && status == SWITCH_STATUS_NOOP; i++) {
+							caller_control_menu_ctx_t *menu_ctx = NULL;
+
+							if(strcasecmp(dcctbl[i].key,key) == 0) {
+								switch(dcctbl[i].action)
+								{
+									case CALLER_CONTROL_MENU:
+										{
+											char *menu_name = (char *)switch_xml_attr_soft(xml_kvp, "menu-name");
+
+											status = conference_caller_control_menu_build(&menu_ctx,conference,profile,menu_name);
+											if (status != SWITCH_STATUS_SUCCESS) {
+												switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "unable to build menu '%s' bound to '%s'\n", menu_name, val);
+												break;
+											}
+										}
+										// deliberate fall through to default case
+									default:
+										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->handler = dcctbl[i].handler;
+											action->data = (void *)menu_ctx;
+											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",dcctbl[i].key,dcctbl[i].digits);
+											status = SWITCH_STATUS_MEMERR;
+										}
+										break;
+								}
+							}
+						}
+						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);
+					}
 				}
-			} else {
-				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid caller control config entry pair action='%s' digits='%s'\n",key,val);
 			}
+		} else {
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to allocate caller control digit parser.\n");
 		}
 	} else {
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to allocate caller control digit parser.\n");
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "no caller controls intalled.\n");
+	}
+
+	xml_menus = switch_xml_child(profile, "menus");
+	if (xml_menus != NULL) {
+//		switch_xml_t xml_menu;
 	}
 
 	/* Activate the conference mutex for exclusivity */



More information about the Freeswitch-svn mailing list