summaryrefslogtreecommitdiff
path: root/bridges
diff options
context:
space:
mode:
authorJonathan Rose <jrose@digium.com>2013-08-05 17:48:03 +0000
committerJonathan Rose <jrose@digium.com>2013-08-05 17:48:03 +0000
commit2d87fc773b6c68ea2cc82a5345cab30946b38d75 (patch)
tree19c5d91cd4f49aebdbf59398d6b0cea38f24d35a /bridges
parente47794ead1fb35527728a0c655585af35679e258 (diff)
bridge_holding: Add suspsend/unsuspend callbacks
Suspend and unsuspend callbacks are added to the holding bridge so that entertainment can be disabled and re-enabled when operations would suspend a channel on the bridge (such as playback operations). This fixes entertainment so that when those operations end, the entertainment can pick back up and it also serves as an optimization. Also, this patch fixes a bug caused by triggering ringing frames immediately instead of pushing them to the queue which created a race condition where sometimes parking with ringing during attended transfers would cause the ringing to be interrupted by an unhold frame. (closes issue ASTERISK-22006) Reported by: Matt Jordan Review: https://reviewboard.asterisk.org/r/2711/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@396189 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'bridges')
-rw-r--r--bridges/bridge_holding.c44
1 files changed, 42 insertions, 2 deletions
diff --git a/bridges/bridge_holding.c b/bridges/bridge_holding.c
index 646b480ca..5cfb3301f 100644
--- a/bridges/bridge_holding.c
+++ b/bridges/bridge_holding.c
@@ -81,7 +81,7 @@ static void participant_stop_hold_audio(struct ast_bridge_channel *bridge_channe
ast_moh_stop(bridge_channel->chan);
break;
case IDLE_MODE_RINGING:
- ast_indicate(bridge_channel->chan, -1);
+ ast_bridge_channel_queue_control_data(bridge_channel, -1, NULL, 0);
break;
case IDLE_MODE_NONE:
break;
@@ -124,7 +124,7 @@ static void participant_start_hold_audio(struct ast_bridge_channel *bridge_chann
ast_moh_start(bridge_channel->chan, ast_strlen_zero(moh_class) ? NULL : moh_class, NULL);
break;
case IDLE_MODE_RINGING:
- ast_indicate(bridge_channel->chan, AST_CONTROL_RINGING);
+ ast_bridge_channel_queue_control_data(bridge_channel, AST_CONTROL_RINGING, NULL, 0);
break;
case IDLE_MODE_NONE:
break;
@@ -302,6 +302,44 @@ static int holding_bridge_write(struct ast_bridge *bridge, struct ast_bridge_cha
return 0;
}
+static void holding_bridge_suspend(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
+{
+ struct holding_channel *hc = bridge_channel ? bridge_channel->tech_pvt : NULL;
+
+ if (!hc) {
+ return;
+ }
+
+ if (!ast_test_flag(&hc->holding_roles, HOLDING_ROLE_PARTICIPANT)) {
+ return;
+ }
+
+ participant_stop_hold_audio(bridge_channel);
+}
+
+static void holding_bridge_unsuspend(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
+{
+ struct holding_channel *hc = bridge_channel ? bridge_channel->tech_pvt : NULL;
+ struct ast_bridge_channel *announcer_channel = bridge->tech_pvt;
+
+ if (!hc) {
+ return;
+ }
+
+ /* If the bridge channel being unsuspended is not a participant, no need to do anything. */
+ if (!ast_test_flag(&hc->holding_roles, HOLDING_ROLE_PARTICIPANT)) {
+ return;
+ }
+
+ /* If there is currently an announcer channel in the bridge, there is also no need to do anything. */
+ if (announcer_channel) {
+ return;
+ }
+
+ /* Otherwise we need to resume the entertainment. */
+ participant_start_hold_audio(bridge_channel);
+}
+
static struct ast_bridge_technology holding_bridge = {
.name = "holding_bridge",
.capabilities = AST_BRIDGE_CAPABILITY_HOLDING,
@@ -309,6 +347,8 @@ static struct ast_bridge_technology holding_bridge = {
.write = holding_bridge_write,
.join = holding_bridge_join,
.leave = holding_bridge_leave,
+ .suspend = holding_bridge_suspend,
+ .unsuspend = holding_bridge_unsuspend,
};
static int unload_module(void)