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

Freeswitch SVN knhor at freeswitch.org
Wed Dec 27 01:02:24 EST 2006


Author: knhor
Date: Wed Dec 27 01:02:24 2006
New Revision: 3839

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

Log:
clean up the conf_api_dispatch and conf_api_sub_xxx argument handling.
commonize the code to get xml section pointers.
enhance chat's list output w/ more caller info.
reformatted the conf_api_sub_commands table so that it is readable, please leave it that way.
alphabetically sorted the conf_api_sub_commands table.


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 Dec 27 01:02:24 2006
@@ -54,6 +54,9 @@
 /* this doesn't work correctly yet, don't bother trying! */
 //#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
+
 typedef enum {
 	FILE_STOP_CURRENT, 
 	FILE_STOP_ALL
@@ -149,11 +152,13 @@
 
 /* conference xml config sections */
 typedef struct conf_xml_cfg {
+	switch_xml_t cxml;
 	switch_xml_t profile;
 	switch_xml_t controls;
 #ifdef OPTION_IVR_MENU_SUPPORT
 	switch_xml_t menus;
 #endif
+//	switch_xml_t chat_admin;
 } conf_xml_cfg_t;
 
 /* Conference Object */
@@ -193,6 +198,8 @@
 	uint32_t count;
 	int32_t energy_level;
 	uint8_t min;
+//	switch_hash_t *chat_admin;
+//	switch_hash_t *chat_id;
 } conference_obj_t;
 
 /* Relationship with another member */
@@ -312,6 +319,7 @@
 static switch_status_t conf_api_sub_undeaf(conference_member_t *member, 
                                            switch_stream_handle_t *stream, 
                                            void *data);
+static switch_status_t conference_get_xml_sections(char *profile_name, conf_xml_cfg_t *xml_cfg);
 
 /* Return a Distinct ID # */
 static uint32_t next_member_id(void)
@@ -368,17 +376,18 @@
 	conference_member_t *member = NULL;
 
     assert(conference != NULL);
-    assert(id != 0);
 
