diff --git a/apps/app_confbridge.c b/apps/app_confbridge.c
index 42c0a4c..ae26518 100644
--- a/apps/app_confbridge.c
+++ b/apps/app_confbridge.c
@@ -184,6 +184,31 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+
+ Deafen a Confbridge user.
+
+
+
+
+
+
+
+
+
+
+
+ Un
+ Undefaen a Confbridge user.
+
+
+
+
+
+
+
+
+
Kick a Confbridge user.
@@ -310,6 +335,10 @@ const char *conf_get_sound(enum conf_sounds sound, struct bridge_profile_sounds
return S_OR(custom_sounds->muted, "conf-muted");
case CONF_SOUND_UNMUTED:
return S_OR(custom_sounds->unmuted, "conf-unmuted");
+ case CONF_SOUND_DEAFENED:
+ return S_OR(custom_sounds->deafened, "conf-deafened");
+ case CONF_SOUND_UNDEAFENED:
+ return S_OR(custom_sounds->undeafened, "conf-undeafened");
case CONF_SOUND_ONLY_ONE:
return S_OR(custom_sounds->onlyone, "conf-onlyone");
case CONF_SOUND_THERE_ARE:
@@ -1416,10 +1445,13 @@ static int confbridge_exec(struct ast_channel *chan, const char *data)
volume_adjustments[0] = ast_audiohook_volume_get(chan, AST_AUDIOHOOK_DIRECTION_READ);
volume_adjustments[1] = ast_audiohook_volume_get(chan, AST_AUDIOHOOK_DIRECTION_WRITE);
- /* If the caller should be joined already muted, make it so */
+ /* If the caller should be joined already muted or deaf, make it so */
if (ast_test_flag(&conference_bridge_user.u_profile, USER_OPT_STARTMUTED)) {
conference_bridge_user.features.mute = 1;
}
+ if (ast_test_flag(&conference_bridge_user.u_profile, USER_OPT_STARTDEAF)) {
+ conference_bridge_user.features.deaf = 1;
+ }
if (ast_test_flag(&conference_bridge_user.u_profile, USER_OPT_DROP_SILENCE)) {
conference_bridge_user.tech_args.drop_silence = 1;
@@ -1548,6 +1580,19 @@ static int action_toggle_mute(struct conference_bridge *conference_bridge,
"");
}
+static int action_toggle_deaf(struct conference_bridge *conference_bridge,
+ struct conference_bridge_user *conference_bridge_user,
+ struct ast_channel *chan)
+{
+ /* Deafen or undeafen yourself */
+ conference_bridge_user->features.deaf = (!conference_bridge_user->features.deaf ? 1 : 0);
+
+ return ast_stream_and_wait(chan, (conference_bridge_user->features.deaf ?
+ conf_get_sound(CONF_SOUND_DEAFENED, conference_bridge_user->b_profile.sounds) :
+ conf_get_sound(CONF_SOUND_UNDEAFENED, conference_bridge_user->b_profile.sounds)),
+ "");
+}
+
static int action_playback(struct ast_bridge_channel *bridge_channel, const char *playback_file)
{
char *file_copy = ast_strdupa(playback_file);
@@ -1727,6 +1772,11 @@ static int execute_menu_entry(struct conference_bridge *conference_bridge,
conference_bridge_user,
bridge_channel->chan);
break;
+ case MENU_ACTION_TOGGLE_DEAF:
+ res |= action_toggle_deaf(conference_bridge,
+ conference_bridge_user,
+ bridge_channel->chan);
+ break;
case MENU_ACTION_PLAYBACK:
if (!stop_prompts) {
res |= action_playback(bridge_channel, menu_action->data.playback_file);
@@ -1988,13 +2038,13 @@ static int generic_lock_unlock_helper(int lock, const char *conference)
}
/* \internal
- * \brief finds a conference user by channel name and mutes/unmutes them.
+ * \brief finds a conference user by channel name and mutes/unmutes and deafens/undeafens them.
*
* \retval 0 success
* \retval -1 conference not found
* \retval -2 user not found
*/
-static int generic_mute_unmute_helper(int mute, const char *conference, const char *user)
+static int generic_mute_deafen_helper(int mute, int deaf, const char *conference, const char *user)
{
struct conference_bridge *bridge = NULL;
struct conference_bridge tmp;
@@ -2012,9 +2062,14 @@ static int generic_mute_unmute_helper(int mute, const char *conference, const ch
}
}
if (participant) {
- participant->features.mute = mute;
+ if (mute >= 0) {
+ participant->features.mute = mute;
+ }
+ if (deaf >= 0) {
+ participant->features.deaf = deaf;
+ }
} else {
- res = -2;;
+ res = -2;
}
ao2_unlock(bridge);
ao2_ref(bridge, -1);
@@ -2022,9 +2077,10 @@ static int generic_mute_unmute_helper(int mute, const char *conference, const ch
return res;
}
-static int cli_mute_unmute_helper(int mute, struct ast_cli_args *a)
+static int cli_mute_deafen_helper(int mute, int deaf, struct ast_cli_args *a)
{
- int res = generic_mute_unmute_helper(mute, a->argv[2], a->argv[3]);
+ const char *verb;
+ int res = generic_mute_deafen_helper(mute, deaf, a->argv[2], a->argv[3]);
if (res == -1) {
ast_cli(a->fd, "No conference bridge named '%s' found!\n", a->argv[2]);
@@ -2033,7 +2089,16 @@ static int cli_mute_unmute_helper(int mute, struct ast_cli_args *a)
ast_cli(a->fd, "No channel named '%s' found in conference %s\n", a->argv[3], a->argv[2]);
return -1;
}
- ast_cli(a->fd, "%s %s from confbridge %s\n", mute ? "Muting" : "Unmuting", a->argv[3], a->argv[2]);
+ if (mute == 1) {
+ verb = "Muting";
+ } else if (mute == 0) {
+ verb = "Unmuting";
+ } else if (deaf == 1) {
+ verb = "Deafening";
+ } else {
+ verb = "Undeafening";
+ }
+ ast_cli(a->fd, "%s %s from confbridge %s\n", verb, a->argv[3], a->argv[2]);
return 0;
}
@@ -2055,7 +2120,7 @@ static char *handle_cli_confbridge_mute(struct ast_cli_entry *e, int cmd, struct
return CLI_SHOWUSAGE;
}
- cli_mute_unmute_helper(1, a);
+ cli_mute_deafen_helper(1, -1, a);
return CLI_SUCCESS;
}
@@ -2078,7 +2143,53 @@ static char *handle_cli_confbridge_unmute(struct ast_cli_entry *e, int cmd, stru
return CLI_SHOWUSAGE;
}
- cli_mute_unmute_helper(0, a);
+ cli_mute_deafen_helper(0, -1, a);
+
+ return CLI_SUCCESS;
+}
+
+static char *handle_cli_confbridge_deafen(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "confbridge deafen";
+ e->usage =
+ "Usage: confbridge deafen \n";
+ return NULL;
+ case CLI_GENERATE:
+ if (a->pos == 2) {
+ return complete_confbridge_name(a->line, a->word, a->pos, a->n);
+ }
+ return NULL;
+ }
+ if (a->argc != 4) {
+ return CLI_SHOWUSAGE;
+ }
+
+ cli_mute_deafen_helper(-1, 1, a);
+
+ return CLI_SUCCESS;
+}
+
+static char *handle_cli_confbridge_undeafen(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "confbridge undeafen";
+ e->usage =
+ "Usage: confbridge undeafen \n";
+ return NULL;
+ case CLI_GENERATE:
+ if (a->pos == 2) {
+ return complete_confbridge_name(a->line, a->word, a->pos, a->n);
+ }
+ return NULL;
+ }
+ if (a->argc != 4) {
+ return CLI_SHOWUSAGE;
+ }
+
+ cli_mute_deafen_helper(-1, 0, a);
return CLI_SUCCESS;
}
@@ -2226,6 +2337,8 @@ static struct ast_cli_entry cli_confbridge[] = {
AST_CLI_DEFINE(handle_cli_confbridge_kick, "Kick participants out of conference bridges."),
AST_CLI_DEFINE(handle_cli_confbridge_mute, "Mute a participant."),
AST_CLI_DEFINE(handle_cli_confbridge_unmute, "Unmute a participant."),
+ AST_CLI_DEFINE(handle_cli_confbridge_deafen, "Deafen a participant."),
+ AST_CLI_DEFINE(handle_cli_confbridge_undeafen, "Undeafen a participant."),
AST_CLI_DEFINE(handle_cli_confbridge_lock, "Lock a conference."),
AST_CLI_DEFINE(handle_cli_confbridge_unlock, "Unlock a conference."),
AST_CLI_DEFINE(handle_cli_confbridge_start_record, "Start recording a conference"),
@@ -2360,10 +2473,11 @@ static int action_confbridgelistrooms(struct mansession *s, const struct message
return 0;
}
-static int action_mute_unmute_helper(struct mansession *s, const struct message *m, int mute)
+static int action_mute_deafen_helper(struct mansession *s, const struct message *m, int mute, int deaf)
{
const char *conference = astman_get_header(m, "Conference");
const char *channel = astman_get_header(m, "Channel");
+ char *verb;
int res = 0;
if (ast_strlen_zero(conference)) {
@@ -2379,7 +2493,7 @@ static int action_mute_unmute_helper(struct mansession *s, const struct message
return 0;
}
- res = generic_mute_unmute_helper(mute, conference, channel);
+ res = generic_mute_deafen_helper(mute, deaf, conference, channel);
if (res == -1) {
astman_send_error(s, m, "No Conference by that name found.");
@@ -2389,17 +2503,35 @@ static int action_mute_unmute_helper(struct mansession *s, const struct message
return 0;
}
- astman_send_ack(s, m, mute ? "User muted" : "User unmuted");
+ if (mute == 1) {
+ verb = "User muted";
+ } else if (mute == 0) {
+ verb = "User unmuted";
+ } else if (deaf == 1) {
+ verb = "User deafened";
+ } else {
+ verb = "User undeafened";
+ }
+
+ astman_send_ack(s, m, verb);
return 0;
}
static int action_confbridgeunmute(struct mansession *s, const struct message *m)
{
- return action_mute_unmute_helper(s, m, 0);
+ return action_mute_deafen_helper(s, m, 0, -1);
}
static int action_confbridgemute(struct mansession *s, const struct message *m)
{
- return action_mute_unmute_helper(s, m, 1);
+ return action_mute_deafen_helper(s, m, 1, -1);
+}
+static int action_confbridgeundeafen(struct mansession *s, const struct message *m)
+{
+ return action_mute_deafen_helper(s, m, -1, 0);
+}
+static int action_confbridgedeafen(struct mansession *s, const struct message *m)
+{
+ return action_mute_deafen_helper(s, m, -1, 1);
}
static int action_lock_unlock_helper(struct mansession *s, const struct message *m, int lock)
@@ -2685,6 +2817,8 @@ static int unload_module(void)
res |= ast_manager_unregister("ConfbridgeListRooms");
res |= ast_manager_unregister("ConfbridgeMute");
res |= ast_manager_unregister("ConfbridgeUnmute");
+ res |= ast_manager_unregister("ConfbridgeDeafen");
+ res |= ast_manager_unregister("ConfbridgeUndeafen");
res |= ast_manager_unregister("ConfbridgeKick");
res |= ast_manager_unregister("ConfbridgeUnlock");
res |= ast_manager_unregister("ConfbridgeLock");
@@ -2726,6 +2860,8 @@ static int load_module(void)
res |= ast_manager_register_xml("ConfbridgeListRooms", EVENT_FLAG_REPORTING, action_confbridgelistrooms);
res |= ast_manager_register_xml("ConfbridgeMute", EVENT_FLAG_CALL, action_confbridgemute);
res |= ast_manager_register_xml("ConfbridgeUnmute", EVENT_FLAG_CALL, action_confbridgeunmute);
+ res |= ast_manager_register_xml("ConfbridgeDeafen", EVENT_FLAG_CALL, action_confbridgedeafen);
+ res |= ast_manager_register_xml("ConfbridgeUndeafen", EVENT_FLAG_CALL, action_confbridgeundeafen);
res |= ast_manager_register_xml("ConfbridgeKick", EVENT_FLAG_CALL, action_confbridgekick);
res |= ast_manager_register_xml("ConfbridgeUnlock", EVENT_FLAG_CALL, action_confbridgeunlock);
res |= ast_manager_register_xml("ConfbridgeLock", EVENT_FLAG_CALL, action_confbridgelock);
diff --git a/apps/confbridge/conf_config_parser.c b/apps/confbridge/conf_config_parser.c
index d11b825..df1997a 100644
--- a/apps/confbridge/conf_config_parser.c
+++ b/apps/confbridge/conf_config_parser.c
@@ -153,6 +153,8 @@ static int set_user_option(const char *name, const char *value, struct user_prof
ast_set2_flag(u_profile, ast_true(value), USER_OPT_MARKEDUSER);
} else if (!strcasecmp(name, "startmuted")) {
ast_set2_flag(u_profile, ast_true(value), USER_OPT_STARTMUTED);
+ } else if (!strcasecmp(name, "startdeaf")) {
+ ast_set2_flag(u_profile, ast_true(value), USER_OPT_STARTDEAF);
} else if (!strcasecmp(name, "music_on_hold_when_empty")) {
ast_set2_flag(u_profile, ast_true(value), USER_OPT_MUSICONHOLD);
} else if (!strcasecmp(name, "quiet")) {
@@ -229,6 +231,10 @@ static int set_sound(const char *sound_name, const char *sound_file, struct brid
ast_string_field_set(sounds, muted, sound_file);
} else if (!strcasecmp(sound_name, "sound_unmuted")) {
ast_string_field_set(sounds, unmuted, sound_file);
+ } else if (!strcasecmp(sound_name, "sound_deafened")) {
+ ast_string_field_set(sounds, deafened, sound_file);
+ } else if (!strcasecmp(sound_name, "sound_undeafened")) {
+ ast_string_field_set(sounds, undeafened, sound_file);
} else if (!strcasecmp(sound_name, "sound_there_are")) {
ast_string_field_set(sounds, thereare, sound_file);
} else if (!strcasecmp(sound_name, "sound_other_in_party")) {
@@ -533,6 +539,7 @@ static int add_action_to_menu_entry(struct conf_menu_entry *menu_entry, enum con
switch (id) {
case MENU_ACTION_NOOP:
case MENU_ACTION_TOGGLE_MUTE:
+ case MENU_ACTION_TOGGLE_DEAF:
case MENU_ACTION_INCREASE_LISTENING:
case MENU_ACTION_DECREASE_LISTENING:
case MENU_ACTION_INCREASE_TALKING:
@@ -1015,6 +1022,8 @@ static char *handle_cli_confbridge_show_bridge_profile(struct ast_cli_entry *e,
ast_cli(a->fd,"sound_kicked: %s\n", conf_get_sound(CONF_SOUND_KICKED, b_profile.sounds));
ast_cli(a->fd,"sound_muted: %s\n", conf_get_sound(CONF_SOUND_MUTED, b_profile.sounds));
ast_cli(a->fd,"sound_unmuted: %s\n", conf_get_sound(CONF_SOUND_UNMUTED, b_profile.sounds));
+ ast_cli(a->fd,"sound_deafened: %s\n", conf_get_sound(CONF_SOUND_DEAFENED, b_profile.sounds));
+ ast_cli(a->fd,"sound_undeafened: %s\n", conf_get_sound(CONF_SOUND_UNDEAFENED, b_profile.sounds));
ast_cli(a->fd,"sound_there_are: %s\n", conf_get_sound(CONF_SOUND_THERE_ARE, b_profile.sounds));
ast_cli(a->fd,"sound_other_in_party: %s\n", conf_get_sound(CONF_SOUND_OTHER_IN_PARTY, b_profile.sounds));
ast_cli(a->fd,"sound_place_into_conference: %s\n", conf_get_sound(CONF_SOUND_PLACE_IN_CONF, b_profile.sounds));
@@ -1124,6 +1133,9 @@ static char *handle_cli_confbridge_show_menu(struct ast_cli_entry *e, int cmd, s
case MENU_ACTION_TOGGLE_MUTE:
ast_cli(a->fd, "toggle_mute");
break;
+ case MENU_ACTION_TOGGLE_DEAF:
+ ast_cli(a->fd, "toggle_deaf");
+ break;
case MENU_ACTION_NOOP:
ast_cli(a->fd, "no_op");
break;
diff --git a/apps/confbridge/include/confbridge.h b/apps/confbridge/include/confbridge.h
index ab4a8c4..f733b49 100644
--- a/apps/confbridge/include/confbridge.h
+++ b/apps/confbridge/include/confbridge.h
@@ -57,6 +57,7 @@ enum user_profile_flags {
USER_OPT_DTMF_PASS = (1 << 13), /*!< Sets if dtmf should be passed into the conference or not */
USER_OPT_ANNOUNCEUSERCOUNTALL = (1 << 14), /*!< Sets if the number of users should be announced to everyone. */
USER_OPT_JITTERBUFFER = (1 << 15), /*!< Places a jitterbuffer on the user. */
+ USER_OPT_STARTDEAF = (1 << 16), /*!< Set if the caller should be initially set deaf */
};
enum bridge_profile_flags {
@@ -68,6 +69,7 @@ enum bridge_profile_flags {
enum conf_menu_action_id {
MENU_ACTION_TOGGLE_MUTE = 1,
+ MENU_ACTION_TOGGLE_DEAF,
MENU_ACTION_PLAYBACK,
MENU_ACTION_PLAYBACK_AND_CONTINUE,
MENU_ACTION_INCREASE_LISTENING,
@@ -141,6 +143,8 @@ enum conf_sounds {
CONF_SOUND_KICKED,
CONF_SOUND_MUTED,
CONF_SOUND_UNMUTED,
+ CONF_SOUND_DEAFENED,
+ CONF_SOUND_UNDEAFENED,
CONF_SOUND_ONLY_ONE,
CONF_SOUND_THERE_ARE,
CONF_SOUND_OTHER_IN_PARTY,
@@ -165,6 +169,8 @@ struct bridge_profile_sounds {
AST_STRING_FIELD(kicked);
AST_STRING_FIELD(muted);
AST_STRING_FIELD(unmuted);
+ AST_STRING_FIELD(deafened);
+ AST_STRING_FIELD(undeafened);
AST_STRING_FIELD(onlyone);
AST_STRING_FIELD(thereare);
AST_STRING_FIELD(otherinparty);
diff --git a/bridges/bridge_softmix.c b/bridges/bridge_softmix.c
index 7632f36..103e3be 100644
--- a/bridges/bridge_softmix.c
+++ b/bridges/bridge_softmix.c
@@ -850,16 +850,23 @@ static int softmix_bridge_thread(struct ast_bridge *bridge)
ast_mutex_lock(&sc->lock);
- /* Make SLINEAR write frame from local buffer */
- if (sc->write_frame.subclass.format.id != cur_slin_id) {
- ast_format_set(&sc->write_frame.subclass.format, cur_slin_id, 0);
+ if (bridge->features.deaf ||
+ (bridge_channel->features && bridge_channel->features->deaf)) {
+ /* For deaf channels post a null frame */
+ sc->write_frame.frametype = AST_FRAME_NULL;
+ } else {
+ /* Make SLINEAR write frame from local buffer */
+ sc->write_frame.frametype = AST_FRAME_VOICE;
+ if (sc->write_frame.subclass.format.id != cur_slin_id) {
+ ast_format_set(&sc->write_frame.subclass.format, cur_slin_id, 0);
+ }
+ sc->write_frame.datalen = softmix_datalen;
+ sc->write_frame.samples = softmix_samples;
+ memcpy(sc->final_buf, buf, softmix_datalen);
+
+ /* process the softmix channel's new write audio */
+ softmix_process_write_audio(&trans_helper, &bridge_channel->chan->rawwriteformat, sc);
}
- sc->write_frame.datalen = softmix_datalen;
- sc->write_frame.samples = softmix_samples;
- memcpy(sc->final_buf, buf, softmix_datalen);
-
- /* process the softmix channel's new write audio */
- softmix_process_write_audio(&trans_helper, &bridge_channel->chan->rawwriteformat, sc);
/* The frame is now ready for use... */
sc->have_frame = 1;
diff --git a/include/asterisk/bridging_features.h b/include/asterisk/bridging_features.h
index e377ca6..5ce3d56 100644
--- a/include/asterisk/bridging_features.h
+++ b/include/asterisk/bridging_features.h
@@ -127,6 +127,8 @@ struct ast_bridge_features {
unsigned int usable:1;
/*! Bit to indicate whether the channel/bridge is muted or not */
unsigned int mute:1;
+ /*! Bit to indicate whether the channel/bridge is deaf or not */
+ unsigned int deaf:1;
/*! Bit to indicate whether DTMF should be passed into the bridge tech or not. */
unsigned int dtmf_passthrough:1;