diff options
author | Kevin Harwell <kharwell@digium.com> | 2015-03-26 17:04:13 +0000 |
---|---|---|
committer | Kevin Harwell <kharwell@digium.com> | 2015-03-26 17:04:13 +0000 |
commit | fd434a210f4255b741ed90dd0634b5a1a8ca241a (patch) | |
tree | 2e2ded1312650cd4b2241c07d5f3773f743af38c /main/bridge_channel.c | |
parent | dea885a6070a62dfcaa631740b86f7ebdc09c977 (diff) |
app_confbridge: file playback blocks dtmf
Attempting to execute DTMF in a confbridge while file playback (prompt,
announcement, etc) is occurring is not allowed. You have to wait until
the sound file has completed before entering DTMF. This patch fixes it
so that app_confbridge now monitors for dtmf key presses during menu
driven file playback. If a key is pressed playback stops and it executes
the matched menu option.
ASTERISK-24864 #close
Reported by: Steve Pitts
Review: https://reviewboard.asterisk.org/r/4510/
........
Merged revisions 433445 from http://svn.asterisk.org/svn/asterisk/branches/11
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/13@433446 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'main/bridge_channel.c')
-rw-r--r-- | main/bridge_channel.c | 90 |
1 files changed, 63 insertions, 27 deletions
diff --git a/main/bridge_channel.c b/main/bridge_channel.c index ac72c8bc2..5e359ff47 100644 --- a/main/bridge_channel.c +++ b/main/bridge_channel.c @@ -1510,6 +1510,51 @@ static void testsuite_notify_feature_success(struct ast_channel *chan, const cha #endif /* TEST_FRAMEWORK */ } +static int bridge_channel_feature_digit_add( + struct ast_bridge_channel *bridge_channel, int digit, size_t dtmf_len) +{ + if (dtmf_len < ARRAY_LEN(bridge_channel->dtmf_hook_state.collected) - 1) { + /* Add the new digit to the DTMF string so we can do our matching */ + bridge_channel->dtmf_hook_state.collected[dtmf_len++] = digit; + bridge_channel->dtmf_hook_state.collected[dtmf_len] = '\0'; + + ast_debug(1, "DTMF feature string on %p(%s) is now '%s'\n", + bridge_channel, ast_channel_name(bridge_channel->chan), + bridge_channel->dtmf_hook_state.collected); + } + + return dtmf_len; +} + +static unsigned int bridge_channel_feature_digit_timeout(struct ast_bridge_channel *bridge_channel) +{ + unsigned int digit_timeout; + struct ast_features_general_config *gen_cfg; + + /* Determine interdigit timeout */ + ast_channel_lock(bridge_channel->chan); + gen_cfg = ast_get_chan_features_general_config(bridge_channel->chan); + ast_channel_unlock(bridge_channel->chan); + + if (!gen_cfg) { + ast_log(LOG_ERROR, "Unable to retrieve features configuration.\n"); + return 3000; /* Pick a reasonable failsafe timeout in ms */ + } + + digit_timeout = gen_cfg->featuredigittimeout; + ao2_ref(gen_cfg, -1); + + return digit_timeout; +} + +void ast_bridge_channel_feature_digit_add(struct ast_bridge_channel *bridge_channel, int digit) +{ + if (digit) { + bridge_channel_feature_digit_add( + bridge_channel, digit, strlen(bridge_channel->dtmf_hook_state.collected)); + } +} + void ast_bridge_channel_feature_digit(struct ast_bridge_channel *bridge_channel, int digit) { struct ast_bridge_features *features = bridge_channel->features; @@ -1527,17 +1572,10 @@ void ast_bridge_channel_feature_digit(struct ast_bridge_channel *bridge_channel, } if (digit) { - /* There should always be room for the new digit. */ - ast_assert(dtmf_len < ARRAY_LEN(bridge_channel->dtmf_hook_state.collected) - 1); - - /* Add the new digit to the DTMF string so we can do our matching */ - bridge_channel->dtmf_hook_state.collected[dtmf_len++] = digit; - bridge_channel->dtmf_hook_state.collected[dtmf_len] = '\0'; - - ast_debug(1, "DTMF feature string on %p(%s) is now '%s'\n", - bridge_channel, ast_channel_name(bridge_channel->chan), - bridge_channel->dtmf_hook_state.collected); + dtmf_len = bridge_channel_feature_digit_add(bridge_channel, digit, dtmf_len); + } + while (digit) { /* See if a DTMF feature hook matches or can match */ hook = ao2_find(features->dtmf_hooks, bridge_channel->dtmf_hook_state.collected, OBJ_SEARCH_PARTIAL_KEY); @@ -1545,25 +1583,12 @@ void ast_bridge_channel_feature_digit(struct ast_bridge_channel *bridge_channel, ast_debug(1, "No DTMF feature hooks on %p(%s) match '%s'\n", bridge_channel, ast_channel_name(bridge_channel->chan), bridge_channel->dtmf_hook_state.collected); + break; } else if (dtmf_len != strlen(hook->dtmf.code)) { unsigned int digit_timeout; - struct ast_features_general_config *gen_cfg; - /* Need more digits to match */ ao2_ref(hook, -1); - - /* Determine interdigit timeout */ - ast_channel_lock(bridge_channel->chan); - gen_cfg = ast_get_chan_features_general_config(bridge_channel->chan); - ast_channel_unlock(bridge_channel->chan); - if (!gen_cfg) { - ast_log(LOG_ERROR, "Unable to retrieve features configuration.\n"); - digit_timeout = 3000; /* Pick a reasonable failsafe timeout in ms */ - } else { - digit_timeout = gen_cfg->featuredigittimeout; - ao2_ref(gen_cfg, -1); - } - + digit_timeout = bridge_channel_feature_digit_timeout(bridge_channel); bridge_channel->dtmf_hook_state.interdigit_timeout = ast_tvadd(ast_tvnow(), ast_samp2tv(digit_timeout, 1000)); return; @@ -1612,10 +1637,21 @@ void ast_bridge_channel_feature_digit(struct ast_bridge_channel *bridge_channel, */ if (bridge_channel->chan && ast_check_hangup_locked(bridge_channel->chan)) { ast_bridge_channel_kick(bridge_channel, 0); + bridge_channel->dtmf_hook_state.collected[0] = '\0'; + return; + } + + /* if there is dtmf that has been collected then loop back through, + but set digit to -1 so it doesn't try to do an add since the dtmf + is already in the buffer */ + dtmf_len = strlen(bridge_channel->dtmf_hook_state.collected); + if (!dtmf_len) { + return; } - return; } - } else { + } + + if (!digit) { ast_debug(1, "DTMF feature string collection on %p(%s) timed out\n", bridge_channel, ast_channel_name(bridge_channel->chan)); } |