aboutsummaryrefslogtreecommitdiffstats
path: root/main
diff options
context:
space:
mode:
authorrussell <russell@f38db490-d61c-443f-a65b-d21fe96a405b>2007-04-24 19:03:16 +0000
committerrussell <russell@f38db490-d61c-443f-a65b-d21fe96a405b>2007-04-24 19:03:16 +0000
commite3343b3289e878c143ae7952edfec370dd065a9d (patch)
tree9eefe7fc138bb94d7fbf65ba50cf30aa241559ad /main
parent27f1a378b7221e31f52548f9a307f1637cb65ea8 (diff)
Merged revisions 61781 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r61781 | russell | 2007-04-24 14:00:06 -0500 (Tue, 24 Apr 2007) | 6 lines Improve DTMF handling in ast_read() even more in response to a discussion on the asterisk-dev mailing list. I changed the enforced minimum length of a digit from 100ms to 80ms. Furthermore, I made it now enforce a gap of 45ms in between digits. These values are not configurable in a configuration file right now, but they can be easily changed near the top of main/channel.c. ........ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@61782 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'main')
-rw-r--r--main/channel.c64
1 files changed, 46 insertions, 18 deletions
diff --git a/main/channel.c b/main/channel.c
index a77aa9450..eb5877bd7 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -104,7 +104,16 @@ unsigned long global_fin, global_fout;
AST_THREADSTORAGE(state2str_threadbuf);
#define STATE2STR_BUFSIZE 32
-#define AST_DEFAULT_EMULATE_DTMF_DURATION 100 /*!< 100ms */
+/*! Default amount of time to use when emulating a digit as a begin and end
+ * 100ms */
+#define AST_DEFAULT_EMULATE_DTMF_DURATION 100
+
+/*! Minimum allowed digit length - 80ms */
+#define AST_MIN_DTMF_DURATION 80
+
+/*! Minimum amount of time between the end of the last digit and the beginning
+ * of a new one - 45ms */
+#define AST_MIN_DTMF_GAP 45
/*! \brief List of channel drivers */
struct chanlist {
@@ -2070,7 +2079,8 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio)
prestate = chan->_state;
if (!ast_test_flag(chan, AST_FLAG_DEFER_DTMF | AST_FLAG_EMULATE_DTMF | AST_FLAG_IN_DTMF) &&
- !ast_strlen_zero(chan->dtmfq)) {
+ !ast_strlen_zero(chan->dtmfq) &&
+ (ast_tvzero(chan->dtmf_tv) || ast_tvdiff_ms(ast_tvnow(), chan->dtmf_tv) > AST_MIN_DTMF_GAP) ) {
/* We have DTMF that has been deferred. Return it now */
chan->dtmff.subclass = chan->dtmfq[0];
/* Drop first digit from the buffer */
@@ -2083,8 +2093,8 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio)
ast_set_flag(chan, AST_FLAG_EMULATE_DTMF);
chan->emulate_dtmf_digit = f->subclass;
chan->emulate_dtmf_duration = AST_DEFAULT_EMULATE_DTMF_DURATION;
- chan->dtmf_begin_tv = ast_tvnow();
}
+ chan->dtmf_tv = ast_tvnow();
goto done;
}
@@ -2222,35 +2232,51 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio)
ast_frfree(f);
f = &ast_null_frame;
} else if (!ast_test_flag(chan, AST_FLAG_IN_DTMF | AST_FLAG_END_DTMF_ONLY)) {
- f->frametype = AST_FRAME_DTMF_BEGIN;
- ast_set_flag(chan, AST_FLAG_EMULATE_DTMF);
- chan->emulate_dtmf_digit = f->subclass;
- chan->dtmf_begin_tv = ast_tvnow();
- if (f->len && f->len > AST_DEFAULT_EMULATE_DTMF_DURATION)
- chan->emulate_dtmf_duration = f->len;
- else
- chan->emulate_dtmf_duration = AST_DEFAULT_EMULATE_DTMF_DURATION;
+ if (!ast_tvzero(chan->dtmf_tv) &&
+ ast_tvdiff_ms(ast_tvnow(), chan->dtmf_tv) < AST_MIN_DTMF_GAP) {
+ /* If it hasn't been long enough, defer this digit */
+ if (strlen(chan->dtmfq) < sizeof(chan->dtmfq) - 2)
+ chan->dtmfq[strlen(chan->dtmfq)] = f->subclass;
+ else
+ ast_log(LOG_WARNING, "Dropping deferred DTMF digits on %s\n", chan->name);
+ ast_frfree(f);
+ f = &ast_null_frame;
+ } else {
+ /* There was no begin, turn this into a begin and send the end later */
+ f->frametype = AST_FRAME_DTMF_BEGIN;
+ ast_set_flag(chan, AST_FLAG_EMULATE_DTMF);
+ chan->emulate_dtmf_digit = f->subclass;
+ chan->dtmf_tv = ast_tvnow();
+ if (f->len && f->len > AST_MIN_DTMF_DURATION)
+ chan->emulate_dtmf_duration = f->len;
+ else
+ chan->emulate_dtmf_duration = AST_MIN_DTMF_DURATION;
+ }
} else {
+ struct timeval now = ast_tvnow();
ast_clear_flag(chan, AST_FLAG_IN_DTMF);
if (!f->len)
- f->len = ast_tvdiff_ms(ast_tvnow(), chan->dtmf_begin_tv);
- if (f->len < AST_DEFAULT_EMULATE_DTMF_DURATION) {
+ f->len = ast_tvdiff_ms(now, chan->dtmf_tv);
+ if (f->len < AST_MIN_DTMF_DURATION) {
ast_set_flag(chan, AST_FLAG_EMULATE_DTMF);
chan->emulate_dtmf_digit = f->subclass;
- chan->emulate_dtmf_duration = AST_DEFAULT_EMULATE_DTMF_DURATION - f->len;
+ chan->emulate_dtmf_duration = AST_MIN_DTMF_DURATION - f->len;
f = &ast_null_frame;
- }
+ } else
+ chan->dtmf_tv = now;
}
break;
case AST_FRAME_DTMF_BEGIN:
send_dtmf_event(chan, "Received", f->subclass, "Yes", "No");
ast_log(LOG_DTMF, "DTMF begin '%c' received on %s\n", f->subclass, chan->name);
- if (ast_test_flag(chan, AST_FLAG_DEFER_DTMF | AST_FLAG_END_DTMF_ONLY)) {
+ if ( ast_test_flag(chan, AST_FLAG_DEFER_DTMF | AST_FLAG_END_DTMF_ONLY) ||
+ (!ast_tvzero(chan->dtmf_tv) &&
+ ast_tvdiff_ms(ast_tvnow(), chan->dtmf_tv) < AST_MIN_DTMF_GAP) ) {
ast_frfree(f);
f = &ast_null_frame;
} else {
ast_set_flag(chan, AST_FLAG_IN_DTMF);
- chan->dtmf_begin_tv = ast_tvnow();
+ chan->dtmf_tv = ast_tvnow();
}
break;
case AST_FRAME_VOICE:
@@ -2268,10 +2294,12 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio)
f = &ast_null_frame;
} else if (ast_test_flag(chan, AST_FLAG_EMULATE_DTMF)) {
if ((f->samples / 8) >= chan->emulate_dtmf_duration) { /* XXX 8kHz */
+ struct timeval now = ast_tvnow();
chan->emulate_dtmf_duration = 0;
f->frametype = AST_FRAME_DTMF_END;
f->subclass = chan->emulate_dtmf_digit;
- f->len = ast_tvdiff_ms(ast_tvnow(), chan->dtmf_begin_tv);
+ f->len = ast_tvdiff_ms(now, chan->dtmf_tv);
+ chan->dtmf_tv = now;
} else {
chan->emulate_dtmf_duration -= f->samples / 8; /* XXX 8kHz */
ast_frfree(f);