app_meetme Muting and Manager API enhancements #6731 (softins w/some minor mods...
authorBJ Weschke <bweschke@btwtech.com>
Tue, 23 May 2006 16:35:46 +0000 (16:35 +0000)
committerBJ Weschke <bweschke@btwtech.com>
Tue, 23 May 2006 16:35:46 +0000 (16:35 +0000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@29705 65c4cc65-6c06-0410-ace0-fbb531ad65f3

UPGRADE.txt
apps/app_meetme.c

index 0b2fe45..c0e32e7 100644 (file)
@@ -97,6 +97,12 @@ Applications:
   record conversations queue members are having with queue callers. Please
   see configs/queues.conf.sample for more information on this option.
 
   record conversations queue members are having with queue callers. Please
   see configs/queues.conf.sample for more information on this option.
 
+* app_meetme: The 'm' option (monitor) is renamed to 'l' (listen only), and
+  the 'm' option now provides the functionality of "initially muted". 
+  In practice, most existing dialplans using the 'm' flag should not notice
+  any difference, unless the keypad menu is enabled, allowing the user 
+  to unmute themsleves.
+
 * ast_play_and_record would attempt to cancel the recording if a DTMF
   '0' was received.  This behavior was not documented in most of the
   applications that used ast_play_and_record and the return codes from
 * ast_play_and_record would attempt to cancel the recording if a DTMF
   '0' was received.  This behavior was not documented in most of the
   applications that used ast_play_and_record and the return codes from
@@ -132,6 +138,12 @@ Manager:
   headers are not automatically sent, unless you specify them as separate
   arguments.  Please see the application help for the new syntax.
 
   headers are not automatically sent, unless you specify them as separate
   arguments.  Please see the application help for the new syntax.
 
+* app_meetme: Mute and Unmute events are now reported via the Manager API.
+  Native Manager API commands MeetMeMute and MeetMeUnmute are provided, which
+  are easier to use than "Action Command:". The MeetMeStopTalking event has
+  also been deprecated in favor of the already existing MeetmeTalking event
+  with a "Status" of "on" or "off" added.
+
 Variables:
 
 * The builtin variables ${CALLERID}, ${CALLERIDNAME}, ${CALLERIDNUM},
 Variables:
 
 * The builtin variables ${CALLERID}, ${CALLERIDNAME}, ${CALLERIDNUM},
index d05c37e..e6fed57 100644 (file)
@@ -74,8 +74,9 @@ LOCAL_USER_DECL;
 #define DEFAULT_AUDIO_BUFFERS  32
 
 enum {
 #define DEFAULT_AUDIO_BUFFERS  32
 
 enum {
-       ADMINFLAG_MUTED =  (1 << 1), /*!< User is muted */
-       ADMINFLAG_KICKME = (1 << 2)  /*!< User has been kicked */
+       ADMINFLAG_MUTED =     (1 << 1), /*!< User is muted */
+       ADMINFLAG_SELFMUTED = (1 << 2), /*!< User muted self */
+       ADMINFLAG_KICKME =    (1 << 3)  /*!< User has been kicked */
 };
 
 #define MEETME_DELAYDETECTTALK     300
 };
 
 #define MEETME_DELAYDETECTTALK     300
@@ -146,9 +147,11 @@ enum {
        /*! If set, won't speak the extra prompt when the first person 
         *  enters the conference */
        CONFFLAG_NOONLYPERSON = (1 << 22),
        /*! If set, won't speak the extra prompt when the first person 
         *  enters the conference */
        CONFFLAG_NOONLYPERSON = (1 << 22),
-       CONFFLAG_INTROUSERNOREVIEW = (1 << 23)
+       CONFFLAG_INTROUSERNOREVIEW = (1 << 23),
        /*! If set, user will be asked to record name on entry of conference 
         *  without review */
        /*! If set, user will be asked to record name on entry of conference 
         *  without review */
+       CONFFLAG_STARTMUTED = (1 << 24)
+       /*! If set, the user will be initially muted by admin */
 };
 
 AST_APP_OPTIONS(meetme_opts, {
 };
 
 AST_APP_OPTIONS(meetme_opts, {
@@ -163,7 +166,7 @@ AST_APP_OPTIONS(meetme_opts, {
        AST_APP_OPTION('i', CONFFLAG_INTROUSER ),
        AST_APP_OPTION('I', CONFFLAG_INTROUSERNOREVIEW ),
        AST_APP_OPTION('M', CONFFLAG_MOH ),
        AST_APP_OPTION('i', CONFFLAG_INTROUSER ),
        AST_APP_OPTION('I', CONFFLAG_INTROUSERNOREVIEW ),
        AST_APP_OPTION('M', CONFFLAG_MOH ),
-       AST_APP_OPTION('m', CONFFLAG_MONITOR ),
+       AST_APP_OPTION('m', CONFFLAG_STARTMUTED ),
        AST_APP_OPTION('o', CONFFLAG_OPTIMIZETALKER ),
        AST_APP_OPTION('P', CONFFLAG_ALWAYSPROMPT ),
        AST_APP_OPTION('p', CONFFLAG_POUNDEXIT ),
        AST_APP_OPTION('o', CONFFLAG_OPTIMIZETALKER ),
        AST_APP_OPTION('P', CONFFLAG_ALWAYSPROMPT ),
        AST_APP_OPTION('p', CONFFLAG_POUNDEXIT ),
@@ -171,6 +174,7 @@ AST_APP_OPTIONS(meetme_opts, {
        AST_APP_OPTION('r', CONFFLAG_RECORDCONF ),
        AST_APP_OPTION('s', CONFFLAG_STARMENU ),
        AST_APP_OPTION('T', CONFFLAG_MONITORTALKER ),
        AST_APP_OPTION('r', CONFFLAG_RECORDCONF ),
        AST_APP_OPTION('s', CONFFLAG_STARMENU ),
        AST_APP_OPTION('T', CONFFLAG_MONITORTALKER ),
+       AST_APP_OPTION('l', CONFFLAG_MONITOR ),
        AST_APP_OPTION('t', CONFFLAG_TALKER ),
        AST_APP_OPTION('w', CONFFLAG_WAITMARKED ),
        AST_APP_OPTION('X', CONFFLAG_EXIT_CONTEXT ),
        AST_APP_OPTION('t', CONFFLAG_TALKER ),
        AST_APP_OPTION('w', CONFFLAG_WAITMARKED ),
        AST_APP_OPTION('X', CONFFLAG_EXIT_CONTEXT ),
@@ -207,7 +211,8 @@ static const char *descrip =
 "      'E' -- select an empty pinless conference\n"
 "      'i' -- announce user join/leave with review\n"
 "      'I' -- announce user join/leave without review\n"
 "      'E' -- select an empty pinless conference\n"
 "      'i' -- announce user join/leave with review\n"
 "      'I' -- announce user join/leave without review\n"
-"      'm' -- set monitor only mode (Listen only, no talking)\n"
+"      'l' -- set listen only mode (Listen only, no talking)\n"
+"      'm' -- set initially muted by admin\n"
 "      'M' -- enable music on hold when the conference has a single caller\n"
 "      'o' -- set talker optimization - treats talkers who aren't speaking as\n"
 "             being muted, meaning (a) No encode is done on transmission and\n"
 "      'M' -- enable music on hold when the conference has a single caller\n"
 "      'o' -- set talker optimization - treats talkers who aren't speaking as\n"
 "             being muted, meaning (a) No encode is done on transmission and\n"
@@ -948,7 +953,7 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, int c
 
        user->chan = chan;
        user->userflags = confflags;
 
        user->chan = chan;
        user->userflags = confflags;
-       user->adminflags = 0;
+       user->adminflags = (confflags & CONFFLAG_STARTMUTED) ? ADMINFLAG_MUTED : 0;
        user->talking = -1;
        conf->users++;
        /* Update table */
        user->talking = -1;
        conf->users++;
        /* Update table */
@@ -1298,39 +1303,51 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, int c
                                break;
                        }
        
                                break;
                        }
        
-                       /* Check if the admin changed my modes */
-                       if (user->adminflags) {                 
-                               /* Set the new modes */
-                               if ((user->adminflags & ADMINFLAG_MUTED) && (ztc.confmode & ZT_CONF_TALKER)) {
-                                       ztc.confmode ^= ZT_CONF_TALKER;
-                                       if (ioctl(fd, ZT_SETCONF, &ztc)) {
-                                               ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n");
-                                               ret = -1;
-                                               break;
-                                       }
-                               }
-                               if (!(user->adminflags & ADMINFLAG_MUTED) && !(confflags & CONFFLAG_MONITOR) && !(ztc.confmode & ZT_CONF_TALKER)) {
-                                       ztc.confmode |= ZT_CONF_TALKER;
-                                       if (ioctl(fd, ZT_SETCONF, &ztc)) {
-                                               ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n");
-                                               ret = -1;
-                                               break;
-                                       }
-                               }
-                               if (user->adminflags & ADMINFLAG_KICKME) {
-                                       /* You have been kicked. */
-                                       if (!ast_streamfile(chan, "conf-kicked", chan->language))
-                                               ast_waitstream(chan, "");
-                                       ret = 0;
+                       /* Check if my modes have changed */
+
+                       /* If I should be muted but am still talker, mute me */
+                       if ((user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) && (ztc.confmode & ZT_CONF_TALKER)) {
+                               ztc.confmode ^= ZT_CONF_TALKER;
+                               if (ioctl(fd, ZT_SETCONF, &ztc)) {
+                                       ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n");
+                                       ret = -1;
                                        break;
                                }
                                        break;
                                }
-                       } else if (!(confflags & CONFFLAG_MONITOR) && !(ztc.confmode & ZT_CONF_TALKER)) {
+
+                               manager_event(EVENT_FLAG_CALL, "MeetmeMute", 
+                                               "Channel: %s\r\n"
+                                               "Uniqueid: %s\r\n"
+                                               "Meetme: %s\r\n"
+                                               "Usernum: %i\r\n"
+                                               "Status: on\r\n",
+                                               chan->name, chan->uniqueid, conf->confno, user->user_no);
+                       }
+
+                       /* If I should be un-muted but am not talker, un-mute me */
+                       if (!(user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) && !(confflags & CONFFLAG_MONITOR) && !(ztc.confmode & ZT_CONF_TALKER)) {
                                ztc.confmode |= ZT_CONF_TALKER;
                                if (ioctl(fd, ZT_SETCONF, &ztc)) {
                                        ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n");
                                        ret = -1;
                                        break;
                                }
                                ztc.confmode |= ZT_CONF_TALKER;
                                if (ioctl(fd, ZT_SETCONF, &ztc)) {
                                        ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n");
                                        ret = -1;
                                        break;
                                }
+
+                               manager_event(EVENT_FLAG_CALL, "MeetmeMute", 
+                                               "Channel: %s\r\n"
+                                               "Uniqueid: %s\r\n"
+                                               "Meetme: %s\r\n"
+                                               "Usernum: %i\r\n"
+                                               "Status: off\r\n",
+                                               chan->name, chan->uniqueid, conf->confno, user->user_no);
+                       }
+
+                       /* If I have been kicked, exit the conference */
+                       if (user->adminflags & ADMINFLAG_KICKME) {
+                               //You have been kicked.
+                               if (!ast_streamfile(chan, "conf-kicked", chan->language))
+                                       ast_waitstream(chan, "");
+                               ret = 0;
+                               break;
                        }
 
                        if (c) {
                        }
 
                        if (c) {
@@ -1369,17 +1386,19 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, int c
                                                                      "Channel: %s\r\n"
                                                                      "Uniqueid: %s\r\n"
                                                                      "Meetme: %s\r\n"
                                                                      "Channel: %s\r\n"
                                                                      "Uniqueid: %s\r\n"
                                                                      "Meetme: %s\r\n"
-                                                                     "Usernum: %d\r\n",
+                                                                     "Usernum: %d\r\n"
+                                                                     "Status: on\r\n",
                                                                      chan->name, chan->uniqueid, conf->confno, user->user_no);
                                                }
                                                if (user->talking && totalsilence > MEETME_DELAYDETECTENDTALK) {
                                                        user->talking = 0;
                                                        if (confflags & CONFFLAG_MONITORTALKER)
                                                                      chan->name, chan->uniqueid, conf->confno, user->user_no);
                                                }
                                                if (user->talking && totalsilence > MEETME_DELAYDETECTENDTALK) {
                                                        user->talking = 0;
                                                        if (confflags & CONFFLAG_MONITORTALKER)
-                                                               manager_event(EVENT_FLAG_CALL, "MeetmeStopTalking",
+                                                               manager_event(EVENT_FLAG_CALL, "MeetmeTalking",
                                                                      "Channel: %s\r\n"
                                                                      "Uniqueid: %s\r\n"
                                                                      "Meetme: %s\r\n"
                                                                      "Channel: %s\r\n"
                                                                      "Uniqueid: %s\r\n"
                                                                      "Meetme: %s\r\n"
-                                                                     "Usernum: %d\r\n",
+                                                                     "Usernum: %d\r\n"
+                                                                     "Status: off\r\n",
                                                                      chan->name, chan->uniqueid, conf->confno, user->user_no);
                                                }
                                        }
                                                                      chan->name, chan->uniqueid, conf->confno, user->user_no);
                                                }
                                        }
@@ -1445,22 +1464,14 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, int c
                                                        switch(dtmf) {
                                                        case '1': /* Un/Mute */
                                                                menu_active = 0;
                                                        switch(dtmf) {
                                                        case '1': /* Un/Mute */
                                                                menu_active = 0;
-                                                               if (ztc.confmode & ZT_CONF_TALKER) {
-                                                                       ztc.confmode = ZT_CONF_CONF | ZT_CONF_LISTENER;
-                                                                       confflags |= CONFFLAG_MONITOR ^ CONFFLAG_TALKER;
-                                                               } else {
-                                                                       ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER | ZT_CONF_LISTENER;
-                                                                       confflags ^= CONFFLAG_MONITOR | CONFFLAG_TALKER;
-                                                               }
-                                                               if (ioctl(fd, ZT_SETCONF, &ztc)) {
-                                                                       ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n");
-                                                                       ret = -1;
-                                                                       break;
-                                                               }
-                                                               if (ztc.confmode & ZT_CONF_TALKER) {
+
+                                                               /* for admin, change both admin and use flags */
+                                                               if (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) {
+                                                                       user->adminflags &= ~(ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED);
                                                                        if (!ast_streamfile(chan, "conf-unmuted", chan->language))
                                                                                ast_waitstream(chan, "");
                                                                } else {
                                                                        if (!ast_streamfile(chan, "conf-unmuted", chan->language))
                                                                                ast_waitstream(chan, "");
                                                                } else {
+                                                                       user->adminflags |= (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED);
                                                                        if (!ast_streamfile(chan, "conf-muted", chan->language))
                                                                                ast_waitstream(chan, "");
                                                                }
                                                                        if (!ast_streamfile(chan, "conf-muted", chan->language))
                                                                                ast_waitstream(chan, "");
                                                                }
@@ -1525,23 +1536,16 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, int c
                                                        switch(dtmf) {
                                                        case '1': /* Un/Mute */
                                                                menu_active = 0;
                                                        switch(dtmf) {
                                                        case '1': /* Un/Mute */
                                                                menu_active = 0;
-                                                               if (ztc.confmode & ZT_CONF_TALKER) {
-                                                                       ztc.confmode = ZT_CONF_CONF | ZT_CONF_LISTENER;
-                                                                       confflags |= CONFFLAG_MONITOR ^ CONFFLAG_TALKER;
-                                                               } else if (!(user->adminflags & ADMINFLAG_MUTED)) {
-                                                                       ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER | ZT_CONF_LISTENER;
-                                                                       confflags ^= CONFFLAG_MONITOR | CONFFLAG_TALKER;
-                                                               }
-                                                               if (ioctl(fd, ZT_SETCONF, &ztc)) {
-                                                                       ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n");
-                                                                       ret = -1;
-                                                                       break;
-                                                               }
-                                                               if (ztc.confmode & ZT_CONF_TALKER) {
-                                                                       if (!ast_streamfile(chan, "conf-unmuted", chan->language))
+
+                                                               /* user can only toggle the self-muted state */
+                                                               user->adminflags ^= ADMINFLAG_SELFMUTED;
+
+                                                               /* they can't override the admin mute state */
+                                                               if (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) {
+                                                                       if (!ast_streamfile(chan, "conf-muted", chan->language))
                                                                                ast_waitstream(chan, "");
                                                                } else {
                                                                                ast_waitstream(chan, "");
                                                                } else {
-                                                                       if (!ast_streamfile(chan, "conf-muted", chan->language))
+                                                                       if (!ast_streamfile(chan, "conf-unmuted", chan->language))
                                                                                ast_waitstream(chan, "");
                                                                }
                                                                break;
                                                                                ast_waitstream(chan, "");
                                                                }
                                                                break;
@@ -2266,31 +2270,21 @@ static int admin_exec(struct ast_channel *chan, void *data) {
                        case 77: /* M: Mute */ 
                                if (user) {
                                        user->adminflags |= ADMINFLAG_MUTED;
                        case 77: /* M: Mute */ 
                                if (user) {
                                        user->adminflags |= ADMINFLAG_MUTED;
-                                       manager_event(EVENT_FLAG_CALL, "MeetmeMute",
-                                               "Status: on"
-                                               "Meetme: %s\r\n"
-                                               "Usernum: %d\r\n",
-                                               cnf->confno, user->user_no);
                                } else {
                                        ast_log(LOG_NOTICE, "Specified User not found!\n");
                                }
                                break;
                                } else {
                                        ast_log(LOG_NOTICE, "Specified User not found!\n");
                                }
                                break;
-                       case 78: /* N: Mute all users */
+                       case 78: /* N: Mute all (non-admin) users */
                                AST_LIST_TRAVERSE(&cnf->userlist, user, list) {
                                        if (!(user->userflags & CONFFLAG_ADMIN))
                                                user->adminflags |= ADMINFLAG_MUTED;
                                }
                                break;                                  
                        case 109: /* m: Unmute */ 
                                AST_LIST_TRAVERSE(&cnf->userlist, user, list) {
                                        if (!(user->userflags & CONFFLAG_ADMIN))
                                                user->adminflags |= ADMINFLAG_MUTED;
                                }
                                break;                                  
                        case 109: /* m: Unmute */ 
-                               if (user && (user->adminflags & ADMINFLAG_MUTED)) {
-                                       user->adminflags ^= ADMINFLAG_MUTED;
-                                       manager_event(EVENT_FLAG_CALL, "MeetmeMute",
-                                               "Status: off"
-                                               "Meetme: %s\r\n"
-                                               "Usernum: %d\r\n",
-                                               cnf->confno, user->user_no);
+                               if (user) {
+                                       user->adminflags &= ~ADMINFLAG_MUTED;
                                } else {
                                } else {
-                                       ast_log(LOG_NOTICE, "Specified User not found or he muted himself!\n");
+                                       ast_log(LOG_NOTICE, "Specified User not found!\n");
                                }
                                break;
                        case 110: /* n: Unmute all users */
                                }
                                break;
                        case 110: /* n: Unmute all users */
@@ -2315,6 +2309,77 @@ static int admin_exec(struct ast_channel *chan, void *data) {
        return 0;
 }
 
        return 0;
 }
 
+static int meetmemute(struct mansession *s, struct message *m, int mute)
+{
+       struct ast_conference *conf;
+       struct ast_conf_user *user;
+       char *confid = astman_get_header(m, "Meetme");
+       char *userid = astman_get_header(m, "Usernum");
+       int userno;
+
+       if (!confid || ast_strlen_zero(confid)) {
+               astman_send_error(s, m, "Meetme conference not specified");
+               return 0;
+       }
+
+       if (!userid || ast_strlen_zero(userid)) {
+               astman_send_error(s, m, "Meetme user number not specified");
+               return 0;
+       }
+
+       userno = strtoul(userid, &userid, 10);
+
+       if (*userid) {
+               astman_send_error(s, m, "Invalid user number");
+               return 0;
+       }
+
+       /* Look in the conference list */
+       AST_LIST_LOCK(&confs);
+       AST_LIST_TRAVERSE(&confs, conf, list) {
+               if (!strcmp(confid, conf->confno))
+                       break;
+       }
+
+       if (!conf) {
+               AST_LIST_UNLOCK(&confs);
+               astman_send_error(s, m, "Meetme conference does not exist");
+               return 0;
+       }
+
+       AST_LIST_TRAVERSE(&conf->userlist, user, list)
+               if (user->user_no == userno)
+                       break;
+
+       if (!user) {
+               AST_LIST_UNLOCK(&confs);
+               astman_send_error(s, m, "User number not found");
+               return 0;
+       }
+
+       if (mute)
+               user->adminflags |= ADMINFLAG_MUTED;    /* request user muting */
+       else
+               user->adminflags &= ~ADMINFLAG_MUTED;   /* request user unmuting */
+
+       AST_LIST_UNLOCK(&confs);
+
+       ast_log(LOG_NOTICE, "Requested to %smute conf %s user %d userchan %s uniqueid %s\n", mute ? "" : "un", conf->confno, user->user_no, user->chan->name, user->chan->uniqueid);
+
+       astman_send_ack(s, m, mute ? "User muted" : "User unmuted");
+       return 0;
+}
+
+static int action_meetmemute(struct mansession *s, struct message *m)
+{
+       return meetmemute(s, m, 1);
+}
+
+static int action_meetmeunmute(struct mansession *s, struct message *m)
+{
+       return meetmemute(s, m, 0);
+}
+
 static void *recordthread(void *args)
 {
        struct ast_conference *cnf = args;
 static void *recordthread(void *args)
 {
        struct ast_conference *cnf = args;
@@ -2410,6 +2475,8 @@ static int unload_module(void *mod)
        int res;
        
        res = ast_cli_unregister(&cli_conf);
        int res;
        
        res = ast_cli_unregister(&cli_conf);
+       res |= ast_manager_unregister("MeetmeMute");
+       res |= ast_manager_unregister("MeetmeUnmute");
        res |= ast_unregister_application(app3);
        res |= ast_unregister_application(app2);
        res |= ast_unregister_application(app);
        res |= ast_unregister_application(app3);
        res |= ast_unregister_application(app2);
        res |= ast_unregister_application(app);
@@ -2426,6 +2493,8 @@ static int load_module(void *mod)
        load_config();
 
        res = ast_cli_register(&cli_conf);
        load_config();
 
        res = ast_cli_register(&cli_conf);
+       res |= ast_manager_register("MeetmeMute", EVENT_FLAG_CALL, action_meetmemute, "Mute a Meetme user");
+       res |= ast_manager_register("MeetmeUnmute", EVENT_FLAG_CALL, action_meetmeunmute, "Unmute a Meetme user");
        res |= ast_register_application(app3, admin_exec, synopsis3, descrip3);
        res |= ast_register_application(app2, count_exec, synopsis2, descrip2);
        res |= ast_register_application(app, conf_exec, synopsis, descrip);
        res |= ast_register_application(app3, admin_exec, synopsis3, descrip3);
        res |= ast_register_application(app2, count_exec, synopsis2, descrip2);
        res |= ast_register_application(app, conf_exec, synopsis, descrip);