Skip to content

Commit 6cc004d

Browse files
InterLinked1gtjoseph
authored andcommitted
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
1 parent 6fbf55a commit 6cc004d

File tree

4 files changed

+71
-5
lines changed

4 files changed

+71
-5
lines changed

Diff for: apps/app_read.c

+30-3
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,16 @@
7575
<option name="n">
7676
<para>to read digits even if the line is not up.</para>
7777
</option>
78+
<option name="t">
79+
<para>Terminator digit(s) to use for ending input.
80+
Default is <literal>#</literal>. If you need to read
81+
the digit <literal>#</literal> literally, you should
82+
remove or change the terminator character. Multiple
83+
terminator characters may be specified. If no terminator
84+
digit is present, input cannot be ended using digits
85+
and you will need to rely on duration and max digits
86+
for ending input.</para>
87+
</option>
7888
</optionlist>
7989
</parameter>
8090
<parameter name="attempts">
@@ -114,12 +124,20 @@ enum read_option_flags {
114124
OPT_SKIP = (1 << 0),
115125
OPT_INDICATION = (1 << 1),
116126
OPT_NOANSWER = (1 << 2),
127+
OPT_TERMINATOR = (1 << 3),
128+
};
129+
130+
enum {
131+
OPT_ARG_TERMINATOR,
132+
/* note: this entry _MUST_ be the last one in the enum */
133+
OPT_ARG_ARRAY_SIZE,
117134
};
118135

119136
AST_APP_OPTIONS(read_app_options, {
120137
AST_APP_OPTION('s', OPT_SKIP),
121138
AST_APP_OPTION('i', OPT_INDICATION),
122139
AST_APP_OPTION('n', OPT_NOANSWER),
140+
AST_APP_OPTION_ARG('t', OPT_TERMINATOR, OPT_ARG_TERMINATOR),
123141
});
124142

125143
static char *app = "Read";
@@ -132,9 +150,11 @@ static int read_exec(struct ast_channel *chan, const char *data)
132150
int tries = 1, to = 0, x = 0;
133151
double tosec;
134152
char *argcopy = NULL;
153+
char *opt_args[OPT_ARG_ARRAY_SIZE];
135154
struct ast_tone_zone_sound *ts = NULL;
136155
struct ast_flags flags = {0};
137156
const char *status = "ERROR";
157+
char *terminator = NULL; /* use default terminator # by default */
138158

