[Asterisk-code-review] func_sayfiles: Retrieve say file names (asterisk[master])

N A asteriskteam at digium.com
Mon Jul 26 12:51:12 CDT 2021


N A has uploaded this change for review. ( https://gerrit.asterisk.org/c/asterisk/+/16226 )


Change subject: func_sayfiles: Retrieve say file names
......................................................................

func_sayfiles: Retrieve say file names

Up until now, all of the logic used to translate
arguments to the Say applications has been
directly coupled to playback, preventing other
modules from using this logic.

This refactors code in say.c and adds a SAYFILES
function that can be used to retrieve the file
names that would be played. These can then be
used in other applications or for other purposes.

ASTERISK-29531

Change-Id: If9718c89353b8e153d84add3cc4637b79585db19
---
A doc/CHANGES-staging/say.txt
A funcs/func_sayfiles.c
M include/asterisk/say.h
M main/say.c
4 files changed, 239 insertions(+), 33 deletions(-)



  git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/26/16226/1

diff --git a/doc/CHANGES-staging/say.txt b/doc/CHANGES-staging/say.txt
new file mode 100644
index 0000000..7b8e64d
--- /dev/null
+++ b/doc/CHANGES-staging/say.txt
@@ -0,0 +1,5 @@
+Subject: say.c
+
+Refactors some code in say.c so that other Asterisk
+modules can use the filename logic independently
+of playback.
diff --git a/funcs/func_sayfiles.c b/funcs/func_sayfiles.c
new file mode 100644
index 0000000..934265f
--- /dev/null
+++ b/funcs/func_sayfiles.c
@@ -0,0 +1,139 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2021, Naveen Albert <asterisk at phreaknet.org>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief Returns files played by Say applications
+ *
+ * \author Naveen Albert <asterisk at phreaknet.org>
+ * \ingroup functions
+ */
+
+/*** MODULEINFO
+	<support_level>extended</support_level>
+ ***/
+
+#include "asterisk.h"
+
+#include "asterisk/pbx.h"
+#include "asterisk/file.h"
+#include "asterisk/channel.h"
+#include "asterisk/say.h"
+#include "asterisk/lock.h"
+#include "asterisk/localtime.h"
+#include "asterisk/utils.h"
+#include "asterisk/app.h"
+#include "asterisk/test.h"
+#include "asterisk/module.h"
+
+/*** DOCUMENTATION
+	<function name="SAYFILES" language="en_US">
+		<synopsis>
+			Returns the file names that would be played by the Say applications (e.g. SayAlpha, SayDigits).
+		</synopsis>
+		<syntax>
+			<parameter name="value" required="true">
+				<para>The value to be translated to filenames.</para>
+			</parameter>
+			<parameter name="value">
+				<para>Say application type.</para>
+				<enumlist>
+					<enum name="alpha">
+						<para>Files played by SayAlpha(). Default if none is specified.</para>
+					</enum>
+					<enum name="phonetic">
+						<para>Files played by SayPhonetic().</para>
+					</enum>
+					<enum name="digits">
+						<para>Files played by SayDigits().</para>
+					</enum>
+				</enumlist>
+			</parameter>
+		</syntax>
+		<description>
+			<para>Returns the files that would be played by a Say application. These filenames could then be
+			passed directly into Playback, BackGround, Read, Queue, or any application which supports
+			playback of multiple ampersand-delimited files.</para>
+		</description>
+		<see-also>
+			<ref type="application">SayAlpha</ref>
+			<ref type="application">SayPhonetic</ref>
+			<ref type="application">SayDigits</ref>
+		</see-also>
+	</function>
+ ***/
+static int sayfile_exec(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
+{
+	char *value, *type, *files;
+	struct ast_str *filenames = NULL;
+	AST_DECLARE_APP_ARGS(args,
+		AST_APP_ARG(value);
+		AST_APP_ARG(type);
+	);
+
+	if (ast_strlen_zero(data)) {
+		ast_log(LOG_WARNING, "SAYFILES requires an argument\n");
+		return 0;
+	}
+
+	AST_STANDARD_APP_ARGS(args, data);
+	
+	value = args.value;
+	if (ast_strlen_zero(args.type))
+		type = "alpha";
+	else
+		type = args.type;
+
+	
+	if (!strcmp(type, "alpha")) {
+		filenames = ast_get_character_str_full(value, ast_channel_language(chan), AST_SAY_CASE_NONE);
+	} else if (!strcmp(type, "phonetic")) {
+		filenames = ast_get_phonetic_str_full(value, ast_channel_language(chan));
+	} else if (!strcmp(type, "digits")) {
+		filenames = ast_get_digit_str_full(value, ast_channel_language(chan));
+	} else {
+		ast_log(LOG_WARNING, "Invalid say type specified: %s\n", type);
+	}
+
+	if (!filenames) {
+		return -1;
+	}
+
+	files = ast_str_buffer(filenames);
+	snprintf(buf, len, "%s", files);
+	ast_free(filenames);
+
+	return 0;
+}
+
+static struct ast_custom_function sayfiles = {
+	.name = "SAYFILES",
+	.read = sayfile_exec,
+};
+
+static int unload_module(void)
+{
+	ast_custom_function_unregister(&sayfiles);
+
+	return 0;
+}
+
+static int load_module(void)
+{
+	return ast_custom_function_register(&sayfiles);
+}
+
+AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Say application files");
diff --git a/include/asterisk/say.h b/include/asterisk/say.h
index a4aa90c..4359eff 100644
--- a/include/asterisk/say.h
+++ b/include/asterisk/say.h
@@ -188,4 +188,8 @@
 }
 #endif
 
+struct ast_str* ast_get_character_str_full(const char *str, const char *lang, enum ast_say_case_sensitivity sensitivity);
+struct ast_str* ast_get_phonetic_str_full(const char *str, const char *lang);
+struct ast_str* ast_get_digit_str_full(const char *str, const char *lang);
+
 #endif /* _ASTERISK_SAY_H */
diff --git a/main/say.c b/main/say.c
index 0a37091..1715aab 100644
--- a/main/say.c
+++ b/main/say.c
@@ -29,6 +29,8 @@
  *						Next Generation Networks (NGN).
  * \note 2007-03-20 : Support for Thai added by Dome C. <dome at tel.co.th>,
  *						IP Crossing Co., Ltd.
+ * \note 2021-07-26 : Refactoring to separate string buildup and playback
+ *						by Naveen Albert <asterisk at phreaknet.org>
  */
 
 /*** MODULEINFO
@@ -58,9 +60,7 @@
 /* Forward declaration */
 static int wait_file(struct ast_channel *chan, const char *ints, const char *file, const char *lang);
 
-
-static int say_character_str_full(struct ast_channel *chan, const char *str, const char *ints, const char *lang, enum ast_say_case_sensitivity sensitivity, int audiofd, int ctrlfd)
-{
+struct ast_str* ast_get_character_str_full(const char *str, const char *lang, enum ast_say_case_sensitivity sensitivity) {
 	const char *fn;
 	char fnbuf[10], asciibuf[20] = "letters/ascii";
 	char ltr;
@@ -68,6 +68,9 @@
 	int res = 0;
 	int upper = 0;
 	int lower = 0;
+	
+	struct ast_str *filenames = ast_str_create(20);
+	ast_str_reset(filenames);
 
 	while (str[num] && !res) {
 		fn = NULL;
@@ -154,14 +157,7 @@
 		}
 		if ((fn && ast_fileexists(fn, NULL, lang) > 0) ||
 			(snprintf(asciibuf + 13, sizeof(asciibuf) - 13, "%d", str[num]) > 0 && ast_fileexists(asciibuf, NULL, lang) > 0 && (fn = asciibuf))) {
-			res = ast_streamfile(chan, fn, lang);
-			if (!res) {
-				if ((audiofd  > -1) && (ctrlfd > -1))
-					res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
-				else
-					res = ast_waitstream(chan, ints);
-			}
-			ast_stopstream(chan);
+			ast_str_append(&filenames, 0, (num == 0 ? "%s" : "&%s"), fn);
 		}
 		if (upper || lower) {
 			continue;
@@ -169,18 +165,44 @@
 		num++;
 	}
 
+	return filenames;
+}
+
+static int say_character_str_full(struct ast_channel *chan, const char *str, const char *ints, const char *lang, enum ast_say_case_sensitivity sensitivity, int audiofd, int ctrlfd)
+{
+	const char *fn;
+	int res = 0;
+
+	struct ast_str *filenames = ast_get_character_str_full(str, lang, sensitivity);
+	char *files = ast_str_buffer(filenames);
+
+	while ((fn = strsep(&files, "&"))) {
+		res = ast_streamfile(chan, fn, lang);
+		if (!res) {
+			if ((audiofd  > -1) && (ctrlfd > -1))
+				res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
+			else
+				res = ast_waitstream(chan, ints);
+		}
+		ast_stopstream(chan);
+	}
+	
+	ast_free(filenames);
+
 	return res;
 }
 
-static int say_phonetic_str_full(struct ast_channel *chan, const char *str, const char *ints, const char *lang, int audiofd, int ctrlfd)
+struct ast_str* ast_get_phonetic_str_full(const char *str, const char *lang)
 {
 	const char *fn;
 	char fnbuf[256];
 	char ltr;
 	int num = 0;
-	int res = 0;
+	
+	struct ast_str *filenames = ast_str_create(20);
+	ast_str_reset(filenames);
 
-	while (str[num] && !res) {
+	while (str[num]) {
 		fn = NULL;
 		switch (str[num]) {
 		case ('*'):
@@ -237,29 +259,48 @@
 			fn = fnbuf;
 		}
 		if (fn && ast_fileexists(fn, NULL, lang) > 0) {
-			res = ast_streamfile(chan, fn, lang);
-			if (!res) {
-				if ((audiofd  > -1) && (ctrlfd > -1))
-					res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
-				else
-					res = ast_waitstream(chan, ints);
-			}
-			ast_stopstream(chan);
+			ast_str_append(&filenames, 0, (num == 0 ? "%s" : "&%s"), fn);
 		}
 		num++;
 	}
 
+	return filenames;
+}
+
+static int say_phonetic_str_full(struct ast_channel *chan, const char *str, const char *ints, const char *lang, int audiofd, int ctrlfd)
+{
+	const char *fn;
+	int res = 0;
+
+	struct ast_str *filenames = ast_get_phonetic_str_full(str, lang);
+	char *files = ast_str_buffer(filenames);
+
+	while ((fn = strsep(&files, "&"))) {
+		res = ast_streamfile(chan, fn, lang);
+		if (!res) {
+			if ((audiofd  > -1) && (ctrlfd > -1))
+				res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
+			else
+				res = ast_waitstream(chan, ints);
+		}
+		ast_stopstream(chan);
+	}
+
+	ast_free(filenames);
+
 	return res;
 }
 
-static int say_digit_str_full(struct ast_channel *chan, const char *str, const char *ints, const char *lang, int audiofd, int ctrlfd)
+struct ast_str* ast_get_digit_str_full(const char *str, const char *lang)
 {
 	const char *fn;
 	char fnbuf[256];
 	int num = 0;
-	int res = 0;
+	
+	struct ast_str *filenames = ast_str_create(20);
+	ast_str_reset(filenames);
 
-	while (str[num] && !res) {
+	while (str[num]) {
 		fn = NULL;
 		switch (str[num]) {
 		case ('*'):
@@ -287,18 +328,35 @@
 			break;
 		}
 		if (fn && ast_fileexists(fn, NULL, lang) > 0) {
-			res = ast_streamfile(chan, fn, lang);
-			if (!res) {
-				if ((audiofd  > -1) && (ctrlfd > -1))
-					res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
-				else
-					res = ast_waitstream(chan, ints);
-			}
-			ast_stopstream(chan);
+			ast_str_append(&filenames, 0, (num == 0 ? "%s" : "&%s"), fn);
 		}
 		num++;
 	}
 
+	return filenames;
+}
+
+static int say_digit_str_full(struct ast_channel *chan, const char *str, const char *ints, const char *lang, int audiofd, int ctrlfd)
+{
+	const char *fn;
+	int res = 0;
+
+	struct ast_str *filenames = ast_get_digit_str_full(str, lang);
+	char *files = ast_str_buffer(filenames);
+
+	while ((fn = strsep(&files, "&"))) {
+		res = ast_streamfile(chan, fn, lang);
+		if (!res) {
+			if ((audiofd  > -1) && (ctrlfd > -1))
+				res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
+			else
+				res = ast_waitstream(chan, ints);
+		}
+		ast_stopstream(chan);
+	}
+
+	ast_free(filenames);
+
 	return res;
 }
 

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

Gerrit-Project: asterisk
Gerrit-Branch: master
Gerrit-Change-Id: If9718c89353b8e153d84add3cc4637b79585db19
Gerrit-Change-Number: 16226
Gerrit-PatchSet: 1
Gerrit-Owner: N A <mail at interlinked.x10host.com>
Gerrit-MessageType: newchange
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-code-review/attachments/20210726/0e5adac2/attachment-0001.html>


More information about the asterisk-code-review mailing list