aboutsummaryrefslogtreecommitdiffstats
path: root/main/asterisk/ASTERISK-19109.patch
diff options
context:
space:
mode:
Diffstat (limited to 'main/asterisk/ASTERISK-19109.patch')
-rw-r--r--main/asterisk/ASTERISK-19109.patch358
1 files changed, 296 insertions, 62 deletions
diff --git a/main/asterisk/ASTERISK-19109.patch b/main/asterisk/ASTERISK-19109.patch
index 21fe3cb224..73c8accff4 100644
--- a/main/asterisk/ASTERISK-19109.patch
+++ b/main/asterisk/ASTERISK-19109.patch
@@ -1,8 +1,14 @@
+commit 0fad0f8a679cbb0609056528ac157476dd4e5877
+Author: Timo Teräs <timo.teras@iki.fi>
+Date: Wed Dec 28 08:30:54 2011 +0200
+
+ Support 'deaf' participants in ConfBridge
+
diff --git a/apps/app_confbridge.c b/apps/app_confbridge.c
-index 42c0a4c..ae26518 100644
+index d5609b7..8569f5c 100644
--- a/apps/app_confbridge.c
+++ b/apps/app_confbridge.c
-@@ -184,6 +184,31 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+@@ -185,6 +185,30 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
<description>
</description>
</manager>
@@ -20,8 +26,7 @@ index 42c0a4c..ae26518 100644
+ </manager>
+ <manager name="ConfbridgeUndeafen" language="en_US">
+ <synopsis>
-+ Un
-+ Undefaen a Confbridge user.
++ Undeafen a Confbridge user.
+ </synopsis>
+ <syntax>
+ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
@@ -34,7 +39,21 @@ index 42c0a4c..ae26518 100644
<manager name="ConfbridgeKick" language="en_US">
<synopsis>
Kick a Confbridge user.
-@@ -310,6 +335,10 @@ const char *conf_get_sound(enum conf_sounds sound, struct bridge_profile_sounds
+@@ -273,6 +297,13 @@ static const char app[] = "ConfBridge";
+ /* Number of buckets our conference bridges container can have */
+ #define CONFERENCE_BRIDGE_BUCKETS 53
+
++enum confbridge_feature_action {
++ CONFBRIDGE_FEATURE_MUTE,
++ CONFBRIDGE_FEATURE_UNMUTE,
++ CONFBRIDGE_FEATURE_DEAFEN,
++ CONFBRIDGE_FEATURE_UNDEAFEN
++};
++
+ /*! \brief Container to hold all conference bridges in progress */
+ static struct ao2_container *conference_bridges;
+
+@@ -311,6 +342,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");
@@ -45,7 +64,7 @@ index 42c0a4c..ae26518 100644
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)
+@@ -1423,10 +1458,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);
@@ -60,8 +79,8 @@ index 42c0a4c..ae26518 100644
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,
- "");
+@@ -1587,6 +1625,20 @@ static int action_toggle_mute_participants(struct conference_bridge *conference_
+ return 0;
}
+static int action_toggle_deaf(struct conference_bridge *conference_bridge,
@@ -70,6 +89,7 @@ index 42c0a4c..ae26518 100644
+{
+ /* Deafen or undeafen yourself */
+ conference_bridge_user->features.deaf = (!conference_bridge_user->features.deaf ? 1 : 0);
++ ast_test_suite_event_notify("CONF_DEAF", "Message: participant %s %s\r\nConference: %s\r\nChannel: %s", chan->name, conference_bridge_user->features.deaf ? "deafened" : "undeafened", conference_bridge_user->b_profile.name, chan->name);
+
+ return ast_stream_and_wait(chan, (conference_bridge_user->features.deaf ?
+ conf_get_sound(CONF_SOUND_DEAFENED, conference_bridge_user->b_profile.sounds) :
@@ -80,9 +100,9 @@ index 42c0a4c..ae26518 100644
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);
+@@ -1775,6 +1827,11 @@ static int execute_menu_entry(struct conference_bridge *conference_bridge,
+ case MENU_ACTION_PARTICIPANT_COUNT:
+ announce_user_count(conference_bridge, conference_bridge_user);
break;
+ case MENU_ACTION_TOGGLE_DEAF:
+ res |= action_toggle_deaf(conference_bridge,
@@ -92,32 +112,63 @@ index 42c0a4c..ae26518 100644
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)
+@@ -2038,13 +2095,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.
++ * \brief finds a conference user by channel name and changes feature bits on it.
*
* \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)
++static int generic_feature_action_helper(enum confbridge_feature_action action, 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
+@@ -2062,10 +2119,44 @@ 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;
+- ast_test_suite_event_notify("CONF_MUTE", "Message: participant %s %s\r\nConference: %s\r\nChannel: %s", participant->chan->name, participant->features.mute ? "muted" : "unmuted", bridge->b_profile.name, participant->chan->name);
++ const char *state, *verb;
++
++ switch (action) {
++ case CONFBRIDGE_FEATURE_DEAFEN:
++ participant->features.deaf = 1;
++ state = "CONF_DEAF";
++ verb = "deafened";
++ break;
++ case CONFBRIDGE_FEATURE_UNDEAFEN:
++ participant->features.deaf = 0;
++ state = "CONF_DEAF";
++ verb = "undeafened";
++ break;
++ case CONFBRIDGE_FEATURE_MUTE:
++ participant->features.mute = 1;
++ state = "CONF_MUTE";
++ verb = "muted";
++ break;
++ case CONFBRIDGE_FEATURE_UNMUTE:
++ default:
++ participant->features.mute = 0;
++ state = "CONF_MUTE";
++ verb = "unmuted";
++ break;
+ }
-+ if (deaf >= 0) {
-+ participant->features.deaf = deaf;
++
++ if (state != NULL && verb != NULL) {
++ ast_test_suite_event_notify(state,
++ "Message: participant %s %s\r\n"
++ "Conference: %s\r\n"
++ "Channel: %s",
++ participant->chan->name,
++ verb,
++ bridge->b_profile.name,
++ participant->chan->name);
+ }
} else {
- res = -2;;
@@ -125,52 +176,60 @@ index 42c0a4c..ae26518 100644
}
ao2_unlock(bridge);
ao2_ref(bridge, -1);
-@@ -2022,9 +2077,10 @@ static int generic_mute_unmute_helper(int mute, const char *conference, const ch
+@@ -2073,9 +2164,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)
++static int cli_feature_action_helper(enum confbridge_feature_action action, 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]);
++ int res = generic_feature_action_helper(action, 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)
+@@ -2084,7 +2176,24 @@ 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) {
++
++ switch (action) {
++ case CONFBRIDGE_FEATURE_DEAFEN:
+ verb = "Deafening";
-+ } else {
++ break;
++ case CONFBRIDGE_FEATURE_UNDEAFEN:
+ verb = "Undeafening";
++ break;
++ case CONFBRIDGE_FEATURE_MUTE:
++ verb = "Muting";
++ break;
++ case CONFBRIDGE_FEATURE_UNMUTE:
++ default:
++ verb = "Unmuting";
++ break;
+ }
++
+ 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
+@@ -2106,7 +2215,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);
++ cli_feature_action_helper(CONFBRIDGE_FEATURE_MUTE, a);
return CLI_SUCCESS;
}
-@@ -2078,7 +2143,53 @@ static char *handle_cli_confbridge_unmute(struct ast_cli_entry *e, int cmd, stru
+@@ -2129,7 +2238,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);
++ cli_feature_action_helper(CONFBRIDGE_FEATURE_UNMUTE, a);
+
+ return CLI_SUCCESS;
+}
@@ -193,7 +252,7 @@ index 42c0a4c..ae26518 100644
+ return CLI_SHOWUSAGE;
+ }
+
-+ cli_mute_deafen_helper(-1, 1, a);
++ cli_feature_action_helper(CONFBRIDGE_FEATURE_DEAFEN, a);
+
+ return CLI_SUCCESS;
+}
@@ -216,11 +275,11 @@ index 42c0a4c..ae26518 100644
+ return CLI_SHOWUSAGE;
+ }
+
-+ cli_mute_deafen_helper(-1, 0, a);
++ cli_feature_action_helper(CONFBRIDGE_FEATURE_UNDEAFEN, a);
return CLI_SUCCESS;
}
-@@ -2226,6 +2337,8 @@ static struct ast_cli_entry cli_confbridge[] = {
+@@ -2277,6 +2432,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."),
@@ -229,12 +288,12 @@ index 42c0a4c..ae26518 100644
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
+@@ -2411,10 +2568,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)
++static int action_feature_action_helper(struct mansession *s, const struct message *m, enum confbridge_feature_action action)
{
const char *conference = astman_get_header(m, "Conference");
const char *channel = astman_get_header(m, "Channel");
@@ -242,28 +301,34 @@ index 42c0a4c..ae26518 100644
int res = 0;
if (ast_strlen_zero(conference)) {
-@@ -2379,7 +2493,7 @@ static int action_mute_unmute_helper(struct mansession *s, const struct message
+@@ -2430,7 +2588,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);
++ res = generic_feature_action_helper(action, 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
+@@ -2440,17 +2598,41 @@ 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) {
++ switch (action) {
++ case CONFBRIDGE_FEATURE_DEAFEN:
+ verb = "User deafened";
-+ } else {
++ break;
++ case CONFBRIDGE_FEATURE_UNDEAFEN:
+ verb = "User undeafened";
++ break;
++ case CONFBRIDGE_FEATURE_MUTE:
++ verb = "User muted";
++ break;
++ case CONFBRIDGE_FEATURE_UNMUTE:
++ default:
++ verb = "User unmuted";
++ break;
+ }
+
+ astman_send_ack(s, m, verb);
@@ -273,24 +338,24 @@ index 42c0a4c..ae26518 100644
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);
++ return action_feature_action_helper(s, m, CONFBRIDGE_FEATURE_UNMUTE);
}
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);
++ return action_feature_action_helper(s, m, CONFBRIDGE_FEATURE_MUTE);
+}
+static int action_confbridgeundeafen(struct mansession *s, const struct message *m)
+{
-+ return action_mute_deafen_helper(s, m, -1, 0);
++ return action_feature_action_helper(s, m, CONFBRIDGE_FEATURE_UNDEAFEN);
+}
+static int action_confbridgedeafen(struct mansession *s, const struct message *m)
+{
-+ return action_mute_deafen_helper(s, m, -1, 1);
++ return action_feature_action_helper(s, m, CONFBRIDGE_FEATURE_DEAFEN);
}
static int action_lock_unlock_helper(struct mansession *s, const struct message *m, int lock)
-@@ -2685,6 +2817,8 @@ static int unload_module(void)
+@@ -2737,6 +2919,8 @@ static int unload_module(void)
res |= ast_manager_unregister("ConfbridgeListRooms");
res |= ast_manager_unregister("ConfbridgeMute");
res |= ast_manager_unregister("ConfbridgeUnmute");
@@ -299,7 +364,7 @@ index 42c0a4c..ae26518 100644
res |= ast_manager_unregister("ConfbridgeKick");
res |= ast_manager_unregister("ConfbridgeUnlock");
res |= ast_manager_unregister("ConfbridgeLock");
-@@ -2726,6 +2860,8 @@ static int load_module(void)
+@@ -2778,6 +2962,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);
@@ -309,7 +374,7 @@ index 42c0a4c..ae26518 100644
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
+index 9bb8b2a..3cf7a32 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
@@ -321,7 +386,7 @@ index d11b825..df1997a 100644
} 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
+@@ -231,6 +233,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);
@@ -332,7 +397,7 @@ index d11b825..df1997a 100644
} 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
+@@ -541,6 +547,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:
@@ -340,7 +405,7 @@ index d11b825..df1997a 100644
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,
+@@ -1029,6 +1036,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));
@@ -349,7 +414,7 @@ index d11b825..df1997a 100644
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
+@@ -1140,6 +1149,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;
@@ -360,7 +425,7 @@ index d11b825..df1997a 100644
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
+index 5337e22..c601fa8 100644
--- a/apps/confbridge/include/confbridge.h
+++ b/apps/confbridge/include/confbridge.h
@@ -57,6 +57,7 @@ enum user_profile_flags {
@@ -379,7 +444,7 @@ index ab4a8c4..f733b49 100644
MENU_ACTION_PLAYBACK,
MENU_ACTION_PLAYBACK_AND_CONTINUE,
MENU_ACTION_INCREASE_LISTENING,
-@@ -141,6 +143,8 @@ enum conf_sounds {
+@@ -143,6 +145,8 @@ enum conf_sounds {
CONF_SOUND_KICKED,
CONF_SOUND_MUTED,
CONF_SOUND_UNMUTED,
@@ -388,7 +453,7 @@ index ab4a8c4..f733b49 100644
CONF_SOUND_ONLY_ONE,
CONF_SOUND_THERE_ARE,
CONF_SOUND_OTHER_IN_PARTY,
-@@ -165,6 +169,8 @@ struct bridge_profile_sounds {
+@@ -169,6 +173,8 @@ struct bridge_profile_sounds {
AST_STRING_FIELD(kicked);
AST_STRING_FIELD(muted);
AST_STRING_FIELD(unmuted);
@@ -397,10 +462,90 @@ index ab4a8c4..f733b49 100644
AST_STRING_FIELD(onlyone);
AST_STRING_FIELD(thereare);
AST_STRING_FIELD(otherinparty);
+diff --git a/bridges/bridge_multiplexed.c b/bridges/bridge_multiplexed.c
+index e004dfd..7add614 100644
+--- a/bridges/bridge_multiplexed.c
++++ b/bridges/bridge_multiplexed.c
+@@ -386,7 +386,7 @@ static enum ast_bridge_write_result multiplexed_bridge_write(struct ast_bridge *
+ }
+
+ if (other->state == AST_BRIDGE_CHANNEL_STATE_WAIT) {
+- ast_write(other->chan, frame);
++ ast_bridge_handle_channel_write(bridge, other, frame);
+ }
+
+ return AST_BRIDGE_WRITE_SUCCESS;
+diff --git a/bridges/bridge_simple.c b/bridges/bridge_simple.c
+index 14864df..d4270ff 100644
+--- a/bridges/bridge_simple.c
++++ b/bridges/bridge_simple.c
+@@ -81,7 +81,7 @@ static enum ast_bridge_write_result simple_bridge_write(struct ast_bridge *bridg
+
+ /* Write the frame out if they are in the waiting state... don't worry about freeing it, the bridging core will take care of it */
+ if (other->state == AST_BRIDGE_CHANNEL_STATE_WAIT) {
+- ast_write(other->chan, frame);
++ ast_bridge_handle_channel_write(bridge, other, frame);
+ }
+
+ return AST_BRIDGE_WRITE_SUCCESS;
diff --git a/bridges/bridge_softmix.c b/bridges/bridge_softmix.c
-index 7632f36..103e3be 100644
+index 7632f36..7946c79 100644
--- a/bridges/bridge_softmix.c
+++ b/bridges/bridge_softmix.c
+@@ -435,7 +435,7 @@ static void softmix_pass_dtmf(struct ast_bridge *bridge, struct ast_bridge_chann
+ if (tmp == bridge_channel) {
+ continue;
+ }
+- ast_write(tmp->chan, frame);
++ ast_bridge_handle_channel_write(bridge, tmp, frame);
+ }
+ }
+
+@@ -447,7 +447,7 @@ static void softmix_pass_video_top_priority(struct ast_bridge *bridge, struct as
+ continue;
+ }
+ if (ast_bridge_is_video_src(bridge, tmp->chan) == 1) {
+- ast_write(tmp->chan, frame);
++ ast_bridge_handle_channel_write(bridge, tmp, frame);
+ break;
+ }
+ }
+@@ -463,7 +463,7 @@ static void softmix_pass_video_all(struct ast_bridge *bridge, struct ast_bridge_
+ if ((tmp->chan == bridge_channel->chan) && !echo) {
+ continue;
+ }
+- ast_write(tmp->chan, frame);
++ ast_bridge_handle_channel_write(bridge, tmp, frame);
+ }
+ }
+
+@@ -563,7 +563,7 @@ static enum ast_bridge_write_result softmix_bridge_write(struct ast_bridge *brid
+
+ /* If a frame is ready to be written out, do so */
+ if (sc->have_frame) {
+- ast_write(bridge_channel->chan, &sc->write_frame);
++ ast_bridge_handle_channel_write(bridge, bridge_channel, &sc->write_frame);
+ sc->have_frame = 0;
+ }
+
+@@ -582,7 +582,7 @@ bridge_write_cleanup:
+ * the conference to the channel. */
+ ast_mutex_lock(&sc->lock);
+ if (sc->have_frame) {
+- ast_write(bridge_channel->chan, &sc->write_frame);
++ ast_bridge_handle_channel_write(bridge, bridge_channel, &sc->write_frame);
+ sc->have_frame = 0;
+ }
+ ast_mutex_unlock(&sc->lock);
+@@ -598,7 +598,7 @@ static int softmix_bridge_poke(struct ast_bridge *bridge, struct ast_bridge_chan
+ ast_mutex_lock(&sc->lock);
+
+ if (sc->have_frame) {
+- ast_write(bridge_channel->chan, &sc->write_frame);
++ ast_bridge_handle_channel_write(bridge, bridge_channel, &sc->write_frame);
+ sc->have_frame = 0;
+ }
+
@@ -850,16 +850,23 @@ static int softmix_bridge_thread(struct ast_bridge *bridge)
ast_mutex_lock(&sc->lock);
@@ -434,6 +579,36 @@ index 7632f36..103e3be 100644
/* The frame is now ready for use... */
sc->have_frame = 1;
+diff --git a/configs/confbridge.conf.sample b/configs/confbridge.conf.sample
+index d113825..737f92c 100644
+--- a/configs/confbridge.conf.sample
++++ b/configs/confbridge.conf.sample
+@@ -16,6 +16,7 @@ type=user
+ ;admin=yes ; Sets if the user is an admin or not. Off by default.
+ ;marked=yes ; Sets if this is a marked user or not. Off by default.
+ ;startmuted=yes; Sets if all users should start out muted. Off by default
++;startdeaf=yes ; Sets if all users should start out deaf. Off by default.
+ ;music_on_hold_when_empty=yes ; Sets whether MOH should be played when only
+ ; one person is in the conference or when the
+ ; the user is waiting on a marked user to enter
+@@ -209,6 +210,8 @@ type=bridge
+ ;sound_kicked ; The sound played to a user who has been kicked from the conference.
+ ;sound_muted ; The sound played when the mute option it toggled on.
+ ;sound_unmuted ; The sound played when the mute option it toggled off.
++;sound_deafened ; The sound played when the deaf option is toggled on.
++;sound_undeafened ; The sound played when the deaf option is toggled off.
+ ;sound_only_person ; The sound played when the user is the only person in the conference.
+ ;sound_only_one ; The sound played to a user when there is only one other
+ ; person is in the conference.
+@@ -263,6 +266,8 @@ type=bridge
+ ; toggle_mute ; Toggle turning on and off mute. Mute will make the user silent
+ ; to everyone else, but the user will still be able to listen in.
+ ; continue to collect the dtmf sequence.
++; toggle_deaf ; Toggle turning on and off deaf. Deaf will make the user to hear
++ ; only silence, but the user will still be able to talk.
+ ; no_op ; This action does nothing (No Operation). Its only real purpose exists for
+ ; being able to reserve a sequence in the config as a menu exit sequence.
+ ; decrease_listening_volume ; Decreases the channel's listening volume.
diff --git a/include/asterisk/bridging_features.h b/include/asterisk/bridging_features.h
index e377ca6..5ce3d56 100644
--- a/include/asterisk/bridging_features.h
@@ -447,3 +622,62 @@ index e377ca6..5ce3d56 100644
/*! Bit to indicate whether DTMF should be passed into the bridge tech or not. */
unsigned int dtmf_passthrough:1;
+diff --git a/include/asterisk/bridging_technology.h b/include/asterisk/bridging_technology.h
+index 3d2e870..1ecb4c1 100644
+--- a/include/asterisk/bridging_technology.h
++++ b/include/asterisk/bridging_technology.h
+@@ -143,6 +143,21 @@ int ast_bridge_technology_unregister(struct ast_bridge_technology *technology);
+ */
+ void ast_bridge_handle_trip(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_channel *chan, int outfd);
+
++/*! \brief Used by bridging technologies to hand off a frame to be written to a bridge_channel.
++ *
++ * \param bridge The bridge that the channel is part of.
++ * \param bridge_channel The bridge channel to which the frame is written to.
++ * \param frame The frame to write.
++ *
++ * \retval 0 on success
++ * \retval -1 on failure
++ *
++ * \note This function is essentially a wrapper for ast_write(). The bridging core has some features associated with it
++ * that requires it to have control over how frames are written into a channel. For these features to be available, the bridging
++ * technology must use this wrapper function over ast_write when pushing a frame out a channel.
++ */
++int ast_bridge_handle_channel_write(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame);
++
+ /*! \brief Lets the bridging indicate when a bridge channel has stopped or started talking.
+ *
+ * \note All DSP functionality on the bridge has been pushed down to the lowest possible
+diff --git a/main/bridging.c b/main/bridging.c
+index 9bc0edc..3295dc2 100644
+--- a/main/bridging.c
++++ b/main/bridging.c
+@@ -336,6 +336,28 @@ void ast_bridge_handle_trip(struct ast_bridge *bridge, struct ast_bridge_channel
+ return;
+ }
+
++int ast_bridge_handle_channel_write(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
++{
++ if (frame->frametype == AST_FRAME_VOICE &&
++ (bridge->features.deaf ||
++ (bridge_channel->features && bridge_channel->features->deaf))) {
++ short buf[frame->samples];
++ struct ast_frame sframe = {
++ .frametype = AST_FRAME_VOICE,
++ .data.ptr = buf,
++ .samples = frame->samples,
++ .datalen = sizeof(buf),
++ };
++ ast_format_set(&sframe.subclass.format, AST_FORMAT_SLINEAR, 0);
++ memset(buf, 0, sizeof(buf));
++
++ return ast_write(bridge_channel->chan, &sframe);
++ }
++
++ return ast_write(bridge_channel->chan, frame);
++}
++
++
+ /*! \brief Generic thread loop, TODO: Rethink this/improve it */
+ static int generic_thread_loop(struct ast_bridge *bridge)
+ {