diff --git a/apps/app_senddtmf.c b/apps/app_senddtmf.c index 25444a323a..5dde8dc336 100644 --- a/apps/app_senddtmf.c +++ b/apps/app_senddtmf.c @@ -169,7 +169,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 8ec74e6136..0fc236af4b 100644 --- a/include/asterisk/channel.h +++ b/include/asterisk/channel.h @@ -2111,13 +2111,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 a5cc4e7e9f..27a959a4b9 100644 --- a/main/channel.c +++ b/main/channel.c @@ -5029,12 +5029,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 >= AST_DEFAULT_EMULATE_DTMF_DURATION ? duration : AST_DEFAULT_EMULATE_DTMF_DURATION)); + ast_safe_sleep(chan, duration); } - 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_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); + usleep(duration * 1000); + } + + return ast_senddigit_end(chan, digit, duration); } int ast_prod(struct ast_channel *chan)