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;
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)
/* 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)) {
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)),
"");
{
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, "");
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)
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);
}
}
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;;
}
"Channel: %s\r\n"
"Admin: %s\r\n"
"MarkedUser: %s\r\n"
+ "Muted: %s\r\n"
"\r\n",
id_text,
bridge->name,
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)
{
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)
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)
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);
}
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;
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--;
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;
}