<p>Joshua Colp <strong>merged</strong> this change.</p><p><a href="https://gerrit.asterisk.org/6007">View Change</a></p><div style="white-space:pre-wrap">Approvals:
Kevin Harwell: Looks good to me, but someone else must approve
Joshua Colp: Looks good to me, but someone else must approve; Approved for Submit
George Joseph: Looks good to me, approved
</div><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;">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: merged </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>
<div style="display:none"> Gerrit-Reviewer: Corey Farrell <git@cfware.com> </div>
<div style="display:none"> Gerrit-Reviewer: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins2 </div>
<div style="display:none"> Gerrit-Reviewer: Joshua Colp <jcolp@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Kevin Harwell <kharwell@digium.com> </div>