app_read: Allow reading # as a digit
Allows for the digit # to be read as a digit, just like any other DTMF digit, as opposed to forcing it to be used as an end of input indicator. The default behavior remains unchanged. ASTERISK-18454 #close Change-Id: I3033432adb9d296ad227e76b540b8b4a2417665b
This commit is contained in:
parent
18189ff594
commit
0e4a1c5079
|
@ -75,6 +75,16 @@
|
|||
<option name="n">
|
||||
<para>to read digits even if the line is not up.</para>
|
||||
</option>
|
||||
<option name="t">
|
||||
<para>Terminator digit(s) to use for ending input.
|
||||
Default is <literal>#</literal>. If you need to read
|
||||
the digit <literal>#</literal> literally, you should
|
||||
remove or change the terminator character. Multiple
|
||||
terminator characters may be specified. If no terminator
|
||||
digit is present, input cannot be ended using digits
|
||||
and you will need to rely on duration and max digits
|
||||
for ending input.</para>
|
||||
</option>
|
||||
</optionlist>
|
||||
</parameter>
|
||||
<parameter name="attempts">
|
||||
|
@ -114,12 +124,20 @@ enum read_option_flags {
|
|||
OPT_SKIP = (1 << 0),
|
||||
OPT_INDICATION = (1 << 1),
|
||||
OPT_NOANSWER = (1 << 2),
|
||||
OPT_TERMINATOR = (1 << 3),
|
||||
};
|
||||
|
||||
enum {
|
||||
OPT_ARG_TERMINATOR,
|
||||
/* note: this entry _MUST_ be the last one in the enum */
|
||||
OPT_ARG_ARRAY_SIZE,
|
||||
};
|
||||
|
||||
AST_APP_OPTIONS(read_app_options, {
|
||||
AST_APP_OPTION('s', OPT_SKIP),
|
||||
AST_APP_OPTION('i', OPT_INDICATION),
|
||||
AST_APP_OPTION('n', OPT_NOANSWER),
|
||||
AST_APP_OPTION_ARG('t', OPT_TERMINATOR, OPT_ARG_TERMINATOR),
|
||||
});
|
||||
|
||||
static char *app = "Read";
|
||||
|
@ -132,9 +150,11 @@ static int read_exec(struct ast_channel *chan, const char *data)
|
|||
int tries = 1, to = 0, x = 0;
|
||||
double tosec;
|
||||
char *argcopy = NULL;
|
||||
char *opt_args[OPT_ARG_ARRAY_SIZE];
|
||||
struct ast_tone_zone_sound *ts = NULL;
|
||||
struct ast_flags flags = {0};
|
||||
const char *status = "ERROR";
|
||||
char *terminator = NULL; /* use default terminator # by default */
|
||||
|
||||
AST_DECLARE_APP_ARGS(arglist,
|
||||
AST_APP_ARG(variable);
|
||||
|
@ -156,7 +176,7 @@ static int read_exec(struct ast_channel *chan, const char *data)
|
|||
AST_STANDARD_APP_ARGS(arglist, argcopy);
|
||||
|
||||
if (!ast_strlen_zero(arglist.options)) {
|
||||
ast_app_parse_options(read_app_options, &flags, NULL, arglist.options);
|
||||
ast_app_parse_options(read_app_options, &flags, opt_args, arglist.options);
|
||||
}
|
||||
|
||||
if (!ast_strlen_zero(arglist.attempts)) {
|
||||
|
@ -192,6 +212,13 @@ static int read_exec(struct ast_channel *chan, const char *data)
|
|||
ts = ast_get_indication_tone(ast_channel_zone(chan), arglist.filename);
|
||||
}
|
||||
}
|
||||
if (ast_test_flag(&flags, OPT_TERMINATOR)) {
|
||||
if (!ast_strlen_zero(arglist.filename)) {
|
||||
terminator = opt_args[OPT_ARG_TERMINATOR];
|
||||
} else {
|
||||
terminator = ""; /* no digit inherently will terminate input */
|
||||
}
|
||||
}
|
||||
if (ast_channel_state(chan) != AST_STATE_UP) {
|
||||
if (ast_test_flag(&flags, OPT_SKIP)) {
|
||||
/* At the user's option, skip if the line is not up */
|
||||
|
@ -223,7 +250,7 @@ static int read_exec(struct ast_channel *chan, const char *data)
|
|||
break;
|
||||
}
|
||||
tmp[x++] = res;
|
||||
if (tmp[x-1] == '#') {
|
||||
if (strchr(terminator, tmp[x-1])) {
|
||||
tmp[x-1] = '\0';
|
||||
status = "OK";
|
||||
break;
|
||||
|
@ -233,7 +260,7 @@ static int read_exec(struct ast_channel *chan, const char *data)
|
|||
}
|
||||
}
|
||||
} else {
|
||||
res = ast_app_getdata(chan, arglist.filename, tmp, maxdigits, to);
|
||||
res = ast_app_getdata_terminator(chan, arglist.filename, tmp, maxdigits, to, terminator);
|
||||
if (res == AST_GETDATA_COMPLETE || res == AST_GETDATA_EMPTY_END_TERMINATED)
|
||||
status = "OK";
|
||||
else if (res == AST_GETDATA_TIMEOUT)
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
Subject: app_read
|
||||
|
||||
A new option allows the digit '#' to be read literally,
|
||||
rather than used exclusively as the input terminator
|
||||
character.
|
|
@ -137,6 +137,23 @@ int ast_ivr_menu_run(struct ast_channel *c, struct ast_ivr_menu *menu, void *cbd
|
|||
*/
|
||||
int ast_app_getdata(struct ast_channel *c, const char *prompt, char *s, int maxlen, int timeout);
|
||||
|
||||
/*! \brief Plays a stream and gets DTMF data from a channel
|
||||
* \param c Which channel one is interacting with
|
||||
* \param prompt File to pass to ast_streamfile (the one that you wish to play).
|
||||
* It is also valid for this to be multiple files concatenated by "&".
|
||||
* For example, "file1&file2&file3".
|
||||
* \param s The location where the DTMF data will be stored
|
||||
* \param maxlen Max Length of the data
|
||||
* \param timeout Timeout length waiting for data(in milliseconds). Set to 0 for standard timeout(six seconds), or -1 for no time out.
|
||||
* \param terminator A string of characters that may be used as terminators to end input. If NULL, "#" will be used.
|
||||
*
|
||||
* This function was designed for application programmers for situations where they need
|
||||
* to play a message and then get some DTMF data in response to the message. If a digit
|
||||
* is pressed during playback, it will immediately break out of the message and continue
|
||||
* execution of your code.
|
||||
*/
|
||||
int ast_app_getdata_terminator(struct ast_channel *c, const char *prompt, char *s, int maxlen, int timeout, char *terminator);
|
||||
|
||||
/*! \brief Full version with audiofd and controlfd. NOTE: returns '2' on ctrlfd available, not '1' like other full functions */
|
||||
int ast_app_getdata_full(struct ast_channel *c, const char *prompt, char *s, int maxlen, int timeout, int audiofd, int ctrlfd);
|
||||
|
||||
|
|
21
main/app.c
21
main/app.c
|
@ -193,8 +193,25 @@ int ast_app_dtget(struct ast_channel *chan, const char *context, char *collect,
|
|||
* \param s The string to read in to. Must be at least the size of your length
|
||||
* \param maxlen How many digits to read (maximum)
|
||||
* \param timeout set timeout to 0 for "standard" timeouts. Set timeout to -1 for
|
||||
* "ludicrous time" (essentially never times out) */
|
||||
* "ludicrous time" (essentially never times out)
|
||||
*/
|
||||
enum ast_getdata_result ast_app_getdata(struct ast_channel *c, const char *prompt, char *s, int maxlen, int timeout)
|
||||
{
|
||||
return ast_app_getdata_terminator(c, prompt, s, maxlen, timeout, NULL);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief ast_app_getdata
|
||||
* \param c The channel to read from
|
||||
* \param prompt The file to stream to the channel
|
||||
* \param s The string to read in to. Must be at least the size of your length
|
||||
* \param maxlen How many digits to read (maximum)
|
||||
* \param timeout set timeout to 0 for "standard" timeouts. Set timeout to -1 for
|
||||
* "ludicrous time" (essentially never times out)
|
||||
* \param terminator A string of characters that may be used as terminators to end input. Default if NULL is "#"
|
||||
*/
|
||||
enum ast_getdata_result ast_app_getdata_terminator(struct ast_channel *c, const char *prompt, char *s,
|
||||
int maxlen, int timeout, char *terminator)
|
||||
{
|
||||
int res = 0, to, fto;
|
||||
char *front, *filename;
|
||||
|
@ -232,7 +249,7 @@ enum ast_getdata_result ast_app_getdata(struct ast_channel *c, const char *promp
|
|||
fto = 50;
|
||||
to = ast_channel_pbx(c) ? ast_channel_pbx(c)->dtimeoutms : 2000;
|
||||
}
|
||||
res = ast_readstring(c, s, maxlen, to, fto, "#");
|
||||
res = ast_readstring(c, s, maxlen, to, fto, S_OR(terminator, "#"));
|
||||
if (res == AST_GETDATA_EMPTY_END_TERMINATED) {
|
||||
return res;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue