diff options
author | Richard Mudgett <rmudgett@digium.com> | 2013-08-23 18:33:36 +0000 |
---|---|---|
committer | Richard Mudgett <rmudgett@digium.com> | 2013-08-23 18:33:36 +0000 |
commit | 6ebfac8e70b0863fd96ee4fe6ca4b254696fe9c4 (patch) | |
tree | df6a91c733cc32ae5179493b800384824dcdcfa3 /main/channel.c | |
parent | 31ab4866275aa28f6ec9fe7ce166b4f86f8ecf24 (diff) |
Handle DTMF and hold wrapup when a channel leaves the bridging system.
DTMF start/end and hold/unhold events have state because a DTMF begin
event and hold event must be ended by something.
The following cases need to be handled when a channel is moved around in
the system.
* When a channel leaves a bridge it may owe a DTMF end event to the
bridge.
* When a channel leaves a bridge it may owe an UNHOLD event to the bridge.
(This case is explicitly ignored because things like transfers need
explicit control over this.)
* When a channel leaves the bridging system it may need to simulate a DTMF
end event to the channel.
* When a channel leaves the bridging system it may need to simulate an
UNHOLD event to the channel.
The patch also fixes the following:
* Fixes playing a file and restarting MOH using the latest MOH class used.
(closes issue ASTERISK-22043)
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/2791/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@397577 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'main/channel.c')
-rw-r--r-- | main/channel.c | 38 |
1 files changed, 35 insertions, 3 deletions
diff --git a/main/channel.c b/main/channel.c index 1abed5e94..f085d31e8 100644 --- a/main/channel.c +++ b/main/channel.c @@ -941,6 +941,7 @@ __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char /* Initial state */ ast_channel_state_set(tmp, state); + ast_channel_hold_state_set(tmp, AST_CONTROL_UNHOLD); ast_channel_streamid_set(tmp, -1); @@ -1072,6 +1073,8 @@ struct ast_channel *ast_dummy_channel_alloc(void) ast_channel_epfd_set(tmp, -1); #endif + ast_channel_hold_state_set(tmp, AST_CONTROL_UNHOLD); + ast_channel_internal_setup_topics(tmp); headp = ast_channel_varshead(tmp); @@ -4453,7 +4456,6 @@ int ast_indicate_data(struct ast_channel *chan, int _condition, ast_channel_connected(chan)); } break; - case AST_CONTROL_REDIRECTING: { struct ast_party_redirecting redirecting; @@ -4466,7 +4468,10 @@ int ast_indicate_data(struct ast_channel *chan, int _condition, ast_party_redirecting_free(&redirecting); } break; - + case AST_CONTROL_HOLD: + case AST_CONTROL_UNHOLD: + ast_channel_hold_state_set(chan, condition); + break; default: break; } @@ -6376,6 +6381,7 @@ void ast_do_masquerade(struct ast_channel *original) int origstate; int visible_indication; int clone_was_zombie = 0;/*!< TRUE if the clonechan was a zombie before the masquerade. */ + int clone_hold_state; struct ast_frame *current; const struct ast_channel_tech *t; void *t_pvt; @@ -6478,6 +6484,8 @@ void ast_do_masquerade(struct ast_channel *original) free_translation(clonechan); free_translation(original); + clone_hold_state = ast_channel_hold_state(clonechan); + /* Save the current DTMF digit being sent if any. */ clone_sending_dtmf_digit = ast_channel_sending_dtmf_digit(clonechan); clone_sending_dtmf_tv = ast_channel_sending_dtmf_tv(clonechan); @@ -6712,6 +6720,11 @@ void ast_do_masquerade(struct ast_channel *original) ast_bridge_notify_masquerade(original); + if (clone_hold_state == AST_CONTROL_HOLD) { + ast_debug(1, "Channel %s simulating UNHOLD for masquerade.\n", + ast_channel_name(original)); + ast_indicate(original, AST_CONTROL_UNHOLD); + } if (clone_sending_dtmf_digit) { /* * The clonechan was sending a DTMF digit that was not completed @@ -6731,7 +6744,23 @@ void ast_do_masquerade(struct ast_channel *original) * (RINGING, CONGESTION, etc.) */ if (visible_indication) { - ast_indicate(original, visible_indication); + if (visible_indication == AST_CONTROL_HOLD) { + const char *latest_musicclass; + int len; + + ast_channel_lock(original); + latest_musicclass = ast_strdupa(ast_channel_latest_musicclass(original)); + ast_channel_unlock(original); + if (ast_strlen_zero(latest_musicclass)) { + latest_musicclass = NULL; + len = 0; + } else { + len = strlen(latest_musicclass) + 1; + } + ast_indicate_data(original, visible_indication, latest_musicclass, len); + } else { + ast_indicate(original, visible_indication); + } } ast_channel_lock(original); @@ -10390,6 +10419,9 @@ void ast_channel_end_dtmf(struct ast_channel *chan, char digit, struct timeval s } duration = ast_tvdiff_ms(ast_tvnow(), start); + if (duration < option_dtmfminduration) { + duration = option_dtmfminduration; + } ast_senddigit_end(chan, digit, duration); ast_log(LOG_DTMF, "DTMF end '%c' simulated on %s due to %s, duration %ld ms\n", digit, ast_channel_name(chan), why, duration); |