[Asterisk-code-review] confbridge: Separate user muting from system muting overrides. (asterisk[certified/11.6])

Richard Mudgett asteriskteam at digium.com
Wed Jan 27 17:24:25 CST 2016


Richard Mudgett has uploaded a new change for review.

  https://gerrit.asterisk.org/2118

Change subject: confbridge: Separate user muting from system muting overrides.
......................................................................

confbridge: Separate user muting from system muting overrides.

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 column 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/

Cherry-picked to support ASTERISK-20987

Change-Id: Iec7bd77736847af6a5f70b8d279f85c6e2082ee2
---
M apps/app_confbridge.c
M apps/confbridge/conf_state.c
M apps/confbridge/conf_state_inactive.c
M apps/confbridge/conf_state_multi.c
M apps/confbridge/conf_state_multi_marked.c
M apps/confbridge/conf_state_single.c
M apps/confbridge/conf_state_single_marked.c
M apps/confbridge/include/confbridge.h
8 files changed, 113 insertions(+), 43 deletions(-)


  git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/18/2118/1

diff --git a/apps/app_confbridge.c b/apps/app_confbridge.c
index b08af53..ef27a2e 100644
--- a/apps/app_confbridge.c
+++ b/apps/app_confbridge.c
@@ -960,6 +960,32 @@
 	return 0;
 }
 
+void conf_update_user_mute(struct conference_bridge_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_bridge->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 conference_bridge_user *user)
 {
 	user->playing_moh = 0;
@@ -1105,9 +1131,7 @@
 	if (ast_test_flag(&first_participant->u_profile, USER_OPT_MUSICONHOLD)) {
 		conf_moh_stop(first_participant);
 	}
-	if (!ast_test_flag(&first_participant->u_profile, USER_OPT_STARTMUTED)) {
-		first_participant->features.mute = 0;
-	}
+	conf_update_user_mute(first_participant);
 }
 
 void conf_ended(struct conference_bridge *conference_bridge)
