<p>George Joseph <strong>merged</strong> this change.</p><p><a href="https://gerrit.asterisk.org/9210">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
Sean Bright: Looks good to me, approved
George Joseph: Approved for Submit
</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">ARI POST DTMF: Make not compete with channel's media thread.<br><br>There can be one and only one thread handling a channel's media at a time.<br>Otherwise, we don't know which thread is going to handle the media frames.<br><br>ASTERISK-27625<br><br>Change-Id: I4d6a2fe7386ea447ee199003bf8ad681cb30454e<br>---<br>M include/asterisk/app.h<br>M main/app.c<br>M res/stasis/control.c<br>3 files changed, 115 insertions(+), 34 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">diff --git a/include/asterisk/app.h b/include/asterisk/app.h<br>index 5b10b1c..0865121 100644<br>--- a/include/asterisk/app.h<br>+++ b/include/asterisk/app.h<br>@@ -923,24 +923,51 @@<br> void ast_unreplace_sigchld(void);<br> <br> /*!<br>- \brief Send DTMF to a channel<br>-<br>- \param chan The channel that will receive the DTMF frames<br>- \param peer (optional) Peer channel that will be autoserviced while the<br>- primary channel is receiving DTMF<br>- \param digits This is a string of characters representing the DTMF digits<br>- to be sent to the channel. Valid characters are<br>- "0123456789*#abcdABCD". Note: You can pass arguments 'f' or<br>- 'F', if you want to Flash the channel (if supported by the<br>- channel), or 'w' to add a 500 millisecond pause to the DTMF<br>- sequence.<br>- \param between This is the number of milliseconds to wait in between each<br>- DTMF digit. If zero milliseconds is specified, then the<br>- default value of 100 will be used.<br>- \param duration This is the duration that each DTMF digit should have.<br>-*/<br>+ * \brief Send a string of DTMF digits to a channel<br>+ *<br>+ * \param chan The channel that will receive the DTMF frames<br>+ * \param peer (optional) Peer channel that will be autoserviced while the<br>+ * primary channel is receiving DTMF<br>+ * \param digits This is a string of characters representing the DTMF digits<br>+ * to be sent to the channel. Valid characters are<br>+ * "0123456789*#abcdABCD". Note: You can pass arguments 'f' or<br>+ * 'F', if you want to Flash the channel (if supported by the<br>+ * channel), or 'w' to add a 500 millisecond pause to the DTMF<br>+ * sequence.<br>+ * \param between This is the number of milliseconds to wait in between each<br>+ * DTMF digit. If zero milliseconds is specified, then the<br>+ * default value of 100 will be used.<br>+ * \param duration This is the duration that each DTMF digit should have.<br>+ *<br>+ * \pre This must only be called by the channel's media handler thread.<br>+ *<br>+ * \retval 0 on success.<br>+ * \retval -1 on failure or a channel hung up.<br>+ */<br> int ast_dtmf_stream(struct ast_channel *chan, struct ast_channel *peer, const char *digits, int between, unsigned int duration);<br> <br>+/*!<br>+ * \brief Send a string of DTMF digits to a channel from an external thread.<br>+ *<br>+ * \param chan The channel that will receive the DTMF frames<br>+ * \param digits This is a string of characters representing the DTMF digits<br>+ * to be sent to the channel. Valid characters are<br>+ * "0123456789*#abcdABCD". Note: You can pass arguments 'f' or<br>+ * 'F', if you want to Flash the channel (if supported by the<br>+ * channel), or 'w' to add a 500 millisecond pause to the DTMF<br>+ * sequence.<br>+ * \param between This is the number of milliseconds to wait in between each<br>+ * DTMF digit. If zero milliseconds is specified, then the<br>+ * default value of 100 will be used.<br>+ * \param duration This is the duration that each DTMF digit should have.<br>+ *<br>+ * \pre This must only be called by threads that are not the channel's<br>+ * media handler thread.<br>+ *<br>+ * \return Nothing<br>+ */<br>+void ast_dtmf_stream_external(struct ast_channel *chan, const char *digits, int between, unsigned int duration);<br>+<br> /*! \brief Stream a filename (or file descriptor) as a generator. */<br> int ast_linear_stream(struct ast_channel *chan, const char *filename, int fd, int allowoverride);<br> <br>diff --git a/main/app.c b/main/app.c<br>index 331c827..e7aab10 100644<br>--- a/main/app.c<br>+++ b/main/app.c<br>@@ -875,25 +875,37 @@<br> }<br> #endif<br> <br>-int ast_dtmf_stream(struct ast_channel *chan, struct ast_channel *peer, const char *digits, int between, unsigned int duration)<br>+static int external_sleep(struct ast_channel *chan, int ms)<br>+{<br>+ usleep(ms * 1000);<br>+ return 0;<br>+}<br>+<br>+static int dtmf_stream(struct ast_channel *chan, const char *digits, int between, unsigned int duration, int is_external)<br> {<br> const char *ptr;<br> int res;<br> struct ast_silence_generator *silgen = NULL;<br>+ int (*my_sleep)(struct ast_channel *chan, int ms);<br>+ int (*my_senddigit)(struct ast_channel *chan, char digit, unsigned int duration);<br>+<br>+ if (is_external) {<br>+ my_sleep = external_sleep;<br>+ my_senddigit = ast_senddigit_external;<br>+ } else {<br>+ my_sleep = ast_safe_sleep;<br>+ my_senddigit = ast_senddigit;<br>+ }<br> <br> if (!between) {<br> between = 100;<br>- }<br>-<br>- if (peer && ast_autoservice_start(peer)) {<br>- return -1;<br> }<br> <br> /* Need a quiet time before sending digits. */<br> if (ast_opt_transmit_silence) {<br> silgen = ast_channel_start_silence_generator(chan);<br> }<br>- res = ast_safe_sleep(chan, 100);<br>+ res = my_sleep(chan, 100);<br> if (res) {<br> goto dtmf_stream_cleanup;<br> }<br>@@ -901,12 +913,14 @@<br> for (ptr = digits; *ptr; ptr++) {<br> if (*ptr == 'w') {<br> /* 'w' -- wait half a second */<br>- if ((res = ast_safe_sleep(chan, 500))) {<br>+ res = my_sleep(chan, 500);<br>+ if (res) {<br> break;<br> }<br> } else if (*ptr == 'W') {<br> /* 'W' -- wait a second */<br>- if ((res = ast_safe_sleep(chan, 1000))) {<br>+ res = my_sleep(chan, 1000);<br>+ if (res) {<br> break;<br> }<br> } else if (strchr("0123456789*#abcdfABCDF", *ptr)) {<br>@@ -915,10 +929,11 @@<br> ast_indicate(chan, AST_CONTROL_FLASH);<br> } else {<br> /* Character represents valid DTMF */<br>- ast_senddigit(chan, *ptr, duration);<br>+ my_senddigit(chan, *ptr, duration);<br> }<br> /* pause between digits */<br>- if ((res = ast_safe_sleep(chan, between))) {<br>+ res = my_sleep(chan, between);<br>+ if (res) {<br> break;<br> }<br> } else {<br>@@ -930,6 +945,18 @@<br> if (silgen) {<br> ast_channel_stop_silence_generator(chan, silgen);<br> }<br>+<br>+ return res;<br>+}<br>+<br>+int ast_dtmf_stream(struct ast_channel *chan, struct ast_channel *peer, const char *digits, int between, unsigned int duration)<br>+{<br>+ int res;<br>+<br>+ if (peer && ast_autoservice_start(peer)) {<br>+ return -1;<br>+ }<br>+ res = dtmf_stream(chan, digits, between, duration, 0);<br> if (peer && ast_autoservice_stop(peer)) {<br> res = -1;<br> }<br>@@ -937,6 +964,11 @@<br> return res;<br> }<br> <br>+void ast_dtmf_stream_external(struct ast_channel *chan, const char *digits, int between, unsigned int duration)<br>+{<br>+ dtmf_stream(chan, digits, between, duration, 1);<br>+}<br>+<br> struct linear_state {<br> int fd;<br> int autoclose;<br>diff --git a/res/stasis/control.c b/res/stasis/control.c<br>index df97931..1821f20 100644<br>--- a/res/stasis/control.c<br>+++ b/res/stasis/control.c<br>@@ -503,6 +503,32 @@<br> char dtmf[];<br> };<br> <br>+static void dtmf_in_bridge(struct ast_channel *chan, struct stasis_app_control_dtmf_data *dtmf_data)<br>+{<br>+ if (dtmf_data->before) {<br>+ usleep(dtmf_data->before * 1000);<br>+ }<br>+<br>+ ast_dtmf_stream_external(chan, dtmf_data->dtmf, dtmf_data->between, dtmf_data->duration);<br>+<br>+ if (dtmf_data->after) {<br>+ usleep(dtmf_data->after * 1000);<br>+ }<br>+}<br>+<br>+static void dtmf_no_bridge(struct ast_channel *chan, struct stasis_app_control_dtmf_data *dtmf_data)<br>+{<br>+ if (dtmf_data->before) {<br>+ ast_safe_sleep(chan, dtmf_data->before);<br>+ }<br>+<br>+ ast_dtmf_stream(chan, NULL, dtmf_data->dtmf, dtmf_data->between, dtmf_data->duration);<br>+<br>+ if (dtmf_data->after) {<br>+ ast_safe_sleep(chan, dtmf_data->after);<br>+ }<br>+}<br>+<br> static int app_control_dtmf(struct stasis_app_control *control,<br> struct ast_channel *chan, void *data)<br> {<br>@@ -512,14 +538,10 @@<br> ast_indicate(chan, AST_CONTROL_PROGRESS);<br> }<br> <br>- if (dtmf_data->before) {<br>- ast_safe_sleep(chan, dtmf_data->before);<br>- }<br>-<br>- ast_dtmf_stream(chan, NULL, dtmf_data->dtmf, dtmf_data->between, dtmf_data->duration);<br>-<br>- if (dtmf_data->after) {<br>- ast_safe_sleep(chan, dtmf_data->after);<br>+ if (stasis_app_get_bridge(control)) {<br>+ dtmf_in_bridge(chan, dtmf_data);<br>+ } else {<br>+ dtmf_no_bridge(chan, dtmf_data);<br> }<br> <br> return 0;<br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/9210">change 9210</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/9210"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 13 </div>
<div style="display:none"> Gerrit-MessageType: merged </div>
<div style="display:none"> Gerrit-Change-Id: I4d6a2fe7386ea447ee199003bf8ad681cb30454e </div>
<div style="display:none"> Gerrit-Change-Number: 9210 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Richard Mudgett <rmudgett@digium.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>
<div style="display:none"> Gerrit-Reviewer: Richard Mudgett <rmudgett@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Sean Bright <sean.bright@gmail.com> </div>