From b08c247feb01c316ebbcc84d1d49279c2b9719cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Tue, 27 Dec 2011 11:34:28 +0200 Subject: main/asterisk: add few useful new features from asterisk bug reports --- main/asterisk/APKBUILD | 6 +- main/asterisk/ASTERISK-19107.patch | 60 +++++ main/asterisk/ASTERISK-19109.patch | 449 +++++++++++++++++++++++++++++++++++++ 3 files changed, 514 insertions(+), 1 deletion(-) create mode 100644 main/asterisk/ASTERISK-19107.patch create mode 100644 main/asterisk/ASTERISK-19109.patch (limited to 'main') diff --git a/main/asterisk/APKBUILD b/main/asterisk/APKBUILD index e6419e228..c0e2e5c64 100644 --- a/main/asterisk/APKBUILD +++ b/main/asterisk/APKBUILD @@ -2,7 +2,7 @@ # Maintainer: Timo Teras pkgname=asterisk pkgver=10.0.0 -pkgrel=2 +pkgrel=3 pkgdesc="Asterisk: A Module Open Source PBX System" url="http://www.asterisk.org/" arch="all" @@ -25,6 +25,8 @@ source="http://downloads.asterisk.org/pub/telephony/asterisk/releases/asterisk-$ ASTERISK-18994.patch ASTERISK-18995.patch ASTERISK-19106.patch + ASTERISK-19107.patch + ASTERISK-19109.patch asterisk.initd asterisk.confd asterisk.logrotate" @@ -173,6 +175,8 @@ da5a3c500192dee4275aae5235d25f97 ASTERISK-18976.patch 0af5e797f0a99d0f81f95e3710baf5b6 ASTERISK-18994.patch bc6713f5434e07b79d3afdd155461d72 ASTERISK-18995.patch fee11ba2f6518462ea6dde4039f9d8fa ASTERISK-19106.patch +90e6c516b55245f4ff4a995b6f36a6b7 ASTERISK-19107.patch +a59d61843a44d5a72da401218dcf6588 ASTERISK-19109.patch 86c7589e906102869d67f7f8bc82ca4b asterisk.initd ed31d7ba37bcf8b0346dcf8593c395f0 asterisk.confd 3e65172275684373e1a25c8a11224411 asterisk.logrotate" diff --git a/main/asterisk/ASTERISK-19107.patch b/main/asterisk/ASTERISK-19107.patch new file mode 100644 index 000000000..cb43615b2 --- /dev/null +++ b/main/asterisk/ASTERISK-19107.patch @@ -0,0 +1,60 @@ +diff --git a/main/config.c b/main/config.c +index 498ae99..0f5f0e2 100644 +--- a/main/config.c ++++ b/main/config.c +@@ -1199,9 +1199,11 @@ static int process_text_line(struct ast_config *cfg, struct ast_category **cat, + if (newcat) + ast_category_append(cfg, *cat); + } else if (cur[0] == '#') { /* A directive - #include or #exec */ ++ struct ast_config *res; + char *cur2; + char real_inclusion_name[256]; + int do_include = 0; /* otherwise, it is exec */ ++ int quiet = 0; + + cur++; + c = cur; +@@ -1221,6 +1223,9 @@ static int process_text_line(struct ast_config *cfg, struct ast_category **cat, + } + if (!strcasecmp(cur, "include")) { + do_include = 1; ++ } else if (!strcasecmp(cur, "-include")) { ++ do_include = 1; ++ quiet = 1; + } else if (!strcasecmp(cur, "exec")) { + if (!ast_opt_exec_includes) { + ast_log(LOG_WARNING, "Cannot perform #exec unless execincludes option is enabled in asterisk.conf (options section)!\n"); +@@ -1233,7 +1238,7 @@ static int process_text_line(struct ast_config *cfg, struct ast_category **cat, + + if (c == NULL) { + ast_log(LOG_WARNING, "Directive '#%s' needs an argument (%s) at line %d of %s\n", +- do_include ? "include" : "exec", ++ cur, + do_include ? "filename" : "/path/to/executable", + lineno, + configfile); +@@ -1275,10 +1280,13 @@ static int process_text_line(struct ast_config *cfg, struct ast_category **cat, + /* record this inclusion */ + ast_include_new(cfg, cfg->include_level == 1 ? "" : configfile, cur, !do_include, cur2, lineno, real_inclusion_name, sizeof(real_inclusion_name)); + +- do_include = ast_config_internal_load(cur, cfg, flags, real_inclusion_name, who_asked) ? 1 : 0; ++ res = ast_config_internal_load(cur, cfg, flags, real_inclusion_name, who_asked); + if (!ast_strlen_zero(exec_file)) + unlink(exec_file); +- if (!do_include) { ++ if (res == CONFIG_STATUS_FILEINVALID) { ++ ast_log(LOG_ERROR, "The file '%s' was listed as a #include but it failed to load.\n", cur); ++ return -1; ++ } else if (res == CONFIG_STATUS_FILEMISSING && !quiet) { + ast_log(LOG_ERROR, "The file '%s' was listed as a #include but it does not exist.\n", cur); + return -1; + } +@@ -1643,7 +1651,7 @@ static struct ast_config *config_text_file_load(const char *database, const char + } + + if (count == 0) +- return NULL; ++ return CONFIG_STATUS_FILEMISSING; + + return cfg; + } diff --git a/main/asterisk/ASTERISK-19109.patch b/main/asterisk/ASTERISK-19109.patch new file mode 100644 index 000000000..21fe3cb22 --- /dev/null +++ b/main/asterisk/ASTERISK-19109.patch @@ -0,0 +1,449 @@ +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; + -- cgit v1.2.3