@@ -1652,7 +1676,8 @@
 
 	/* If the caller should be joined already muted, make it so */
 	if (ast_test_flag(&conference_bridge_user.u_profile, USER_OPT_STARTMUTED)) {
-		conference_bridge_user.features.mute = 1;
+		/* Set user level mute request. */
+		conference_bridge_user.muted = 1;
 	}
 
 	if (ast_test_flag(&conference_bridge_user.u_profile, USER_OPT_DROP_SILENCE)) {
@@ -1769,12 +1794,23 @@
 	struct conference_bridge_user *conference_bridge_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(&conference_bridge_user->u_profile, USER_OPT_WAITMARKED) || conference_bridge->markedusers) {
-		conference_bridge_user->features.mute = (!conference_bridge_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), conference_bridge_user->features.mute ? "muted" : "unmuted", conference_bridge_user->b_profile.name, ast_channel_name(chan));
-	}
-	return ast_stream_and_wait(chan, (conference_bridge_user->features.mute ?
+	int mute;
+
+	/* Toggle user level mute request. */
+	mute = !conference_bridge_user->muted;
+	conference_bridge_user->muted = mute;
+
+	conf_update_user_mute(conference_bridge_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",
+		conference_bridge_user->b_profile.name,
+		ast_channel_name(chan));
+
+	return ast_stream_and_wait(chan, (mute ?
 		conf_get_sound(CONF_SOUND_MUTED, conference_bridge_user->b_profile.sounds) :
 		conf_get_sound(CONF_SOUND_UNMUTED, conference_bridge_user->b_profile.sounds)),
 		"");
@@ -1784,21 +1820,26 @@
 {
 	struct conference_bridge_user *participant = NULL;
 	const char *sound_to_play;
+	int mute;
 
 	ao2_lock(conference_bridge);
 
-	/* If already muted, then unmute */
-	conference_bridge->muted = conference_bridge->muted ? 0 : 1;
-	sound_to_play = conf_get_sound((conference_bridge->muted ? CONF_SOUND_PARTICIPANTS_MUTED : CONF_SOUND_PARTICIPANTS_UNMUTED),
-		conference_bridge_user->b_profile.sounds);
+	/* Toggle bridge level mute request. */
+	mute = !conference_bridge->muted;
+	conference_bridge->muted = mute;
 
 	AST_LIST_TRAVERSE(&conference_bridge->active_list, participant, list) {
 		if (!ast_test_flag(&participant->u_profile, USER_OPT_ADMIN)) {
-			participant->features.mute = conference_bridge->muted;
+			/* Set user level to bridge level mute request. */
+			participant->muted = mute;
+			conf_update_user_mute(participant);
 		}
 	}
 
 	ao2_unlock(conference_bridge);
+
+	sound_to_play = conf_get_sound((mute ? CONF_SOUND_PARTICIPANTS_MUTED : CONF_SOUND_PARTICIPANTS_UNMUTED),
+		conference_bridge_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(conference_bridge_user->chan, sound_to_play, "");
@@ -2219,12 +2260,14 @@
 
 static void handle_cli_confbridge_list_item(struct ast_cli_args *a, struct conference_bridge_user *participant)
 {
-	ast_cli(a->fd, "%-29s ", ast_channel_name(participant->chan));
-	ast_cli(a->fd, "%-17s", participant->u_profile.name);
-	ast_cli(a->fd, "%-17s", participant->b_profile.name);
-	ast_cli(a->fd, "%-17s", participant->menu_name);
-	ast_cli(a->fd, "%-17s", S_COR(ast_channel_caller(participant->chan)->id.number.valid, ast_channel_caller(participant->chan)->id.number.str, "<unknown>"));
-	ast_cli(a->fd, "\n");
+	ast_cli(a->fd, "%-30s %-16s %-16s %-16s %-16s %s\n",
+		ast_channel_name(participant->chan),
+		participant->u_profile.name,
+		participant->b_profile.name,
+		participant->menu_name,
+		S_COR(ast_channel_caller(participant->chan)->id.number.valid,
+			ast_channel_caller(participant->chan)->id.number.str, "<unknown>"),
+		AST_CLI_YESNO(participant->muted));
 }
 
 static char *handle_cli_confbridge_list(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
@@ -2267,8 +2310,8 @@
 			ast_cli(a->fd, "No conference bridge named '%s' found!\n", a->argv[2]);
 			return CLI_SUCCESS;
 		}
-		ast_cli(a->fd, "Channel                       User Profile     Bridge Profile   Menu             CallerID\n");
-		ast_cli(a->fd, "============================= ================ ================ ================ ================\n");
+		ast_cli(a->fd, "Channel                        User Profile     Bridge Profile   Menu             CallerID         Muted\n");
+		ast_cli(a->fd, "============================== ================ ================ ================ ================ =====\n");
 		ao2_lock(bridge);
 		AST_LIST_TRAVERSE(&bridge->active_list, participant, list) {
 			handle_cli_confbridge_list_item(a, participant);
@@ -2335,8 +2378,18 @@
 		}
 	}
 	if (participant) {
-		participant->features.mute = mute;
-		ast_test_suite_event_notify("CONF_MUTE", "Message: participant %s %s\r\nConference: %s\r\nChannel: %s", ast_channel_name(participant->chan), participant->features.mute ? "muted" : "unmuted", bridge->b_profile.name, ast_channel_name(participant->chan));
+		/* Set user level mute request. */
+		participant->muted = mute ? 1 : 0;
+
+		conf_update_user_mute(participant);
+		ast_test_suite_event_notify("CONF_MUTE",
+			"Message: participant %s %s\r\n"
+			"Conference: %s\r\n"
+			"Channel: %s",
+			ast_channel_name(participant->chan),
+			mute ? "muted" : "unmuted",
+			bridge->b_profile.name,
+			ast_channel_name(participant->chan));
 	} else {
 		res = -2;;
 	}
@@ -2596,6 +2649,7 @@
 		"Channel: %s\r\n"
 		"Admin: %s\r\n"
 		"MarkedUser: %s\r\n"
+		"Muted: %s\r\n"
 		"\r\n",
 		id_text,
 		bridge->name,
@@ -2603,7 +2657,8 @@
 		S_COR(ast_channel_caller(participant->chan)->id.name.valid, ast_channel_caller(participant->chan)->id.name.str, "<no name>"),
 		ast_channel_name(participant->chan),
 		ast_test_flag(&participant->u_profile, USER_OPT_ADMIN) ? "Yes" : "No",
-		ast_test_flag(&participant->u_profile, USER_OPT_MARKEDUSER) ? "Yes" : "No");
+		ast_test_flag(&participant->u_profile, USER_OPT_MARKEDUSER) ? "Yes" : "No",
+		participant->muted ? "Yes" : "No");
 }
 
 static int action_confbridgelist(struct mansession *s, const struct message *m)
@@ -3051,11 +3106,11 @@
 {
 	struct conference_bridge_user *only_participant = AST_LIST_FIRST(&conference_bridge->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_participant->u_profile, USER_OPT_MUSICONHOLD)) {
-		only_participant->features.mute = 1;
 		conf_moh_start(only_participant);
 	}
+	conf_update_user_mute(only_participant);
 }
 
 void conf_remove_user_waiting(struct conference_bridge *conference_bridge, struct conference_bridge_user *cbu)
