mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-16 09:52:24 +00:00
res_tonedetect: Add option for TONE_DETECT detection to auto stop.
One of the problems with TONE_DETECT as it was originally written is that if a tone is detected multiple times, it can trigger the redirect logic multiple times as well. For example, if we do an async goto in the dialplan after detecting a tone, because the detector is still active until explicitly disabled, if we detect the tone again, we will branch again and start executing that dialplan a second time. This is rarely ever desired behavior, and can happen if the detector is not removed quickly enough. Add a new option, 'e', which automatically disables the detector once the desired number of matches have been heard. This eliminates the potential race condition where previously the detector would need to be disabled immediately, but doing so quickly enough was not guaranteed. This also allows match criteria to be retained longer if needed, so the detector does not need to be destroyed prematurely. Resolves: #1390 UserNote: The 'e' option for TONE_DETECT now allows detection to be disabled automatically once the desired number of matches have been fulfilled, which can help prevent race conditions in the dialplan, since TONE_DETECT does not need to be disabled after a hit.
This commit is contained in:
@@ -214,13 +214,16 @@
|
||||
<option name="d">
|
||||
<para>Custom decibel threshold to use. Default is 16.</para>
|
||||
</option>
|
||||
<option name="e">
|
||||
<para>Automatically end detection after desired number of hits (as specified in the <literal>n</literal> option.</para>
|
||||
</option>
|
||||
<option name="g">
|
||||
<para>Go to the specified context,exten,priority if tone is received on this channel.
|
||||
Detection will not end automatically.</para>
|
||||
Detection will not end automatically, unless the <literal>e</literal> option is also specified.</para>
|
||||
</option>
|
||||
<option name="h">
|
||||
<para>Go to the specified context,exten,priority if tone is transmitted on this channel.
|
||||
Detection will not end automatically.</para>
|
||||
Detection will not end automatically, unless the <literal>e</literal> option is also specified.</para>
|
||||
</option>
|
||||
<option name="n">
|
||||
<para>Number of times the tone should be detected (subject to the
|
||||
@@ -279,9 +282,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;
|
||||
@@ -301,6 +306,7 @@ enum td_opts {
|
||||
OPT_BUSY = (1 << 10),
|
||||
OPT_DIALTONE = (1 << 11),
|
||||
OPT_RINGING = (1 << 12),
|
||||
OPT_AUTOEND = (1 << 13),
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -317,6 +323,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),
|
||||
@@ -373,6 +380,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;
|
||||
}
|
||||
@@ -398,12 +413,12 @@ static int detect_callback(struct ast_audiohook *audiohook, struct ast_channel *
|
||||
|
||||
if (!message) {
|
||||
ast_log(LOG_ERROR, "Unable to publish tone detected event for ARI on channel '%s'", ast_channel_name(chan));
|
||||
return 1;
|
||||
} else {
|
||||
stasis_publish(ast_channel_topic(chan), message);
|
||||
ao2_ref(message, -1);
|
||||
}
|
||||
|
||||
di->matchmet = 1;
|
||||
if (direction == AST_AUDIOHOOK_DIRECTION_READ && di->gotorx) {
|
||||
ast_async_parseable_goto(chan, di->gotorx);
|
||||
} else if (di->gototx) {
|
||||
@@ -725,7 +740,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)) {
|
||||
@@ -1034,7 +1050,7 @@ static int scan_exec(struct ast_channel *chan, const char *data)
|
||||
ast_dsp_free(dsp);
|
||||
if (dsp2) {
|
||||
ast_dsp_free(dsp2);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Reference in New Issue
Block a user