]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
confbridge: Separate user muting from system muting overrides.
authorRichard Mudgett <rmudgett@digium.com>
Sat, 2 Nov 2013 03:21:17 +0000 (03:21 +0000)
committerRichard Mudgett <rmudgett@digium.com>
Sat, 2 Nov 2013 03:21:17 +0000 (03:21 +0000)
The system overrides the user muting requests when MOH is playing or a
waitmarked user is waiting for a marked user to join.  System muting
overrides interfere with what the user may wish the muting to be when the
system override ends.

* User muting requests are now independent of the system muting overrides.
The effective muting is now the logical or of the user request and system
override.

* Added a Muted flag to the CLI "confbridge list <conference>" command.

* Added a Muted header to the AMI ConfbridgeList action ConfbridgeList
event.

(closes issue AST-1102)
Reported by: John Bigelow

Review: https://reviewboard.asterisk.org/r/2960/
........

Merged revisions 402425 from http://svn.asterisk.org/svn/asterisk/branches/11

git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/12@402427 65c4cc65-6c06-0410-ace0-fbb531ad65f3

apps/app_confbridge.c
apps/confbridge/conf_state.c
apps/confbridge/conf_state_inactive.c
apps/confbridge/conf_state_multi.c
apps/confbridge/conf_state_multi_marked.c
apps/confbridge/conf_state_single.c
apps/confbridge/conf_state_single_marked.c
apps/confbridge/include/confbridge.h

index 6f1420fcd21be332d3283e9f2d7b2e78eb2e5e3a..d271ce5ffd8c74176352c7dc413bc37e438fb6e5 100644 (file)
@@ -963,6 +963,32 @@ static int handle_conf_user_leave(struct confbridge_user *user)
        return 0;
 }
 
+void conf_update_user_mute(struct confbridge_user *user)
+{
+       int mute_user;
+       int mute_system;
+       int mute_effective;
+
+       /* User level mute request. */
+       mute_user = user->muted;
+
+       /* System level mute request. */
+       mute_system = user->playing_moh
+               /*
+                * Do not allow waitmarked users to talk to anyone unless there
+                * is a marked user present.
+                */
+               || (!user->conference->markedusers
+                       && ast_test_flag(&user->u_profile, USER_OPT_WAITMARKED));
+
+       mute_effective = mute_user || mute_system;
+
+       ast_debug(1, "User %s is %s: user:%d system:%d.\n",
+               ast_channel_name(user->chan), mute_effective ? "muted" : "unmuted",
+               mute_user, mute_system);
+       user->features.mute = mute_effective;
+}
+
 void conf_moh_stop(struct confbridge_user *user)
 {
        user->playing_moh = 0;
@@ -1108,9 +1134,7 @@ void conf_handle_second_active(struct confbridge_conference *conference)
        if (ast_test_flag(&first_user->u_profile, USER_OPT_MUSICONHOLD)) {
                conf_moh_stop(first_user);
        }
-       if (!ast_test_flag(&first_user->u_profile, USER_OPT_STARTMUTED)) {
-               first_user->features.mute = 0;
-       }
+       conf_update_user_mute(first_user);
 }
 
 void conf_ended(struct confbridge_conference *conference)
