diff options
Diffstat (limited to 'main/asterisk/ASTERISK-19109.patch')
-rw-r--r-- | main/asterisk/ASTERISK-19109.patch | 358 |
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) + { |