<p>Corey Farrell has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/6007">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">core: Add digit filtering to ast_waitfordigit_full<br><br>This adds a parameter to ast_waitfordigit_full which can be used to only<br>stop waiting when certain expected digits are received.  Any unexpected<br>DTMF digits are simply ignored.<br><br>This also creates a new dialplan application WaitDigit.<br><br>ASTERISK-27129 #close<br><br>Change-Id: Id233935ea3d13e71c75a0861834c5936c3700ef9<br>---<br>M include/asterisk/channel.h<br>M main/channel.c<br>M main/pbx_builtins.c<br>M res/res_agi.c<br>4 files changed, 92 insertions(+), 10 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/07/6007/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h<br>index 197cc99..cb2e0e6 100644<br>--- a/include/asterisk/channel.h<br>+++ b/include/asterisk/channel.h<br>@@ -2219,11 +2219,12 @@<br>  * Same as ast_waitfordigit() with audio fd for outputting read audio and ctrlfd to monitor for reading.<br>  * \param c channel to wait for a digit on<br>  * \param ms how many milliseconds to wait (<0 for indefinite).<br>+ * \param breakon string of DTMF digits to break upon or NULL for any.<br>  * \param audiofd audio file descriptor to write to if audio frames are received<br>  * \param ctrlfd control file descriptor to monitor for reading<br>  * \return Returns 1 if ctrlfd becomes available<br>  */<br>-int ast_waitfordigit_full(struct ast_channel *c, int ms, int audiofd, int ctrlfd);<br>+int ast_waitfordigit_full(struct ast_channel *c, int ms, const char *breakon, int audiofd, int ctrlfd);<br> <br> /*!<br>  * \brief Reads multiple digits<br>diff --git a/main/channel.c b/main/channel.c<br>index 811826f..27efb2e 100644<br>--- a/main/channel.c<br>+++ b/main/channel.c<br>@@ -3160,7 +3160,7 @@<br> <br> int ast_waitfordigit(struct ast_channel *c, int ms)<br> {<br>-  return ast_waitfordigit_full(c, ms, -1, -1);<br>+ return ast_waitfordigit_full(c, ms, NULL, -1, -1);<br> }<br> <br> int ast_settimeout(struct ast_channel *c, unsigned int rate, int (*func)(const void *data), void *data)<br>@@ -3222,7 +3222,7 @@<br>    return res;<br> }<br> <br>-int ast_waitfordigit_full(struct ast_channel *c, int timeout_ms, int audiofd, int cmdfd)<br>+int ast_waitfordigit_full(struct ast_channel *c, int timeout_ms, const char *breakon, int audiofd, int cmdfd)<br> {<br>     struct timeval start = ast_tvnow();<br>   int ms;<br>@@ -3273,9 +3273,12 @@<br>                               break;<br>                        case AST_FRAME_DTMF_END:<br>                              res = f->subclass.integer;<br>-                                ast_frfree(f);<br>-                               ast_channel_clear_flag(c, AST_FLAG_END_DTMF_ONLY);<br>-                           return res;<br>+                          if (!breakon || strchr(breakon, res)) {<br>+                                      ast_frfree(f);<br>+                                       ast_channel_clear_flag(c, AST_FLAG_END_DTMF_ONLY);<br>+                                   return res;<br>+                          }<br>+                            break;<br>                        case AST_FRAME_CONTROL:<br>                               switch (f->subclass.integer) {<br>                             case AST_CONTROL_HANGUP:<br>@@ -6351,11 +6354,11 @@<br>                             silgen = ast_channel_start_silence_generator(c);<br>                      usleep(1000);<br>                         if (!d)<br>-                              d = ast_waitfordigit_full(c, to, audiofd, ctrlfd);<br>+                           d = ast_waitfordigit_full(c, to, NULL, audiofd, ctrlfd);<br>              } else {<br>                      if (!silgen && ast_opt_transmit_silence)<br>                              silgen = ast_channel_start_silence_generator(c);<br>-                     d = ast_waitfordigit_full(c, to, audiofd, ctrlfd);<br>+                   d = ast_waitfordigit_full(c, to, NULL, audiofd, ctrlfd);<br>              }<br>             if (d < 0) {<br>                       ast_channel_stop_silence_generator(c, silgen);<br>diff --git a/main/pbx_builtins.c b/main/pbx_builtins.c<br>index bc27b0d..9d43c10 100644<br>--- a/main/pbx_builtins.c<br>+++ b/main/pbx_builtins.c<br>@@ -580,6 +580,42 @@<br>                     <para>This application waits for a specified number of <replaceable>seconds</replaceable>.</para><br>             </description><br>  </application><br>+ <application name="WaitDigit" language="en_US"><br>+            <synopsis><br>+                     Waits for a digit to be entered.<br>+             </synopsis><br>+            <syntax><br>+                       <parameter name="seconds"><br>+                           <para>Can be passed with fractions of a second. For example, <literal>1.5</literal> will ask the<br>+                           application to wait for 1.5 seconds.</para><br>+                    </parameter><br>+                   <parameter name="digits"><br>+                            <para>Digits to accept, all others are ignored.</para><br>+                   </parameter><br>+           </syntax><br>+              <description><br>+                  <para>This application waits for the user to press one of the accepted<br>+                 <replaceable>digits</replaceable> for a specified number of<br>+                      <replaceable>seconds</replaceable>.</para><br>+                 <variablelist><br>+                         <variable name="WAITDIGITSTATUS"><br>+                                    <para>This is the final status of the command</para><br>+                                     <value name="ERROR">Parameters are invalid.</value><br>+                                    <value name="DTMF">An accepted digit was received.</value><br>+                                     <value name="TIMEOUT">The timeout passed before any acceptable digits were received.</value><br>+                                   <value name="CANCEL">The channel has hungup or was redirected.</value><br>+                         </variable><br>+                            <variable name="WAITDIGITRESULT"><br>+                                    <para>The digit that was received, only set if<br>+                                 <variable>WAITDIGITSTATUS</variable> is <literal>DTMF</literal>.</para><br>+                                </variable><br>+                    </variablelist><br>+                </description><br>+         <see-also><br>+                     <ref type="application">Wait</ref><br>+                     <ref type="application">WaitExten</ref><br>+                </see-also><br>+    </application><br>  <application name="WaitExten" language="en_US"><br>             <synopsis><br>                      Waits for an extension to be entered.<br>@@ -951,6 +987,47 @@<br>   if (!ast_app_parse_timelen(data, &ms, TIMELEN_SECONDS) && ms > 0) {<br>            return ast_safe_sleep(chan, ms);<br>      }<br>+    return 0;<br>+}<br>+<br>+/*!<br>+ * \ingroup applications<br>+ */<br>+static int pbx_builtin_waitdigit(struct ast_channel *chan, const char *data)<br>+{<br>+   int res;<br>+     int ms;<br>+      char *parse;<br>+ AST_DECLARE_APP_ARGS(args,<br>+           AST_APP_ARG(timeout);<br>+                AST_APP_ARG(digits);<br>+ );<br>+<br>+        parse = ast_strdupa(data);<br>+   AST_STANDARD_APP_ARGS(args, parse);<br>+<br>+       if (ast_app_parse_timelen(args.timeout, &ms, TIMELEN_SECONDS) || ms < 0) {<br>+            pbx_builtin_setvar_helper(chan, "WAITDIGITSTATUS", "ERROR");<br>+             return 0;<br>+    }<br>+<br>+ /* Wait for "n" seconds */<br>+ res = ast_waitfordigit_full(chan, ms, S_OR(args.digits, AST_DIGIT_ANY), -1, -1);<br>+     if (res < 0) {<br>+            pbx_builtin_setvar_helper(chan, "WAITDIGITSTATUS", "CANCEL");<br>+            return -1;<br>+   }<br>+<br>+ if (res == 0) {<br>+              pbx_builtin_setvar_helper(chan, "WAITDIGITSTATUS", "TIMEOUT");<br>+   } else {<br>+             char key[2];<br>+<br>+              snprintf(key, sizeof(key), "%c", res);<br>+             pbx_builtin_setvar_helper(chan, "WAITDIGITRESULT", key);<br>+           pbx_builtin_setvar_helper(chan, "WAITDIGITSTATUS", "DTMF");<br>+      }<br>+<br>  return 0;<br> }<br> <br>@@ -1410,6 +1487,7 @@<br>       { "SayPhonetic",    pbx_builtin_sayphonetic },<br>      { "SetAMAFlags",    pbx_builtin_setamaflags },<br>      { "Wait",           pbx_builtin_wait },<br>+    { "WaitDigit",      pbx_builtin_waitdigit },<br>        { "WaitExten",      pbx_builtin_waitexten }<br> };<br> <br>diff --git a/res/res_agi.c b/res/res_agi.c<br>index e8497f7..4660635 100644<br>--- a/res/res_agi.c<br>+++ b/res/res_agi.c<br>@@ -2393,7 +2393,7 @@<br>             return RESULT_SHOWUSAGE;<br>      if (sscanf(argv[3], "%30d", &to) != 1)<br>          return RESULT_SHOWUSAGE;<br>-     res = ast_waitfordigit_full(chan, to, agi->audio, agi->ctrl);<br>+  res = ast_waitfordigit_full(chan, to, NULL, agi->audio, agi->ctrl);<br>     ast_agi_send(agi->fd, chan, "200 result=%d\n", res);<br>     return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;<br> }<br>@@ -2673,7 +2673,7 @@<br> <br>         /* If the user didnt press a key, wait for digitTimeout*/<br>     if (res == 0 ) {<br>-             res = ast_waitfordigit_full(chan, timeout, agi->audio, agi->ctrl);<br>+             res = ast_waitfordigit_full(chan, timeout, NULL, agi->audio, agi->ctrl);<br>                /* Make sure the new result is in the escape digits of the GET OPTION */<br>              if ( !strchr(edigits,res) )<br>                   res=0;<br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/6007">change 6007</a>. To unsubscribe, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/6007"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: Id233935ea3d13e71c75a0861834c5936c3700ef9 </div>
<div style="display:none"> Gerrit-Change-Number: 6007 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Corey Farrell <git@cfware.com> </div>