diff --git a/apps/confbridge/conf_state.c b/apps/confbridge/conf_state.c
index ea5ab10..5b3893f 100644
--- a/apps/confbridge/conf_state.c
+++ b/apps/confbridge/conf_state.c
@@ -57,12 +57,11 @@
  */
 static void conf_mute_moh_inactive_waitmarked(struct conference_bridge_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 conference_bridge_user *cbu)
diff --git a/apps/confbridge/conf_state_inactive.c b/apps/confbridge/conf_state_inactive.c
index 80210fc..31cc6f1 100644
--- a/apps/confbridge/conf_state_inactive.c
+++ b/apps/confbridge/conf_state_inactive.c
@@ -61,7 +61,7 @@
 static void join_marked(struct conference_bridge_user *cbu)
 {
 	conf_add_user_marked(cbu->conference_bridge, cbu);
-	conf_handle_second_active(cbu->conference_bridge);
+	conf_update_user_mute(cbu);
 
 	conf_change_state(cbu, CONF_STATE_MULTI_MARKED);
 }
diff --git a/apps/confbridge/conf_state_multi.c b/apps/confbridge/conf_state_multi.c
index 5dcd8f4..689db8a 100644
--- a/apps/confbridge/conf_state_multi.c
+++ b/apps/confbridge/conf_state_multi.c
@@ -54,11 +54,13 @@
 static void join_unmarked(struct conference_bridge_user *cbu)
 {
 	conf_add_user_active(cbu->conference_bridge, cbu);
+	conf_update_user_mute(cbu);
 }
 
 static void join_marked(struct conference_bridge_user *cbu)
 {
 	conf_add_user_marked(cbu->conference_bridge, cbu);
+	conf_update_user_mute(cbu);
 
 	conf_change_state(cbu, CONF_STATE_MULTI_MARKED);
 }
diff --git a/apps/confbridge/conf_state_multi_marked.c b/apps/confbridge/conf_state_multi_marked.c
index ff4b38d..6089ac6 100644
--- a/apps/confbridge/conf_state_multi_marked.c
+++ b/apps/confbridge/conf_state_multi_marked.c
@@ -60,11 +60,13 @@
 static void join_active(struct conference_bridge_user *cbu)
 {
 	conf_add_user_active(cbu->conference_bridge, cbu);
+	conf_update_user_mute(cbu);
 }
 
 static void join_marked(struct conference_bridge_user *cbu)
 {
 	conf_add_user_marked(cbu->conference_bridge, cbu);
+	conf_update_user_mute(cbu);
 }
 
 static void leave_active(struct conference_bridge_user *cbu)
@@ -88,8 +90,8 @@
 		AST_LIST_TRAVERSE_SAFE_BEGIN(&cbu->conference_bridge->active_list, cbu_iter, list) {
 			/* Kick ENDMARKED cbu_iters */
 			if (ast_test_flag(&cbu_iter->u_profile, USER_OPT_ENDMARKED) && !cbu_iter->kicked) {
-				if (ast_test_flag(&cbu_iter->u_profile, USER_OPT_WAITMARKED) &&
-						  !ast_test_flag(&cbu_iter->u_profile, USER_OPT_MARKEDUSER)) {
+				if (ast_test_flag(&cbu_iter->u_profile, USER_OPT_WAITMARKED)
+					&& !ast_test_flag(&cbu_iter->u_profile, USER_OPT_MARKEDUSER)) {
 					AST_LIST_REMOVE_CURRENT(list);
 					cbu_iter->conference_bridge->activeusers--;
 					AST_LIST_INSERT_TAIL(&cbu_iter->conference_bridge->waiting_list, cbu_iter, list);
@@ -97,17 +99,18 @@
 				}
 				cbu_iter->kicked = 1;
 				ast_bridge_remove(cbu_iter->conference_bridge->bridge, cbu_iter->chan);
-			} else if (ast_test_flag(&cbu_iter->u_profile, USER_OPT_WAITMARKED) &&
-					!ast_test_flag(&cbu_iter->u_profile, USER_OPT_MARKEDUSER)) {
+			} else if (ast_test_flag(&cbu_iter->u_profile, USER_OPT_WAITMARKED)
+				&& !ast_test_flag(&cbu_iter->u_profile, USER_OPT_MARKEDUSER)) {
 				AST_LIST_REMOVE_CURRENT(list);
 				cbu_iter->conference_bridge->activeusers--;
 				AST_LIST_INSERT_TAIL(&cbu_iter->conference_bridge->waiting_list, cbu_iter, list);
 				cbu_iter->conference_bridge->waitingusers++;
-				/* Handle muting/moh of cbu_iter if necessary */
+
+				/* Handle moh of cbu_iter if necessary */
 				if (ast_test_flag(&cbu_iter->u_profile, USER_OPT_MUSICONHOLD)) {
-					cbu_iter->features.mute = 1;
 					conf_moh_start(cbu_iter);
 				}
+				conf_update_user_mute(cbu_iter);
 			}
 		}
 		AST_LIST_TRAVERSE_SAFE_END;
@@ -175,7 +178,7 @@
 		conf_handle_first_marked_common(cbu);
 	}
 
