diff --git a/res/res_tonedetect.c b/res/res_tonedetect.c index 2e9d96d8fe..7ca0abe6c0 100644 --- a/res/res_tonedetect.c +++ b/res/res_tonedetect.c @@ -213,13 +213,16 @@ Custom decibel threshold to use. Default is 16. + + Automatically end detection after desired number of hits (as specified in the n option. + Go to the specified context,exten,priority if tone is received on this channel. - Detection will not end automatically. + Detection will not end automatically, unless the e option is also specified. Go to the specified context,exten,priority if tone is transmitted on this channel. - Detection will not end automatically. + Detection will not end automatically, unless the e option is also specified. Number of times the tone should be detected (subject to the @@ -278,9 +281,11 @@ struct detect_information { int db; char *gototx; char *gotorx; - unsigned short int squelch; - unsigned short int tx; - unsigned short int rx; + unsigned int squelch:1; + unsigned int tx:1; + unsigned int rx:1; + unsigned int autoend:1; + unsigned int matchmet:1; int txcount; int rxcount; int hitsrequired; @@ -300,6 +305,7 @@ enum td_opts { OPT_BUSY = (1 << 10), OPT_DIALTONE = (1 << 11), OPT_RINGING = (1 << 12), + OPT_AUTOEND = (1 << 13), }; enum { @@ -316,6 +322,7 @@ AST_APP_OPTIONS(td_opts, { AST_APP_OPTION('b', OPT_BUSY), AST_APP_OPTION('c', OPT_DIALTONE), AST_APP_OPTION_ARG('d', OPT_DECIBEL, OPT_ARG_DECIBEL), + AST_APP_OPTION('e', OPT_AUTOEND), AST_APP_OPTION_ARG('g', OPT_GOTO_RX, OPT_ARG_GOTO_RX), AST_APP_OPTION_ARG('h', OPT_GOTO_TX, OPT_ARG_GOTO_TX), AST_APP_OPTION_ARG('n', OPT_HITS_REQ, OPT_ARG_HITS_REQ), @@ -371,6 +378,14 @@ static int detect_callback(struct ast_audiohook *audiohook, struct ast_channel * return 0; } + /* If we've detected a match, it is very likely that we could detect additional matches, + * which is a problem if the 'g' or 'h' options were used to trigger a redirect, + * since if we detect again before disabling TONE_DETECT, we could redirect multiple times. + * If we don't need to detect anything further, just exit early until the user disables it. */ + if (di->matchmet && di->autoend) { + return 0; + } + if (!(direction == AST_AUDIOHOOK_DIRECTION_READ ? di->rx : di->tx)) { return 0; } @@ -392,6 +407,7 @@ static int detect_callback(struct ast_audiohook *audiohook, struct ast_channel * } ast_debug(1, "TONE_DETECT just got a hit (#%d in this direction, waiting for %d total)\n", now, di->hitsrequired); if (now >= di->hitsrequired) { + di->matchmet = 1; if (direction == AST_AUDIOHOOK_DIRECTION_READ && di->gotorx) { ast_async_parseable_goto(chan, di->gotorx); } else if (di->gototx) { @@ -713,7 +729,8 @@ static int detect_write(struct ast_channel *chan, const char *cmd, char *data, c } di->db = db; di->hitsrequired = hitsrequired; - di->squelch = ast_test_flag(&flags, OPT_SQUELCH); + di->squelch = ast_test_flag(&flags, OPT_SQUELCH) ? 1 : 0; + di->autoend = ast_test_flag(&flags, OPT_AUTOEND) ? 1 : 0; di->tx = 1; di->rx = 1; if (ast_strlen_zero(args.options) || ast_test_flag(&flags, OPT_TX)) { @@ -1022,7 +1039,7 @@ static int scan_exec(struct ast_channel *chan, const char *data) ast_dsp_free(dsp); if (dsp2) { ast_dsp_free(dsp2); - } + } return 0; }