From 7d874c1af78a74efa226bab9501d5ba63a907ab7 Mon Sep 17 00:00:00 2001 From: Richard Mudgett <rmudgett@digium.com> Date: Wed, 13 Jun 2018 13:05:03 -0500 Subject: [PATCH] AMI PlayDTMF Action: Make not compete with channel's media thread. There can be one and only one thread handling a channel's media at a time. Otherwise, we don't know which thread is going to handle the media frames. ASTERISK-27625 Change-Id: Ia341f1a6f4d54f2022261abec9021fe5b2eb4905 --- apps/app_senddtmf.c | 2 +- include/asterisk/channel.h | 18 ++++++++++++++++++ main/channel.c | 20 ++++++++++++++++++-- 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/apps/app_senddtmf.c b/apps/app_senddtmf.c index 178b13ff03..e0362e7d30 100644 --- a/apps/app_senddtmf.c +++ b/apps/app_senddtmf.c @@ -167,7 +167,7 @@ static int manager_play_dtmf(struct mansession *s, const struct message *m) return 0; } - ast_senddigit(chan, *digit, duration_ms); + ast_senddigit_external(chan, *digit, duration_ms); chan = ast_channel_unref(chan); diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h index c865a8a32b..91aed34683 100644 --- a/include/asterisk/channel.h +++ b/include/asterisk/channel.h @@ -2177,13 +2177,31 @@ int ast_recvchar(struct ast_channel *chan, int timeout); /*! * \brief Send a DTMF digit to a channel. + * * \param chan channel to act upon * \param digit the DTMF digit to send, encoded in ASCII * \param duration the duration of the digit ending in ms + * + * \pre This must only be called by the channel's media handler thread. + * * \return 0 on success, -1 on failure */ int ast_senddigit(struct ast_channel *chan, char digit, unsigned int duration); +/*! + * \brief Send a DTMF digit to a channel from an external thread. + * + * \param chan channel to act upon + * \param digit the DTMF digit to send, encoded in ASCII + * \param duration the duration of the digit ending in ms + * + * \pre This must only be called by threads that are not the channel's + * media handler thread. + * + * \return 0 on success, -1 on failure + */ +int ast_senddigit_external(struct ast_channel *chan, char digit, unsigned int duration); + /*! * \brief Send a DTMF digit to a channel. * \param chan channel to act upon diff --git a/main/channel.c b/main/channel.c index d0261219e2..647959792e 100644 --- a/main/channel.c +++ b/main/channel.c @@ -4810,12 +4810,28 @@ int ast_senddigit_end(struct ast_channel *chan, char digit, unsigned int duratio int ast_senddigit(struct ast_channel *chan, char digit, unsigned int duration) { + if (duration < AST_DEFAULT_EMULATE_DTMF_DURATION) { + duration = AST_DEFAULT_EMULATE_DTMF_DURATION; + } + if (ast_channel_tech(chan)->send_digit_begin) { + ast_senddigit_begin(chan, digit); + ast_safe_sleep(chan, duration); + } + + return ast_senddigit_end(chan, digit, duration); +} + +int ast_senddigit_external(struct ast_channel *chan, char digit, unsigned int duration) +{ + if (duration < AST_DEFAULT_EMULATE_DTMF_DURATION) { + duration = AST_DEFAULT_EMULATE_DTMF_DURATION; + } if (ast_channel_tech(chan)->send_digit_begin) { ast_senddigit_begin(chan, digit); - ast_safe_sleep(chan, (duration >= AST_DEFAULT_EMULATE_DTMF_DURATION ? duration : AST_DEFAULT_EMULATE_DTMF_DURATION)); + usleep(duration * 1000); } - return ast_senddigit_end(chan, digit, (duration >= AST_DEFAULT_EMULATE_DTMF_DURATION ? duration : AST_DEFAULT_EMULATE_DTMF_DURATION)); + return ast_senddigit_end(chan, digit, duration); } int ast_prod(struct ast_channel *chan) -- GitLab