-    for(member = conference->members; member; member = member->next) {
-        
-        if (switch_test_flag(member, MFLAG_NOCHANNEL)) {
-            continue;
-        }
-        
-        if (member->id == id) {
-            break;
-        }
+    if (id != 0) {
+	    for(member = conference->members; member; member = member->next) {
+		
+		if (switch_test_flag(member, MFLAG_NOCHANNEL)) {
+		    continue;
+		}
+		
+		if (member->id == id) {
+		    break;
+		}
+	    }
     }
 	
 
@@ -394,7 +403,7 @@
 	assert (conference != NULL);
 
     for(member = conference->members; member; member = member->next) {
-        if (switch_test_flag(member, MFLAG_NOCHANNEL) && (!path || !strcmp(path, member->rec_path))) {
+        if (switch_test_flag(member, MFLAG_NOCHANNEL) && (path == NULL || !strcmp(path, member->rec_path))) {
             switch_clear_flag_locked(member, MFLAG_RUNNING);
             count++;
         }
@@ -521,9 +530,6 @@
 
     assert(conference != NULL);
     assert(member != NULL);
-    
-
-
 
     switch_mutex_lock(conference->mutex);
     switch_mutex_lock(conference->member_mutex);
@@ -1202,8 +1208,6 @@
 		if (lbuf != NULL) {
 			memset(argv, 0, sizeof(argv));
 			argc = switch_separate_string(lbuf, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
-			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "dial argc %u 1 '%s' 2 '%s' 3 '%s' 4 '%s'\n", 
-                              argc, argv[0], argv[1], argv[2], argv[3]);
 			if (argc >= 4) {
 				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "executing conference outcall\n");
 				conference_outcall(member->conference, NULL, argv[0], atoi(argv[1]), NULL, argv[3], argv[2]);
@@ -2122,7 +2126,6 @@
     assert(stream != NULL);
 
     switch_mutex_lock(conference->member_mutex);
-    //		stream->write_function(stream, "<pre>Current Callers:\n");
 
     for (member = conference->members; member; member = member->next) {
         switch_channel_t *channel;
@@ -2135,11 +2138,15 @@
         profile = switch_channel_get_caller_profile(channel);
 
 
-        stream->write_function(stream, "%u) %s (%s)\n", 
+        stream->write_function(stream, "%u) %s (%s) - %s/%s - %d/%d/%d\n", 
                                member->id, 
                                profile->caller_id_name, 
-                               profile->caller_id_number
-                               );
+                               profile->caller_id_number,
+			       (switch_test_flag(member, MFLAG_CAN_HEAR) ? "hear" : "deaf"),
+			       (switch_test_flag(member, MFLAG_CAN_SPEAK) ? "speak" : "mute"),
+                               member->volume_in_level,
+                               member->volume_out_level,
+                               member->energy_level);
 
     }
 
@@ -2481,11 +2488,10 @@
     void *val;
     char *d = ";";
     int pretty = 0;
-    int argofs = (argc >= 2 && strcasecmp(argv[1], "list") == 0);	// detect being called from chat vs. api
 
-    if (argv[1+argofs]) {
-        if (argv[2+argofs] && !strcasecmp(argv[1+argofs], "delim")) {
-            d = argv[2+argofs];
+    if (argv[1]) {
+        if (argv[2] && !strcasecmp(argv[1], "delim")) {
+            d = argv[2];
 
             if (*d == '"') {
                 if (++d) {
@@ -2497,7 +2503,7 @@
                     d = ";";
                 }
             }
-        } else if (strcasecmp(argv[1+argofs], "pretty") == 0) {
+        } else if (strcasecmp(argv[1], "pretty") == 0) {
             pretty = 1;
         }
     }
@@ -2507,10 +2513,12 @@
             switch_hash_this(hi, NULL, NULL, &val);
             conference = (conference_obj_t *) val;
 
-            stream->write_function(stream, "Conference %s (%u member%s)\n", 
+            stream->write_function(stream, "Conference %s (%u member%s, %s)\n", 
                                    conference->name, 
                                    conference->count, 
-                                   conference->count == 1 ? "" : "s");
+                                   conference->count == 1 ? "" : "s",
+				   (switch_test_flag(conference, CFLAG_LOCKED) ? "locked" : "unlocked")
+				   );
             if (pretty) {
                 conference_list_pretty(conference, stream);
             } else {
@@ -2539,35 +2547,35 @@
     assert(stream != NULL);
 
     
-    if (argc == 3) {
-        if (conference_play_file(conference, argv[2], 0, NULL) == SWITCH_STATUS_SUCCESS) {
-            stream->write_function(stream, "(play) Playing file %s\n", argv[2]);
+    if (argc == 1) {
+        if (conference_play_file(conference, argv[0], 0, NULL) == SWITCH_STATUS_SUCCESS) {
+            stream->write_function(stream, "(play) Playing file %s\n", argv[0]);
             if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) {
                 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Conference-Name", conference->name);
                 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Action", "play-file");
-                switch_event_add_header(event, SWITCH_STACK_BOTTOM, "File", argv[2]);
+                switch_event_add_header(event, SWITCH_STACK_BOTTOM, "File", argv[0]);
                 switch_event_fire(&event);
             }
         } else {
-            stream->write_function(stream, "(play) File: %s not found.\n", argv[2] ? argv[2] : "(unspecified)");
+            stream->write_function(stream, "(play) File: %s not found.\n", argv[0] ? argv[0] : "(unspecified)");
         }
         ret_status = SWITCH_STATUS_SUCCESS;
-    } else if (argc == 4) {
-        uint32_t id = atoi(argv[3]);
+    } else if (argc >= 2) {
+        uint32_t id = atoi(argv[1]);
         conference_member_t *member;
 
         if ((member = conference_member_get(conference, id))) {
-            if (conference_member_play_file(member, argv[2], 0) == SWITCH_STATUS_SUCCESS) {
-                stream->write_function(stream, "(play) Playing file %s to member %u\n", argv[2], id);
+            if (conference_member_play_file(member, argv[0], 0) == SWITCH_STATUS_SUCCESS) {
+                stream->write_function(stream, "(play) Playing file %s to member %u\n", argv[0], id);
                 if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) {
                     switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Conference-Name", conference->name);
                     switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Member-ID", "%u", id);
                     switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Action", "play-file-member");
-                    switch_event_add_header(event, SWITCH_STACK_BOTTOM, "File", argv[2]);
+                    switch_event_add_header(event, SWITCH_STACK_BOTTOM, "File", argv[0]);
                     switch_event_fire(&event);
                 }
             } else {
-                stream->write_function(stream, "(play) File: %s not found.\n", argv[2] ? argv[2] : "(unspecified)");
+                stream->write_function(stream, "(play) File: %s not found.\n", argv[0] ? argv[0] : "(unspecified)");
             }
             ret_status = SWITCH_STATUS_SUCCESS;
         } else {
@@ -2677,14 +2685,14 @@
     assert(conference != NULL);
     assert(stream != NULL);
 
-    if (argc > 2) {
-        current = strcasecmp(argv[2], "current") ? 0 : 1;
-        all = strcasecmp(argv[2], "all") ? 0 : 1;
+    if (argc >= 1) {
+        current = strcasecmp(argv[0], "current") ? 0 : 1;
+        all = strcasecmp(argv[0], "all") ? 0 : 1;
     }
 
     if (current || all) {
-        if (argc == 4) {
-            uint32_t id = atoi(argv[3]);
+        if (argc >= 2) {
+            uint32_t id = atoi(argv[1]);
             conference_member_t *member;
 
             if ((member = conference_member_get(conference, id))) {
@@ -2711,14 +2719,10 @@
     assert(conference != NULL);
     assert(stream != NULL);
 
-    if (argc > 4) {
-        uint8_t nospeak = 0, nohear = 0, clear = 0;
-        nospeak = strstr(argv[4], "nospeak") ? 1 : 0;
-        nohear = strstr(argv[4], "nohear") ? 1 : 0;
-
-        if (!strcasecmp(argv[4], "clear")) {
-            clear = 1;
-        }
+    if (argc > 2) {
+        uint8_t clear = (strcasecmp(argv[2], "clear") == 0);
+        uint8_t nospeak = (strstr(argv[2], "nospeak") != NULL);
+        uint8_t nohear = (strstr(argv[2], "nohear") != NULL);
 
         if (!(clear || nospeak || nohear)) { 
             ret_status = SWITCH_STATUS_GENERR;
@@ -2728,8 +2732,8 @@
 
         if (clear) {
             conference_member_t *member = NULL;
-            uint32_t id = atoi(argv[2]);
-            uint32_t oid = atoi(argv[3]);
+            uint32_t id = atoi(argv[0]);
+            uint32_t oid = atoi(argv[1]);
 
             switch_mutex_lock(conference->mutex);
             switch_mutex_lock(conference->member_mutex);
@@ -2743,8 +2747,8 @@
             switch_mutex_unlock(conference->mutex);
         } else if (nospeak || nohear) {
             conference_member_t *member = NULL, *other_member = NULL;
-            uint32_t id = atoi(argv[2]);
-            uint32_t oid = atoi(argv[3]);
+            uint32_t id = atoi(argv[0]);
+            uint32_t oid = atoi(argv[1]);
 
             switch_mutex_lock(conference->mutex);
             switch_mutex_lock(conference->member_mutex);
@@ -2788,7 +2792,7 @@
     assert(stream != NULL);
 
     switch_set_flag_locked(conference, CFLAG_LOCKED);
-    stream->write_function(stream, "OK %s locked\n", argv[0]);
+    stream->write_function(stream, "OK %s locked\n", conference->name);
     if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) {
         switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Conference-Name", conference->name);
         switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Action", "lock");
@@ -2806,7 +2810,7 @@
     assert(stream != NULL);
 
     switch_clear_flag_locked(conference, CFLAG_LOCKED);
-    stream->write_function(stream, "OK %s unlocked\n", argv[0]);
+    stream->write_function(stream, "OK %s unlocked\n", conference->name);
     if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) {
         switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Conference-Name", conference->name);
         switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Action", "unlock");
@@ -2824,8 +2828,8 @@
     assert(conference != NULL);
     assert(stream != NULL);
 
-    if (argc > 2) {
-        conference_outcall(conference, NULL, argv[2], 60, NULL, argv[4], argv[3]);
+    if (argc >= 1) {
+        conference_outcall(conference, NULL, argv[0], 60, NULL, (argc >= 3 ?argv[2] : NULL), (argc >=2 ? argv[1] : NULL));
         stream->write_function(stream, "OK\n");
     } else {
         ret_status = SWITCH_STATUS_GENERR;
@@ -2841,17 +2845,15 @@
     assert(conference != NULL);
     assert(stream != NULL);
 
-    if (argc > 3 && !switch_strlen_zero(argv[2])) {
+    if (argc >= 2 && !switch_strlen_zero(argv[0])) {
         int x;
 
-        for (x = 3; x<argc; x++) {
+        for (x = 1; x<argc; x++) {
             conference_member_t *member = NULL;
             uint32_t id = atoi(argv[x]);
             conference_obj_t *new_conference = NULL;
             switch_channel_t *channel;
             switch_event_t *event;
-            char *profile_name;
-            switch_xml_t cxml = NULL, cfg = NULL, profiles = NULL;
 
             if (!(member = conference_member_get(conference, id))) {								
                 stream->write_function(stream, "No Member %u in conference %s.\n", id, conference->name);
@@ -2861,10 +2863,11 @@
             channel = switch_core_session_get_channel(member->session);
 
             /* build a new conference if it doesn't exist */
-            if (!(new_conference = (conference_obj_t *) switch_core_hash_find(globals.conference_hash, argv[2]))) {
+            if (!(new_conference = (conference_obj_t *) switch_core_hash_find(globals.conference_hash, argv[0]))) {
                 switch_memory_pool_t *pool = NULL;
+		conf_xml_cfg_t xml_cfg = {0};
                 char *conf_name;
-                conf_xml_cfg_t xml_cfg = {0};
+		char *profile_name;
 
                 /* Setup a memory pool to use. */
                 if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {
@@ -2872,35 +2875,26 @@
                     goto done;
                 }
 
-                conf_name = switch_core_strdup(pool, argv[2]);
+                conf_name = switch_core_strdup(pool, argv[0]);
 
                 if ((profile_name = strchr(conf_name, '@'))) {
                     *profile_name++ = '\0';
 
-                    /* Open the config from the xml registry  */
-                    if (!(cxml = switch_xml_open_cfg(global_cf_name, &cfg, NULL))) {
+                    /* get the xml config sections */
+                    if (conference_get_xml_sections(profile_name, &xml_cfg) != SWITCH_STATUS_SUCCESS) {
                         switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "open of %s failed\n", global_cf_name);
                         goto done;
                     }
-
-                    if ((profiles = switch_xml_child(cfg, "profiles"))) {
-                        xml_cfg.profile = switch_xml_find_child(profiles, "profile", "name", profile_name);
-                    }
-                    xml_cfg.controls = switch_xml_child(cfg, "caller-controls");
-#ifdef OPTION_IVR_MENU_SUPPORT
-                    xml_cfg.menus = switch_xml_child(cfg, "menus");
-#endif
                 } 
 
-                /* Release the config registry handle */
-                if (cxml) {
-                    switch_xml_free(cxml);
-                    cxml = NULL;
-                }
-
                 /* 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);
+                }
+
                 if (!new_conference) {
                     switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n");
                     if (pool != NULL) {
@@ -2923,14 +2917,14 @@
             conference_del_member(member->last_conference, member);
             conference_add_member(new_conference, member);
 
-            stream->write_function(stream, "OK Members sent to conference %s.\n", argv[2]);
+            stream->write_function(stream, "OK Member %u sent to conference %s.\n", member->id, argv[0]);
 
             /* tell them what happened */
             if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) {
                 switch_channel_event_set_data(channel, event);
                 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Member-ID", "%u", member->id);
                 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Old-Conference-Name", conference->name);
-                switch_event_add_header(event, SWITCH_STACK_BOTTOM, "New-Conference-Name", argv[3]);
+                switch_event_add_header(event, SWITCH_STACK_BOTTOM, "New-Conference-Name", argv[0]);
                 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Action", "transfer");
                 switch_event_fire(&event);
             }
@@ -2949,8 +2943,8 @@
     assert(conference != NULL);
     assert(stream != NULL);
 
-    if (argc > 2) {
-        launch_conference_record_thread(conference, argv[2]);
+    if (argc >= 1) {
+        launch_conference_record_thread(conference, argv[0]);
     } else {
         ret_status = SWITCH_STATUS_GENERR;
     }
@@ -2965,11 +2959,11 @@
     assert(conference != NULL);
     assert(stream != NULL);
 
-    if (argc > 2) {
-        int all = (strcasecmp(argv[2], "all") == 0 );
+    if (argc >= 1) {
+        int all = (strcasecmp(argv[0], "all") == 0 );
 
-        if (!conference_record_stop(conference, all ? NULL : argv[2]) && !all) {
-            stream->write_function(stream, "non-existant recording '%s'\n", argv[2]);
+        if (!conference_record_stop(conference, (all ? NULL : argv[0])) && !all) {
+            stream->write_function(stream, "non-existant recording '%s'\n", argv[0]);
         }
     } else {
         ret_status = SWITCH_STATUS_GENERR;
@@ -2980,31 +2974,31 @@
 
 /* API Interface Function sub-commands */
 static api_command_t conf_api_sub_commands[] = {
-	{"list", &conf_api_sub_list, CONF_API_SUB_ARGS_SPLIT, "<confname> list [delim <string>]"}, 
-	{"energy", &conf_api_sub_energy, CONF_API_SUB_MEMBER_TARGET, "<confname> energy <member_id|all|last> [<newval>]"}, 
-	{"volume_in", &conf_api_sub_volume_in, CONF_API_SUB_MEMBER_TARGET, "<confname> volume_in <member_id|all|last> [<newval>]"}, 
-	{"volume_out", &conf_api_sub_volume_out, CONF_API_SUB_MEMBER_TARGET, "<confname> volume_out <member_id|all|last> [<newval>]"}, 
-	{"play", &conf_api_sub_play, CONF_API_SUB_ARGS_SPLIT, "<confname> play <file_path> [<member_id>]"}, 
-	{"say", &conf_api_sub_say, CONF_API_SUB_ARGS_AS_ONE, "<confname> say <text>"}, 
-	{"saymember", &conf_api_sub_saymember, CONF_API_SUB_ARGS_AS_ONE, "<confname> saymember <member_id> <text>"}, 
-	{"stop", &conf_api_sub_stop, CONF_API_SUB_MEMBER_TARGET, "<confname> stop <[current|all|last]> [<member_id>]"}, 
-	{"kick", &conf_api_sub_kick, CONF_API_SUB_MEMBER_TARGET, "<confname> kick <[member_id|all|last]>"}, 
-	{"mute", &conf_api_sub_mute, CONF_API_SUB_MEMBER_TARGET, "<confname> mute <[member_id|all]|last>"}, 
-	{"unmute", &conf_api_sub_unmute, CONF_API_SUB_MEMBER_TARGET, "<confname> unmute <[member_id|all]|last>"}, 
-	{"deaf", &conf_api_sub_deaf, CONF_API_SUB_MEMBER_TARGET, "<confname> deaf <[member_id|all]|last>"}, 
-	{"undeaf", &conf_api_sub_undeaf, CONF_API_SUB_MEMBER_TARGET, "<confname> undeaf <[member_id|all]|last>"}, 
-	{"relate", &conf_api_sub_relate, CONF_API_SUB_ARGS_SPLIT, "<confname> relate <member_id> <other_member_id> [nospeak|nohear|clear]"}, 
-	{"lock", &conf_api_sub_lock, CONF_API_SUB_ARGS_SPLIT, "<confname> lock"}, 
-	{"unlock", &conf_api_sub_unlock, CONF_API_SUB_ARGS_SPLIT, "<confname> unlock"}, 
-	{"dial", &conf_api_sub_dial, CONF_API_SUB_ARGS_SPLIT, "<confname> dial <endpoint_module_name>/<destination> <callerid number> <callerid name>"}, 
-	{"transfer", &conf_api_sub_transfer, CONF_API_SUB_ARGS_SPLIT, "<confname> transfer <conference_name> <member id> [...<member id>]"}, 
-	{"record", &conf_api_sub_record, CONF_API_SUB_ARGS_SPLIT, "<confname> record <filename>"}, 
-	{"norecord", &conf_api_sub_norecord, CONF_API_SUB_ARGS_SPLIT, "<confname> norecord <[filename|all]>"}, 
+    {"deaf",         &conf_api_sub_deaf,          CONF_API_SUB_MEMBER_TARGET,    "<confname> deaf <[member_id|all]|last>"},    
+    {"dial",         &conf_api_sub_dial,          CONF_API_SUB_ARGS_SPLIT,       "<confname> dial <endpoint_module_name>/<destination> <callerid number> <callerid name>"},    
+    {"energy",       &conf_api_sub_energy,        CONF_API_SUB_MEMBER_TARGET,    "<confname> energy <member_id|all|last> [<newval>]"}, 
+    {"kick",         &conf_api_sub_kick,          CONF_API_SUB_MEMBER_TARGET,    "<confname> kick <[member_id|all|last]>"},    
+    {"list",         &conf_api_sub_list,          CONF_API_SUB_ARGS_SPLIT,       "<confname> list [delim <string>]"}, 
+    {"lock",         &conf_api_sub_lock,          CONF_API_SUB_ARGS_SPLIT,       "<confname> lock"},    
+    {"mute",         &conf_api_sub_mute,          CONF_API_SUB_MEMBER_TARGET,    "<confname> mute <[member_id|all]|last>"},    
+    {"norecord",     &conf_api_sub_norecord,      CONF_API_SUB_ARGS_SPLIT,       "<confname> norecord <[filename|all]>"},    
+    {"play",         &conf_api_sub_play,          CONF_API_SUB_ARGS_SPLIT,       "<confname> play <file_path> [<member_id>]"}, 
+    {"record",       &conf_api_sub_record,        CONF_API_SUB_ARGS_SPLIT,       "<confname> record <filename>"},    
+    {"relate",       &conf_api_sub_relate,        CONF_API_SUB_ARGS_SPLIT,       "<confname> relate <member_id> <other_member_id> [nospeak|nohear|clear]"},    
+    {"say",          &conf_api_sub_say,           CONF_API_SUB_ARGS_AS_ONE,      "<confname> say <text>"}, 
+    {"saymember",    &conf_api_sub_saymember,     CONF_API_SUB_ARGS_AS_ONE,      "<confname> saymember <member_id> <text>"},    
+    {"stop",         &conf_api_sub_stop,          CONF_API_SUB_MEMBER_TARGET,    "<confname> stop <[current|all|last]> [<member_id>]"},    
+    {"transfer",     &conf_api_sub_transfer,      CONF_API_SUB_ARGS_SPLIT,       "<confname> transfer <conference_name> <member id> [...<member id>]"},    
+    {"undeaf",       &conf_api_sub_undeaf,        CONF_API_SUB_MEMBER_TARGET,    "<confname> undeaf <[member_id|all]|last>"},    
+    {"unlock",       &conf_api_sub_unlock,        CONF_API_SUB_ARGS_SPLIT,       "<confname> unlock"},    
+    {"unmute",       &conf_api_sub_unmute,        CONF_API_SUB_MEMBER_TARGET,    "<confname> unmute <[member_id|all]|last>"},    
+    {"volume_in",    &conf_api_sub_volume_in,     CONF_API_SUB_MEMBER_TARGET,    "<confname> volume_in <member_id|all|last> [<newval>]"}, 
+    {"volume_out",   &conf_api_sub_volume_out,    CONF_API_SUB_MEMBER_TARGET,    "<confname> volume_out <member_id|all|last> [<newval>]"}, 
 };
 
 #define CONFFUNCAPISIZE (sizeof(conf_api_sub_commands)/sizeof(conf_api_sub_commands[0]))
 
-switch_status_t conf_api_dispatch(conference_obj_t *conference, switch_stream_handle_t *stream, int argc, char **argv, const char *cmdline, int argn)
+switch_status_t conf_api_dispatch(conference_obj_t *conference, switch_stream_handle_t *stream, int argc, char **argv, const char *cmdline)
 {	
     switch_status_t status = SWITCH_STATUS_FALSE;
     uint32_t i, found = 0;
@@ -3013,7 +3007,7 @@
 
     /* loop through the command table to find a match */
     for (i = 0; i<CONFFUNCAPISIZE && !found; i++) {
-        if (strcasecmp(argv[argn], conf_api_sub_commands[i].pname) == 0) {
+        if (strcasecmp(argv[0], conf_api_sub_commands[i].pname) == 0) {
             found = 1;
             switch(conf_api_sub_commands[i].fntype) {
 
@@ -3021,7 +3015,7 @@
             case CONF_API_SUB_ARGS_SPLIT:
                 {	conf_api_args_cmd_t pfn = (conf_api_args_cmd_t)conf_api_sub_commands[i].pfnapicmd;
 
-                    if (pfn(conference, stream, argc, argv) != SWITCH_STATUS_SUCCESS) {
+                    if (pfn(conference, stream, argc-1, argv+1) != SWITCH_STATUS_SUCCESS) {
                         /* command returned error, so show syntax usage */
                         stream->write_function(stream, conf_api_sub_commands[i].psyntax);
                     }
@@ -3030,20 +3024,19 @@
 
                 /* member specific command that can be itteratted */
             case CONF_API_SUB_MEMBER_TARGET:
-                {
-                    uint32_t id = atoi(argv[argn+1]);
-                    int all = ( id == 0 && strcasecmp(argv[argn+1], "all") == 0 );
-                    int last = ( id == 0 && strcasecmp(argv[argn+1], "last") == 0 );
+		if (argc > 1) {
+                    uint32_t id = atoi(argv[1]);
+                    int all = ( id == 0 && strcasecmp(argv[1], "all") == 0 );
+                    int last = ( id == 0 && strcasecmp(argv[1], "last") == 0 );
 
                     if (all) {
-                        conference_member_itterator(conference, stream, conf_api_sub_commands[i].pfnapicmd, argv[argn+2]);
+                        conference_member_itterator(conference, stream, conf_api_sub_commands[i].pfnapicmd, argv[2]);
                     } else if (last) {
                         conference_member_t *member = NULL;
                         conference_member_t *last_member = NULL;
 
+                        /* find last (newest) member */
                         switch_mutex_lock(conference->member_mutex);
-
-                        /* find last (oldest) member */
                         member = conference->members;
                         while (member != NULL) {
                             if (last_member == NULL || member->id > last_member->id) {
@@ -3051,20 +3044,19 @@
                             }
                             member = member->next;
                         }
+                        switch_mutex_unlock(conference->member_mutex);
 
-                        /* exec functio on last (oldest) member */
+                        /* exec function on last (newest) member */
                         if (last_member != NULL) {
                             conf_api_member_cmd_t pfn = (conf_api_member_cmd_t)conf_api_sub_commands[i].pfnapicmd;
-                            pfn(last_member, stream, argv[argn+2]);
+                            pfn(last_member, stream, (argc > 2 ? argv[2] : NULL));
                         }
-
-                        switch_mutex_unlock(conference->member_mutex);
                     } else {
                         conf_api_member_cmd_t pfn = (conf_api_member_cmd_t)conf_api_sub_commands[i].pfnapicmd;
                         conference_member_t *member = conference_member_get(conference, id);
 
                         if (member != NULL) {
-                            pfn(conference_member_get(conference, id), stream, argv[argn+2]);
+                            pfn(member, stream, (argc > 2 ? argv[2] : NULL));
                         } else {
                             if (id == 0) {
                                 stream->write_function(stream, conf_api_sub_commands[i].psyntax);
@@ -3073,7 +3065,9 @@
                             }
                         }
                     }
-                }
+                } else {
+			stream->write_function(stream, conf_api_sub_commands[i].psyntax);
+		}
                 break;
 
                 /* commands that deals with all text after command */
@@ -3103,7 +3097,7 @@
     }
 
     if (!found) {
-        stream->write_function(stream, "Confernece command '%s' not found.\n", argv[argn]);
+        stream->write_function(stream, "Confernece command '%s' not found.\n", argv[0]);
     } else {
         status = SWITCH_STATUS_SUCCESS;
     }
@@ -3153,7 +3147,8 @@
             }
 
             if (argc >= 2) {
-                conf_api_dispatch(conference, stream, argc, argv, (const char *)buf, 1);
+		/* call the command dispatcher after left shifting the command line */
+                conf_api_dispatch(conference, stream, argc-1, argv+1, (const char *)buf);
             } else {
                 stream->write_function(stream, "Conference command, not specified.\nTry 'help'\n");
             }
@@ -3164,8 +3159,10 @@
             /* special case the list command, because it doesn't require a conference argument */
             if (strcasecmp(argv[0], "list") == 0) {
                 conf_api_sub_list(NULL, stream, argc, argv);
+            /* provide help */
             } else if (strcasecmp(argv[0], "help") == 0 || strcasecmp(argv[0], "commands") == 0) {
                 stream->write_function(stream, "%s\n", conf_api_interface.syntax);
+            /* failure */
             } else {
                 stream->write_function(stream, "Conference %s not found\n", argv[0]);
                 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Conference %s not found\n", argv[0]);
@@ -3334,6 +3331,31 @@
     return status;
 }
 
+static switch_status_t conference_get_xml_sections(char *profile_name, conf_xml_cfg_t *xml_cfg)
+{
+	switch_status_t status = SWITCH_STATUS_FALSE;
+
+	if (!switch_strlen_zero(profile_name) && xml_cfg != NULL) {
+            switch_xml_t cfg = NULL, profiles = NULL;
+
+            xml_cfg->cxml = switch_xml_open_cfg(global_cf_name, &cfg, NULL);
+
+	    if (xml_cfg->cxml != NULL) {
+		if ((profiles = switch_xml_child(cfg, "profiles"))) {
+			xml_cfg->profile = switch_xml_find_child(profiles, "profile", "name", profile_name);
+		}
+		xml_cfg->controls = switch_xml_child(cfg, "caller-controls");
+#ifdef OPTION_IVR_MENU_SUPPORT
+		xml_cfg->menus = switch_xml_child(cfg, "menus");
+#endif
+//		xml_cfg->chat_admin = switch_xml_child(cfg, "chat-admin");
+		status = SWITCH_STATUS_SUCCESS;
+	    }
+	}
+
+	return status;
+}
+
 /* Application interface function that is called from the dialplan to join the channel to a conference */
 static void conference_function(switch_core_session_t *session, char *data)
 {
@@ -3349,7 +3371,6 @@
     char *flags_prefix = "+flags{";
     char *bridgeto = NULL;
     char *profile_name = NULL;
-    switch_xml_t cxml = NULL, cfg = NULL, profiles = NULL;
     char *flags_str;
     member_flag_t uflags = MFLAG_CAN_SPEAK | MFLAG_CAN_HEAR;
     switch_core_session_message_t msg = {0};
@@ -3411,20 +3432,11 @@
     if ((profile_name = strchr(conf_name, '@'))) {
         *profile_name++ = '\0';
 
-        /* Open the config from the xml registry */
-        if (!(cxml = switch_xml_open_cfg(global_cf_name, &cfg, NULL))) {
+	/* get the xml config sections */
+	if (conference_get_xml_sections(profile_name, &xml_cfg) != SWITCH_STATUS_SUCCESS) {
             switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "open of %s failed\n", global_cf_name);
             goto done;
         }
-
-        if ((profiles = switch_xml_child(cfg, "profiles"))) {
-            xml_cfg.profile = switch_xml_find_child(profiles, "profile", "name", profile_name);
-        }
-
-        xml_cfg.controls = switch_xml_child(cfg, "caller-controls");
-#ifdef OPTION_IVR_MENU_SUPPORT
-        xml_cfg.menus = switch_xml_child(cfg, "menus");
-#endif
     } 
 
     /* if this is a bridging call, and it's not a duplicate, build a */
@@ -3557,9 +3569,9 @@
     }
 
     /* Release the config registry handle */
-    if (cxml) {
-        switch_xml_free(cxml);
-        cxml = NULL;
+    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 */
@@ -3693,8 +3705,8 @@
     switch_buffer_destroy(&member.mux_buffer);
 
     /* Release the config registry handle */
-    if (cxml) {
-        switch_xml_free(cxml);
+    if (xml_cfg.cxml) {
+        switch_xml_free(xml_cfg.cxml);
     }
 
     if (freepool) {
@@ -3816,16 +3828,20 @@
         if (argc) {
             /* special case list */
             if (strcasecmp(argv[0], "list") == 0) {
+		stream.write_function(&stream, "(%u member%s, %s)\n", 
+                                   conference->count, 
+                                   conference->count == 1 ? "" : "s",
+				   (switch_test_flag(conference, CFLAG_LOCKED) ? "locked" : "unlocked")
+				   );
                 conference_list_pretty(conference, &stream);
-                /* provide help */
-            } 
-            else {
-                if (strcasecmp(argv[0], "help") == 0 || strcasecmp(argv[0], "commands") == 0) {
+#ifdef ENABLE_CHAT_ADMIN
+            /* provide help */
+            } else if (strcasecmp(argv[0], "help") == 0 || strcasecmp(argv[0], "commands") == 0) {
                     stream.write_function(&stream, "%s\n", conf_api_interface.syntax);
-                    /* find a normal command */
-                } else {
-                    conf_api_dispatch(conference, &stream, argc, argv, (const char *)body, 0);
-                }
+            /* find a normal command */
+            } else {
+                conf_api_dispatch(conference, &stream, argc, argv, (const char *)body);
+#endif
             }
         } else {
             stream.write_function(&stream, "No parameters specified.\nTry 'help'\n");



More information about the Freeswitch-svn mailing list