]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Merged revisions 61781 via svnmerge from
authorRussell Bryant <russell@russellbryant.com>
Tue, 24 Apr 2007 19:03:16 +0000 (19:03 +0000)
committerRussell Bryant <russell@russellbryant.com>
Tue, 24 Apr 2007 19:03:16 +0000 (19:03 +0000)
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: https://origsvn.digium.com/svn/asterisk/trunk@61782 65c4cc65-6c06-0410-ace0-fbb531ad65f3

include/asterisk/channel.h
main/channel.c

index 6fa71ad11b6cc82143d93c8427c329ebdeba81f3..6b1ab4a833ad0400d6be7646699fda1d1a963752 100644 (file)
@@ -487,7 +487,7 @@ struct ast_channel {
 
        char emulate_dtmf_digit;                        /*!< Digit being emulated */
        unsigned int emulate_dtmf_duration;     /*!< Number of ms left to emulate DTMF for */
-       struct timeval dtmf_begin_tv;       /*!< The time that an in process digit began */
+       struct timeval dtmf_tv;       /*!< The time that an in process digit began, or the last digit ended */
 
        /*! \brief Data stores on the channel */
        AST_LIST_HEAD_NOLOCK(datastores, ast_datastore) datastores;
index a77aa9450461d935c0c21b85f2b48f7e290d5758..eb5877bd766942a846054a8d0efa933fec18b3f2 100644 (file)
@@ -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);