diff --git a/apps/app_senddtmf.c b/apps/app_senddtmf.c index 178b13ff0325db830a9fce26adfe4047c276ed16..e0362e7d300e7c64c0748cb88b92bda7e99857b3 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 c865a8a32b2e51e336a47fcd21da19088e3963d1..91aed3468388083a45251fb79c6479008e6b6ce5 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 d0261219e2ae7420cb77a594d2293b41f87e675e..647959792ee31e1610268ee38c8079f448d09255 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)