[Asterisk-code-review] app_read: Allow reading # as a digit (asterisk[master])

George Joseph asteriskteam at digium.com
Wed Sep 1 10:31:18 CDT 2021


George Joseph has submitted this change. ( https://gerrit.asterisk.org/c/asterisk/+/16352 )

Change subject: app_read: Allow reading # as a digit
......................................................................

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
---
M apps/app_read.c
A doc/CHANGES-staging/app_read.txt
M include/asterisk/app.h
M main/app.c
4 files changed, 71 insertions(+), 5 deletions(-)

Approvals:
  Kevin Harwell: Looks good to me, but someone else must approve
  George Joseph: Looks good to me, approved
  Friendly Automation: Approved for Submit



diff --git a/apps/app_read.c b/apps/app_read.c
index 6398281..dd48f05 100644
--- a/apps/app_read.c
+++ b/apps/app_read.c
@@ -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 @@
 	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 @@
 	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 @@
 	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 @@
 			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 @@
 						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 @@
 					}
 				}
 			} 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)
diff --git a/doc/CHANGES-staging/app_read.txt b/doc/CHANGES-staging/app_read.txt
new file mode 100644
index 0000000..df3247c
--- /dev/null
+++ b/doc/CHANGES-staging/app_read.txt
@@ -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.
diff --git a/include/asterisk/app.h b/include/asterisk/app.h
index 7690364..ab246c8 100644
--- a/include/asterisk/app.h
+++ b/include/asterisk/app.h
@@ -137,6 +137,23 @@
  */
 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);
 
diff --git a/main/app.c b/main/app.c
index 09c0123..f5fbffd 100644
--- a/main/app.c
+++ b/main/app.c
@@ -193,9 +193,26 @@
  * \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 @@
 			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;
 		}

-- 
To view, visit https://gerrit.asterisk.org/c/asterisk/+/16352
To unsubscribe, or for help writing mail filters, visit https://gerrit.asterisk.org/settings

Gerrit-Project: asterisk
Gerrit-Branch: master
Gerrit-Change-Id: I3033432adb9d296ad227e76b540b8b4a2417665b
Gerrit-Change-Number: 16352
Gerrit-PatchSet: 4
Gerrit-Owner: N A <mail at interlinked.x10host.com>
Gerrit-Reviewer: Friendly Automation
Gerrit-Reviewer: George Joseph <gjoseph at digium.com>
Gerrit-Reviewer: Kevin Harwell <kharwell at digium.com>
Gerrit-Reviewer: Sean Bright <sean at seanbright.com>
Gerrit-MessageType: merged
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-code-review/attachments/20210901/5f3a2b5e/attachment.html>


More information about the asterisk-code-review mailing list