[svn-commits] russell: branch 1.4 r61781 - in /branches/1.4: include/asterisk/ main/

svn-commits at lists.digium.com svn-commits at lists.digium.com
Tue Apr 24 12:00:06 MST 2007


Author: russell
Date: Tue Apr 24 14:00:06 2007
New Revision: 61781

URL: http://svn.digium.com/view/asterisk?view=rev&rev=61781
Log:
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.

Modified:
    branches/1.4/include/asterisk/channel.h
    branches/1.4/main/channel.c

Modified: branches/1.4/include/asterisk/channel.h
URL: http://svn.digium.com/view/asterisk/branches/1.4/include/asterisk/channel.h?view=diff&rev=61781&r1=61780&r2=61781
==============================================================================
--- branches/1.4/include/asterisk/channel.h (original)
+++ branches/1.4/include/asterisk/channel.h Tue Apr 24 14:00:06 2007
@@ -428,7 +428,7 @@
 
 	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;

Modified: branches/1.4/main/channel.c
URL: http://svn.digium.com/view/asterisk/branches/1.4/main/channel.c?view=diff&rev=61781&r1=61780&r2=61781
==============================================================================
--- branches/1.4/main/channel.c (original)
+++ branches/1.4/main/channel.c Tue Apr 24 14:00:06 2007
@@ -104,8 +104,16 @@
 AST_THREADSTORAGE(state2str_threadbuf, state2str_threadbuf_init);
 #define STATE2STR_BUFSIZE   32
 
-/*! 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
 
 struct chanlist {
 	const struct ast_channel_tech *tech;
@@ -2113,7 +2121,8 @@
 	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 */
@@ -2126,8 +2135,8 @@
 			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;
 	}
 	
@@ -2264,34 +2273,50 @@
 				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:
 			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:
@@ -2309,10 +2334,12 @@
 				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);



More information about the svn-commits mailing list