139159
AST_DECLARE_APP_ARGS(arglist,
140160
AST_APP_ARG(variable);
@@ -156,7 +176,7 @@ static int read_exec(struct ast_channel *chan, const char *data)
156176
AST_STANDARD_APP_ARGS(arglist, argcopy);
157177

158178
if (!ast_strlen_zero(arglist.options)) {
159-
ast_app_parse_options(read_app_options, &flags, NULL, arglist.options);
179+
ast_app_parse_options(read_app_options, &flags, opt_args, arglist.options);
160180
}
161181

162182
if (!ast_strlen_zero(arglist.attempts)) {
@@ -192,6 +212,13 @@ static int read_exec(struct ast_channel *chan, const char *data)
192212
ts = ast_get_indication_tone(ast_channel_zone(chan), arglist.filename);
193213
}
194214
}
215+
if (ast_test_flag(&flags, OPT_TERMINATOR)) {
216+
if (!ast_strlen_zero(arglist.filename)) {
217+
terminator = opt_args[OPT_ARG_TERMINATOR];
218+
} else {
219+
terminator = ""; /* no digit inherently will terminate input */
220+
}
221+
}
195222
if (ast_channel_state(chan) != AST_STATE_UP) {
196223
if (ast_test_flag(&flags, OPT_SKIP)) {
197224
/* 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)
223250
break;
224251
}
225252
tmp[x++] = res;
226-
if (tmp[x-1] == '#') {
253+
if (strchr(terminator, tmp[x-1])) {
227254
tmp[x-1] = '\0';
228255
status = "OK";
229256
break;
@@ -233,7 +260,7 @@ static int read_exec(struct ast_channel *chan, const char *data)
233260
}
234261
}
235262
} else {
236-
res = ast_app_getdata(chan, arglist.filename, tmp, maxdigits, to);
263+
res = ast_app_getdata_terminator(chan, arglist.filename, tmp, maxdigits, to, terminator);
237264
if (res == AST_GETDATA_COMPLETE || res == AST_GETDATA_EMPTY_END_TERMINATED)
238265
status = "OK";
239266
else if (res == AST_GETDATA_TIMEOUT)

Diff for: doc/CHANGES-staging/app_read.txt

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Subject: app_read
2+
3+
A new option allows the digit '#' to be read literally,
4+
rather than used exclusively as the input terminator
5+
character.

Diff for: include/asterisk/app.h

+17
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,23 @@ int ast_ivr_menu_run(struct ast_channel *c, struct ast_ivr_menu *menu, void *cbd
137137
*/
138138
int ast_app_getdata(struct ast_channel *c, const char *prompt, char *s, int maxlen, int timeout);
139139

140+
/*! \brief Plays a stream and gets DTMF data from a channel
141+
* \param c Which channel one is interacting with
142+
* \param prompt File to pass to ast_streamfile (the one that you wish to play).
143+
* It is also valid for this to be multiple files concatenated by "&".
144+
* For example, "file1&file2&file3".
145+
* \param s The location where the DTMF data will be stored
146+
* \param maxlen Max Length of the data
147+
* \param timeout Timeout length waiting for data(in milliseconds). Set to 0 for standard timeout(six seconds), or -1 for no time out.
148+
* \param terminator A string of characters that may be used as terminators to end input. If NULL, "#" will be used.
149+
*
150+
* This function was designed for application programmers for situations where they need
151+
* to play a message and then get some DTMF data in response to the message. If a digit
152+
* is pressed during playback, it will immediately break out of the message and continue
153+
* execution of your code.
154+
*/
155+
int ast_app_getdata_terminator(struct ast_channel *c, const char *prompt, char *s, int maxlen, int timeout, char *terminator);
156+
140157
/*! \brief Full version with audiofd and controlfd. NOTE: returns '2' on ctrlfd available, not '1' like other full functions */
141158
int ast_app_getdata_full(struct ast_channel *c, const char *prompt, char *s, int maxlen, int timeout, int audiofd, int ctrlfd);
142159

Diff for: main/app.c

+19-2
Original file line numberDiff line numberDiff line change
@@ -193,8 +193,25 @@ int ast_app_dtget(struct ast_channel *chan, const char *context, char *collect,
193193
* \param s The string to read in to. Must be at least the size of your length
194194
* \param maxlen How many digits to read (maximum)
195195
* \param timeout set timeout to 0 for "standard" timeouts. Set timeout to -1 for
196-
* "ludicrous time" (essentially never times out) */
196+
* "ludicrous time" (essentially never times out)
197+
*/
197198
enum ast_getdata_result ast_app_getdata(struct ast_channel *c, const char *prompt, char *s, int maxlen, int timeout)
199+
{
200+
return ast_app_getdata_terminator(c, prompt, s, maxlen, timeout, NULL);
201+
}
202+
203+
/*!
204+
* \brief ast_app_getdata
205+
* \param c The channel to read from
206+
* \param prompt The file to stream to the channel
207+
* \param s The string to read in to. Must be at least the size of your length
208+
* \param maxlen How many digits to read (maximum)
209+
* \param timeout set timeout to 0 for "standard" timeouts. Set timeout to -1 for
210+
* "ludicrous time" (essentially never times out)
211+
* \param terminator A string of characters that may be used as terminators to end input. Default if NULL is "#"
212+
*/
213+
enum ast_getdata_result ast_app_getdata_terminator(struct ast_channel *c, const char *prompt, char *s,
214+
int maxlen, int timeout, char *terminator)
198215
{
199216
int res = 0, to, fto;
200217
char *front, *filename;
@@ -232,7 +249,7 @@ enum ast_getdata_result ast_app_getdata(struct ast_channel *c, const char *promp
232249
fto = 50;
233250
to = ast_channel_pbx(c) ? ast_channel_pbx(c)->dtimeoutms : 2000;
234251
}
235-
res = ast_readstring(c, s, maxlen, to, fto, "#");
252+
res = ast_readstring(c, s, maxlen, to, fto, S_OR(terminator, "#"));
236253
if (res == AST_GETDATA_EMPTY_END_TERMINATED) {
237254
return res;
238255
}

0 commit comments

Comments
 (0)