@@ -1630,7 +1654,8 @@ static int confbridge_exec(struct ast_channel *chan, const char *data)
 
        /* If the caller should be joined already muted, make it so */
        if (ast_test_flag(&user.u_profile, USER_OPT_STARTMUTED)) {
-               user.features.mute = 1;
+               /* Set user level mute request. */
+               user.muted = 1;
        }
 
        if (ast_test_flag(&user.u_profile, USER_OPT_DROP_SILENCE)) {
@@ -1748,17 +1773,28 @@ static int action_toggle_mute(struct confbridge_conference *conference,
        struct confbridge_user *user,
        struct ast_channel *chan)
 {
-       /* Mute or unmute yourself, note we only allow manipulation if they aren't waiting for a marked user or if marked users exist */
-       if (!ast_test_flag(&user->u_profile, USER_OPT_WAITMARKED) || conference->markedusers) {
-               user->features.mute = (!user->features.mute ? 1 : 0);
-               ast_test_suite_event_notify("CONF_MUTE", "Message: participant %s %s\r\nConference: %s\r\nChannel: %s", ast_channel_name(chan), user->features.mute ? "muted" : "unmuted", user->b_profile.name, ast_channel_name(chan));
-               if (user->features.mute) {
-                       send_mute_event(chan, conference);
-               } else {
-                       send_unmute_event(chan, conference);
-               }
+       int mute;
+
+       /* Toggle user level mute request. */
+       mute = !user->muted;
+       user->muted = mute;
+
+       conf_update_user_mute(user);
+       ast_test_suite_event_notify("CONF_MUTE",
+               "Message: participant %s %s\r\n"
+               "Conference: %s\r\n"
+               "Channel: %s",
+               ast_channel_name(chan),
+               mute ? "muted" : "unmuted",
+               user->b_profile.name,
+               ast_channel_name(chan));
+       if (mute) {
+               send_mute_event(chan, conference);
+       } else {
+               send_unmute_event(chan, conference);
        }
-       return ast_stream_and_wait(chan, (user->features.mute ?
+
+       return ast_stream_and_wait(chan, (mute ?
                conf_get_sound(CONF_SOUND_MUTED, user->b_profile.sounds) :
                conf_get_sound(CONF_SOUND_UNMUTED, user->b_profile.sounds)),
                "");
@@ -1768,22 +1804,27 @@ static int action_toggle_mute_participants(struct confbridge_conference *confere
 {
        struct confbridge_user *cur_user = NULL;
        const char *sound_to_play;
+       int mute;
 
        ao2_lock(conference);
 
-       /* If already muted, then unmute */
-       conference->muted = conference->muted ? 0 : 1;
-       sound_to_play = conf_get_sound((conference->muted ? CONF_SOUND_PARTICIPANTS_MUTED : CONF_SOUND_PARTICIPANTS_UNMUTED),
-               user->b_profile.sounds);
+       /* Toggle bridge level mute request. */
+       mute = !conference->muted;
+       conference->muted = mute;
 
        AST_LIST_TRAVERSE(&conference->active_list, cur_user, list) {
                if (!ast_test_flag(&cur_user->u_profile, USER_OPT_ADMIN)) {
-                       cur_user->features.mute = conference->muted;
+                       /* Set user level to bridge level mute request. */
+                       cur_user->muted = mute;
+                       conf_update_user_mute(cur_user);
                }
        }
 
        ao2_unlock(conference);
 
+       sound_to_play = conf_get_sound((mute ? CONF_SOUND_PARTICIPANTS_MUTED : CONF_SOUND_PARTICIPANTS_UNMUTED),
+               user->b_profile.sounds);
+
        /* The host needs to hear it seperately, as they don't get the audio from play_sound_helper */
        ast_stream_and_wait(user->chan, sound_to_play, "");
 
@@ -2203,7 +2244,7 @@ static char *handle_cli_confbridge_kick(struct ast_cli_entry *e, int cmd, struct
 
 static void handle_cli_confbridge_list_item(struct ast_cli_args *a, struct confbridge_user *user, int waiting)
 {
-       char flag_str[5 + 1];/* Max flags + terminator */
+       char flag_str[6 + 1];/* Max flags + terminator */
        int pos = 0;
 
        /* Build flags column string. */
@@ -2219,18 +2260,22 @@ static void handle_cli_confbridge_list_item(struct ast_cli_args *a, struct confb
        if (ast_test_flag(&user->u_profile, USER_OPT_ENDMARKED)) {
                flag_str[pos++] = 'E';
        }
+       if (user->muted) {
+               flag_str[pos++] = 'm';
+       }
        if (waiting) {
                flag_str[pos++] = 'w';
        }
        flag_str[pos] = '\0';
 
-       ast_cli(a->fd, "%-29s ", ast_channel_name(user->chan));
-       ast_cli(a->fd, "%-5s ", flag_str);
-       ast_cli(a->fd, "%-17s", user->u_profile.name);
-       ast_cli(a->fd, "%-17s", user->b_profile.name);
-       ast_cli(a->fd, "%-17s", user->menu_name);
-       ast_cli(a->fd, "%-17s", S_COR(ast_channel_caller(user->chan)->id.number.valid, ast_channel_caller(user->chan)->id.number.str, "<unknown>"));
-       ast_cli(a->fd, "\n");
+       ast_cli(a->fd, "%-30s %-6s %-16s %-16s %-16s %s\n",
+               ast_channel_name(user->chan),
+               flag_str,
+               user->u_profile.name,
+               user->b_profile.name,
+               user->menu_name,
+               S_COR(ast_channel_caller(user->chan)->id.number.valid,
+                       ast_channel_caller(user->chan)->id.number.str, "<unknown>"));
 }
 
 static char *handle_cli_confbridge_list(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
@@ -2252,6 +2297,7 @@ static char *handle_cli_confbridge_list(struct ast_cli_entry *e, int cmd, struct
                        "         M - The user is a marked user\n"
                        "         W - The user must wait for a marked user to join\n"
                        "         E - The user will be kicked after the last marked user leaves the conference\n"
+                       "         m - The user is muted\n"
                        "         w - The user is waiting for a marked user to join\n";
                return NULL;
        case CLI_GENERATE:
@@ -2283,8 +2329,8 @@ static char *handle_cli_confbridge_list(struct ast_cli_entry *e, int cmd, struct
                        ast_cli(a->fd, "No conference bridge named '%s' found!\n", a->argv[2]);
                        return CLI_SUCCESS;
                }
-               ast_cli(a->fd, "Channel                       Flags User Profile     Bridge Profile   Menu             CallerID\n");
-               ast_cli(a->fd, "============================= ===== ================ ================ ================ ================\n");
+               ast_cli(a->fd, "Channel                        Flags  User Profile     Bridge Profile   Menu             CallerID\n");
+               ast_cli(a->fd, "============================== ====== ================ ================ ================ ================\n");
                ao2_lock(conference);
                AST_LIST_TRAVERSE(&conference->active_list, user, list) {
                        handle_cli_confbridge_list_item(a, user, 0);
@@ -2348,14 +2394,23 @@ static int generic_mute_unmute_helper(int mute, const char *conference_name, con
                }
        }
        if (user) {
-               user->features.mute = mute;
-               ast_channel_lock(user->chan);
-               if (user->features.mute) {
+               /* Set user level mute request. */
+               user->muted = mute ? 1 : 0;
+
+               conf_update_user_mute(user);
+               ast_test_suite_event_notify("CONF_MUTE",
+                       "Message: participant %s %s\r\n"
+                       "Conference: %s\r\n"
+                       "Channel: %s",
+                       ast_channel_name(user->chan),
+                       mute ? "muted" : "unmuted",
+                       conference->b_profile.name,
+                       ast_channel_name(user->chan));
+               if (mute) {
                        send_mute_event(user->chan, conference);
                } else {
                        send_unmute_event(user->chan, conference);
                }
-               ast_channel_unlock(user->chan);
        } else {
                res = -2;;
        }
@@ -2614,6 +2669,7 @@ static void action_confbridgelist_item(struct mansession *s, const char *id_text
                "WaitMarked: %s\r\n"
                "EndMarked: %s\r\n"
                "Waiting: %s\r\n"
+               "Muted: %s\r\n"
                "\r\n",
                id_text,
                conference->name,
@@ -2624,7 +2680,8 @@ static void action_confbridgelist_item(struct mansession *s, const char *id_text
                ast_test_flag(&user->u_profile, USER_OPT_MARKEDUSER) ? "Yes" : "No",
                ast_test_flag(&user->u_profile, USER_OPT_WAITMARKED) ? "Yes" : "No",
                ast_test_flag(&user->u_profile, USER_OPT_ENDMARKED) ? "Yes" : "No",
-               waiting ? "Yes" : "No");
+               waiting ? "Yes" : "No",
+               user->muted ? "Yes" : "No");
 }
 
 static int action_confbridgelist(struct mansession *s, const struct message *m)
@@ -3057,11 +3114,11 @@ void conf_mute_only_active(struct confbridge_conference *conference)
 {
        struct confbridge_user *only_user = AST_LIST_FIRST(&conference->active_list);
 
-       /* Turn on MOH/mute if the single participant is set up for it */
+       /* Turn on MOH if the single participant is set up for it */
        if (ast_test_flag(&only_user->u_profile, USER_OPT_MUSICONHOLD)) {
-               only_user->features.mute = 1;
                conf_moh_start(only_user);
        }
+       conf_update_user_mute(only_user);
 }
 
 void conf_remove_user_waiting(struct confbridge_conference *conference, struct confbridge_user *user)
index 988e2e25070ed4628eaa9bacf8a26df03325d18f..03dd7d9af978fb5972c5fa9e008f4524f2c3ed01 100644 (file)
@@ -57,12 +57,11 @@ void conf_invalid_event_fn(struct confbridge_user *user)
  */
 static void conf_mute_moh_inactive_waitmarked(struct confbridge_user *user)
 {
-       /* Be sure we are muted so we can't talk to anybody else waiting */
-       user->features.mute = 1;
        /* Start music on hold if needed */
        if (ast_test_flag(&user->u_profile, USER_OPT_MUSICONHOLD)) {
                conf_moh_start(user);
        }
+       conf_update_user_mute(user);
 }
 
 void conf_default_join_waitmarked(struct confbridge_user *user)
index 28447983deca0d8a78ac1a0e69e33021b0798b7f..379f071a50dbb958b89a0ffb5b9940c076969d25 100644 (file)
@@ -61,7 +61,7 @@ static void join_unmarked(struct confbridge_user *user)
 static void join_marked(struct confbridge_user *user)
 {
        conf_add_user_marked(user->conference, user);
-       conf_handle_second_active(user->conference);
+       conf_update_user_mute(user);
 
        conf_change_state(user, CONF_STATE_MULTI_MARKED);
 }
index 70098158b78ff1f0fbb7a714c3ef40e1e5c4c672..8297742530663a72fe907e0b9f23d1a0940cee89 100644 (file)
@@ -54,11 +54,13 @@ struct confbridge_state *CONF_STATE_MULTI = &STATE_MULTI;
 static void join_unmarked(struct confbridge_user *user)
 {
        conf_add_user_active(user->conference, user);
+       conf_update_user_mute(user);
 }
 
 static void join_marked(struct confbridge_user *user)
 {
        conf_add_user_marked(user->conference, user);
+       conf_update_user_mute(user);
 
        conf_change_state(user, CONF_STATE_MULTI_MARKED);
 }
index 2739be55b64371e03ac96a3f567a13d51d2a699d..a469cf737dfe9276952b8b31d311c41cbf90b25c 100644 (file)
@@ -60,11 +60,13 @@ struct confbridge_state *CONF_STATE_MULTI_MARKED = &STATE_MULTI_MARKED;
 static void join_active(struct confbridge_user *user)
 {
        conf_add_user_active(user->conference, user);
+       conf_update_user_mute(user);
 }
 
 static void join_marked(struct confbridge_user *user)
 {
        conf_add_user_marked(user->conference, user);
+       conf_update_user_mute(user);
 }
 
 static void leave_active(struct confbridge_user *user)
@@ -95,8 +97,8 @@ static void leave_marked(struct confbridge_user *user)
                AST_LIST_TRAVERSE_SAFE_BEGIN(&user->conference->active_list, user_iter, list) {
                        /* Kick ENDMARKED user_iters */
                        if (ast_test_flag(&user_iter->u_profile, USER_OPT_ENDMARKED)) {
-                               if (ast_test_flag(&user_iter->u_profile, USER_OPT_WAITMARKED) &&
-                                                 !ast_test_flag(&user_iter->u_profile, USER_OPT_MARKEDUSER)) {
+                               if (ast_test_flag(&user_iter->u_profile, USER_OPT_WAITMARKED)
+                                       && !ast_test_flag(&user_iter->u_profile, USER_OPT_MARKEDUSER)) {
                                        AST_LIST_REMOVE_CURRENT(list);
                                        user_iter->conference->activeusers--;
                                        AST_LIST_INSERT_TAIL(&user_iter->conference->waiting_list, user_iter, list);
@@ -104,17 +106,18 @@ static void leave_marked(struct confbridge_user *user)
                                }
                                user_iter->kicked = 1;
                                ast_bridge_remove(user_iter->conference->bridge, user_iter->chan);
-                       } else if (ast_test_flag(&user_iter->u_profile, USER_OPT_WAITMARKED) &&
-                                       !ast_test_flag(&user_iter->u_profile, USER_OPT_MARKEDUSER)) {
+                       } else if (ast_test_flag(&user_iter->u_profile, USER_OPT_WAITMARKED)
+                               && !ast_test_flag(&user_iter->u_profile, USER_OPT_MARKEDUSER)) {
                                AST_LIST_REMOVE_CURRENT(list);
                                user_iter->conference->activeusers--;
                                AST_LIST_INSERT_TAIL(&user_iter->conference->waiting_list, user_iter, list);
                                user_iter->conference->waitingusers++;
-                               /* Handle muting/moh of user_iter if necessary */
+
+                               /* Handle moh of user_iter if necessary */
                                if (ast_test_flag(&user_iter->u_profile, USER_OPT_MUSICONHOLD)) {
-                                       user_iter->features.mute = 1;
                                        conf_moh_start(user_iter);
                                }
+                               conf_update_user_mute(user_iter);
                        }
                }
                AST_LIST_TRAVERSE_SAFE_END;
@@ -170,7 +173,7 @@ static void transition_to_marked(struct confbridge_user *user)
                conf_handle_first_marked_common(user);
        }
 
-       /* Move all waiting users to active, stopping MOH and umuting if necessary */
+       /* Move all waiting users to active, stopping MOH and unmuting if necessary */
        AST_LIST_TRAVERSE_SAFE_BEGIN(&user->conference->waiting_list, user_iter, list) {
                AST_LIST_REMOVE_CURRENT(list);
                user->conference->waitingusers--;
@@ -179,10 +182,7 @@ static void transition_to_marked(struct confbridge_user *user)
                if (user_iter->playing_moh) {
                        conf_moh_stop(user_iter);
                }
-               /* only unmute them if they are not supposed to start muted */
-               if (!ast_test_flag(&user_iter->u_profile, USER_OPT_STARTMUTED)) {
-                       user_iter->features.mute = 0;
-               }
+               conf_update_user_mute(user_iter);
        }
        AST_LIST_TRAVERSE_SAFE_END;
 }
index 2d01420b080bcf890feda2f14d12eb1730b2fd2a..e3e0ca11c5587416c0fe1e119194787ee0fda755 100644 (file)
@@ -55,6 +55,7 @@ static void join_unmarked(struct confbridge_user *user)
 {
        conf_add_user_active(user->conference, user);
        conf_handle_second_active(user->conference);
+       conf_update_user_mute(user);
 
        conf_change_state(user, CONF_STATE_MULTI);
 }
@@ -63,6 +64,7 @@ static void join_marked(struct confbridge_user *user)
 {
        conf_add_user_marked(user->conference, user);
        conf_handle_second_active(user->conference);
+       conf_update_user_mute(user);
 
        conf_change_state(user, CONF_STATE_MULTI_MARKED);
 }
index 340245831e275325c3682403c97dfa0dcdd822a8..f72ef5ec19e42685ca991826ab095e95d385c411 100644 (file)
@@ -54,6 +54,7 @@ static void join_active(struct confbridge_user *user)
 {
        conf_add_user_active(user->conference, user);
        conf_handle_second_active(user->conference);
+       conf_update_user_mute(user);
 
        conf_change_state(user, CONF_STATE_MULTI_MARKED);
 }
@@ -62,6 +63,7 @@ static void join_marked(struct confbridge_user *user)
 {
        conf_add_user_marked(user->conference, user);
        conf_handle_second_active(user->conference);
+       conf_update_user_mute(user);
 
        conf_change_state(user, CONF_STATE_MULTI_MARKED);
 }
index 71ae5f7de37e5d8394013e9230b33f9a976359ab..5f94cd5ee6e06c7f530f79c3d26273ced8bc3986 100644 (file)
@@ -241,6 +241,7 @@ struct confbridge_user {
        struct ast_bridge_features features;         /*!< Bridge features structure */
        struct ast_bridge_tech_optimizations tech_args; /*!< Bridge technology optimizations for talk detection */
        unsigned int suspended_moh;                  /*!< Count of active suspended MOH actions. */
+       unsigned int muted:1;                        /*!< Has the user requested to be muted? */
        unsigned int kicked:1;                       /*!< User has been kicked from the conference */
        unsigned int playing_moh:1;                  /*!< MOH is currently being played to the user */
        AST_LIST_HEAD_NOLOCK(, post_join_action) post_join_list; /*!< List of sounds to play after joining */;
@@ -366,6 +367,15 @@ int play_sound_file(struct confbridge_conference *conference, const char *filena
  */
 void conf_ended(struct confbridge_conference *conference);
 
+/*!
+ * \brief Update the actual mute status of the user and set it on the bridge.
+ *
+ * \param user User to update the mute status.
+ *
+ * \return Nothing
+ */
+void conf_update_user_mute(struct confbridge_user *user);
+
 /*!
  * \brief Stop MOH for the conference user.
  *