-	/* 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(&cbu->conference_bridge->waiting_list, cbu_iter, list) {
 		AST_LIST_REMOVE_CURRENT(list);
 		cbu->conference_bridge->waitingusers--;
@@ -184,10 +187,7 @@
 		if (cbu_iter->playing_moh) {
 			conf_moh_stop(cbu_iter);
 		}
-		/* only unmute them if they are not supposed to start muted */
-		if (!ast_test_flag(&cbu_iter->u_profile, USER_OPT_STARTMUTED)) {
-			cbu_iter->features.mute = 0;
-		}
+		conf_update_user_mute(cbu_iter);
 	}
 	AST_LIST_TRAVERSE_SAFE_END;
 }
diff --git a/apps/confbridge/conf_state_single.c b/apps/confbridge/conf_state_single.c
index 806ed63..4dd8d56 100644
--- a/apps/confbridge/conf_state_single.c
+++ b/apps/confbridge/conf_state_single.c
@@ -55,6 +55,7 @@
 {
 	conf_add_user_active(cbu->conference_bridge, cbu);
 	conf_handle_second_active(cbu->conference_bridge);
+	conf_update_user_mute(cbu);
 
 	conf_change_state(cbu, CONF_STATE_MULTI);
 }
@@ -63,6 +64,7 @@
 {
 	conf_add_user_marked(cbu->conference_bridge, cbu);
 	conf_handle_second_active(cbu->conference_bridge);
+	conf_update_user_mute(cbu);
 
 	conf_change_state(cbu, CONF_STATE_MULTI_MARKED);
 }
diff --git a/apps/confbridge/conf_state_single_marked.c b/apps/confbridge/conf_state_single_marked.c
index a7ac578..3a64a74 100644
--- a/apps/confbridge/conf_state_single_marked.c
+++ b/apps/confbridge/conf_state_single_marked.c
@@ -54,6 +54,7 @@
 {
 	conf_add_user_active(cbu->conference_bridge, cbu);
 	conf_handle_second_active(cbu->conference_bridge);
+	conf_update_user_mute(cbu);
 
 	conf_change_state(cbu, CONF_STATE_MULTI_MARKED);
 }
@@ -62,6 +63,7 @@
 {
 	conf_add_user_marked(cbu->conference_bridge, cbu);
 	conf_handle_second_active(cbu->conference_bridge);
+	conf_update_user_mute(cbu);
 
 	conf_change_state(cbu, CONF_STATE_MULTI_MARKED);
 }
diff --git a/apps/confbridge/include/confbridge.h b/apps/confbridge/include/confbridge.h
index f9fc93d..50e223e 100644
--- a/apps/confbridge/include/confbridge.h
+++ b/apps/confbridge/include/confbridge.h
@@ -210,7 +210,7 @@
 	unsigned int markedusers;                                         /*!< Number of marked users present */
 	unsigned int waitingusers;                                        /*!< Number of waiting users present */
 	unsigned int locked:1;                                            /*!< Is this conference bridge locked? */
-	unsigned int muted:1;                                            /*!< Is this conference bridge muted? */
+	unsigned int muted:1;                                             /*!< Is this conference bridge muted? */
 	unsigned int record_state:2;                                      /*!< Whether recording is started, stopped, or should exit */
 	struct ast_channel *playback_chan;                                /*!< Channel used for playback into the conference bridge */
 	struct ast_channel *record_chan;                                  /*!< Channel used for recording the conference */
@@ -238,6 +238,7 @@
 	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 */;
@@ -364,6 +365,15 @@
 void conf_ended(struct conference_bridge *conference_bridge);
 
 /*!
+ * \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 conference_bridge_user *user);
+
+/*!
  * \brief Stop MOH for the conference user.
  *
  * \param user Conference user to stop MOH on.

-- 
To view, visit https://gerrit.asterisk.org/2118
To unsubscribe, visit https://gerrit.asterisk.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Iec7bd77736847af6a5f70b8d279f85c6e2082ee2
Gerrit-PatchSet: 1
Gerrit-Project: asterisk
Gerrit-Branch: certified/11.6
Gerrit-Owner: Richard Mudgett <rmudgett at digium.com>



More information about the asterisk-code-review mailing list