summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES4
-rw-r--r--apps/app_chanspy.c2
-rw-r--r--apps/app_directory.c6
-rw-r--r--apps/app_voicemail.c2
-rw-r--r--include/asterisk/say.h14
-rw-r--r--main/channel.c4
-rw-r--r--main/pbx.c94
-rw-r--r--main/say.c39
-rw-r--r--res/res_agi.c30
9 files changed, 178 insertions, 17 deletions
diff --git a/CHANGES b/CHANGES
index 19946ab9d..140b72581 100644
--- a/CHANGES
+++ b/CHANGES
@@ -339,6 +339,10 @@ AGI (Asterisk Gateway Interface)
will start the playback of the audio at the position specified. It will
also return the final position of the file in 'endpos'.
+ * The SAY ALPHA command now accepts an additional parameter to control
+ whether it specifies the case of uppercase, lowercase, or all letters to
+ provide functionality similar to SayAlphaCase.
+
CDR (Call Detail Records)
------------------
* Significant changes have been made to the behavior of CDRs. For a full
diff --git a/apps/app_chanspy.c b/apps/app_chanspy.c
index 0f40e3193..061fa261d 100644
--- a/apps/app_chanspy.c
+++ b/apps/app_chanspy.c
@@ -1048,7 +1048,7 @@ static int common_exec(struct ast_channel *chan, struct ast_flags *flags,
break;
}
} else {
- res = ast_say_character_str(chan, peer_name, "", ast_channel_language(chan));
+ res = ast_say_character_str(chan, peer_name, "", ast_channel_language(chan), AST_SAY_CASE_NONE);
}
}
if (ptr && (num = atoi(ptr))) {
diff --git a/apps/app_directory.c b/apps/app_directory.c
index edfc349ea..ccdac427b 100644
--- a/apps/app_directory.c
+++ b/apps/app_directory.c
@@ -281,13 +281,13 @@ static int play_mailbox_owner(struct ast_channel *chan, const char *context,
/* If Option 'e' was specified, also read the extension number with the name */
if (ast_test_flag(flags, OPT_SAYEXTENSION)) {
ast_stream_and_wait(chan, "vm-extension", AST_DIGIT_ANY);
- res = ast_say_character_str(chan, ext, AST_DIGIT_ANY, ast_channel_language(chan));
+ res = ast_say_character_str(chan, ext, AST_DIGIT_ANY, ast_channel_language(chan), AST_SAY_CASE_NONE);
}
} else {
- res = ast_say_character_str(chan, S_OR(name, ext), AST_DIGIT_ANY, ast_channel_language(chan));
+ res = ast_say_character_str(chan, S_OR(name, ext), AST_DIGIT_ANY, ast_channel_language(chan), AST_SAY_CASE_NONE);
if (!ast_strlen_zero(name) && ast_test_flag(flags, OPT_SAYEXTENSION)) {
ast_stream_and_wait(chan, "vm-extension", AST_DIGIT_ANY);
- res = ast_say_character_str(chan, ext, AST_DIGIT_ANY, ast_channel_language(chan));
+ res = ast_say_character_str(chan, ext, AST_DIGIT_ANY, ast_channel_language(chan), AST_SAY_CASE_NONE);
}
}
diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c
index 1f048a283..13e94a8ba 100644
--- a/apps/app_voicemail.c
+++ b/apps/app_voicemail.c
@@ -13683,7 +13683,7 @@ static int vmsayname_exec(struct ast_channel *chan, const char *data)
ast_debug(3, "Greeting not found for '%s@%s', falling back to mailbox number.\n", args_copy, context);
res = ast_stream_and_wait(chan, "vm-extension", AST_DIGIT_ANY);
if (!res) {
- res = ast_say_character_str(chan, args_copy, AST_DIGIT_ANY, ast_channel_language(chan));
+ res = ast_say_character_str(chan, args_copy, AST_DIGIT_ANY, ast_channel_language(chan), AST_SAY_CASE_NONE);
}
}
diff --git a/include/asterisk/say.h b/include/asterisk/say.h
index fac606aa8..93c525dd2 100644
--- a/include/asterisk/say.h
+++ b/include/asterisk/say.h
@@ -148,13 +148,23 @@ SAY_EXTERN int (* ast_say_digit_str_full)(struct ast_channel *chan, const char *
*/
SAY_EXTERN int (* ast_say_full)(struct ast_channel *chan, const char *num, const char *ints, const char *lang, const char *options, int audiofd, int ctrlfd) SAY_INIT(ast_say_full);
+/*!
+ * \brief Controls how ast_say_character_str denotes the case of characters in a string
+ */
+enum ast_say_case_sensitivity {
+ AST_SAY_CASE_NONE, /*!< Do not distinguish case on any letters */
+ AST_SAY_CASE_LOWER, /*!< Denote case only on lower case letters, upper case is assumed otherwise */
+ AST_SAY_CASE_UPPER, /*!< Denote case only on upper case letters, lower case is assumed otherwise */
+ AST_SAY_CASE_ALL, /*!< Denote case on all letters, upper and lower */
+};
+
/*! \brief
* function to pronounce character and phonetic strings
*/
int ast_say_character_str(struct ast_channel *chan, const char *num,
- const char *ints, const char *lang);
+ const char *ints, const char *lang, enum ast_say_case_sensitivity sensitivity);
-SAY_EXTERN int (* ast_say_character_str_full)(struct ast_channel *chan, const char *num, const char *ints, const char *lang, int audiofd, int ctrlfd) SAY_INIT(ast_say_character_str_full);
+SAY_EXTERN int (* ast_say_character_str_full)(struct ast_channel *chan, const char *num, const char *ints, const char *lang, enum ast_say_case_sensitivity sensitivity, int audiofd, int ctrlfd) SAY_INIT(ast_say_character_str_full);
int ast_say_phonetic_str(struct ast_channel *chan, const char *num,
const char *ints, const char *lang);
diff --git a/main/channel.c b/main/channel.c
index c5ff77b86..5daf5825e 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -7792,9 +7792,9 @@ int ast_say_digit_str(struct ast_channel *chan, const char *str,
}
int ast_say_character_str(struct ast_channel *chan, const char *str,
- const char *ints, const char *lang)
+ const char *ints, const char *lang, enum ast_say_case_sensitivity sensitivity)
{
- return ast_say_character_str_full(chan, str, ints, lang, -1, -1);
+ return ast_say_character_str_full(chan, str, ints, lang, sensitivity, -1, -1);
}
int ast_say_phonetic_str(struct ast_channel *chan, const char *str,
diff --git a/main/pbx.c b/main/pbx.c
index d5a46a5fd..27a586ef9 100644
--- a/main/pbx.c
+++ b/main/pbx.c
@@ -501,6 +501,46 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
<ref type="function">CHANNEL</ref>
</see-also>
</application>
+ <application name="SayAlphaCase" language="en_US">
+ <synopsis>
+ Say Alpha.
+ </synopsis>
+ <syntax>
+ <parameter name="casetype" required="true" >
+ <enumlist>
+ <enum name="a">
+ <para>Case sensitive (all) pronunciation.
+ (Ex: SayAlphaCase(a,aBc); - lowercase a uppercase b lowercase c).</para>
+ </enum>
+ <enum name="l">
+ <para>Case sensitive (lower) pronunciation.
+ (Ex: SayAlphaCase(l,aBc); - lowercase a b lowercase c).</para>
+ </enum>
+ <enum name="n">
+ <para>Case insensitive pronunciation. Equivalent to SayAlpha.
+ (Ex: SayAlphaCase(n,aBc) - a b c).</para>
+ </enum>
+ <enum name="u">
+ <para>Case sensitive (upper) pronunciation.
+ (Ex: SayAlphaCase(u,aBc); - a uppercase b c).</para>
+ </enum>
+ </enumlist>
+ </parameter>
+ <parameter name="string" required="true" />
+ </syntax>
+ <description>
+ <para>This application will play the sounds that correspond to the letters of the
+ given <replaceable>string</replaceable>. Optionally, a <replaceable>casetype</replaceable> may be
+ specified. This will be used for case-insensitive or case-sensitive pronunciations.</para>
+ </description>
+ <see-also>
+ <ref type="application">SayDigits</ref>
+ <ref type="application">SayNumber</ref>
+ <ref type="application">SayPhonetic</ref>
+ <ref type="application">SayAlpha</ref>
+ <ref type="function">CHANNEL</ref>
+ </see-also>
+ </application>
<application name="SayDigits" language="en_US">
<synopsis>
Say Digits.
@@ -1122,6 +1162,7 @@ static int pbx_builtin_execiftime(struct ast_channel *, const char *);
static int pbx_builtin_saynumber(struct ast_channel *, const char *);
static int pbx_builtin_saydigits(struct ast_channel *, const char *);
static int pbx_builtin_saycharacters(struct ast_channel *, const char *);
+static int pbx_builtin_saycharacters_case(struct ast_channel *, const char *);
static int pbx_builtin_sayphonetic(struct ast_channel *, const char *);
static int matchcid(const char *cidpattern, const char *callerid);
#ifdef NEED_DEBUG
@@ -1297,6 +1338,7 @@ static struct pbx_builtin {
{ "RaiseException", pbx_builtin_raise_exception },
{ "Ringing", pbx_builtin_ringing },
{ "SayAlpha", pbx_builtin_saycharacters },
+ { "SayAlphaCase", pbx_builtin_saycharacters_case },
{ "SayDigits", pbx_builtin_saydigits },
{ "SayNumber", pbx_builtin_saynumber },
{ "SayPhonetic", pbx_builtin_sayphonetic },
@@ -11260,12 +11302,60 @@ static int pbx_builtin_saydigits(struct ast_channel *chan, const char *data)
return res;
}
+static int pbx_builtin_saycharacters_case(struct ast_channel *chan, const char *data)
+{
+ int res = 0;
+ int sensitivity = 0;
+ char *parse;
+ AST_DECLARE_APP_ARGS(args,
+ AST_APP_ARG(options);
+ AST_APP_ARG(characters);
+ );
+
+ if (ast_strlen_zero(data)) {
+ ast_log(LOG_WARNING, "SayAlphaCase requires two arguments (options, characters)\n");
+ return 0;
+ }
+
+ parse = ast_strdupa(data);
+ AST_STANDARD_APP_ARGS(args, parse);
+
+ if (!args.options || strlen(args.options) != 1) {
+ ast_log(LOG_WARNING, "SayAlphaCase options are mutually exclusive and required\n");
+ return 0;
+ }
+
+ switch (args.options[0]) {
+ case 'a':
+ sensitivity = AST_SAY_CASE_ALL;
+ break;
+ case 'l':
+ sensitivity = AST_SAY_CASE_LOWER;
+ break;
+ case 'n':
+ sensitivity = AST_SAY_CASE_NONE;
+ break;
+ case 'u':
+ sensitivity = AST_SAY_CASE_UPPER;
+ break;
+ default:
+ ast_log(LOG_WARNING, "Invalid option: '%s'\n", args.options);
+ return 0;
+ }
+
+ res = ast_say_character_str(chan, args.characters, "", ast_channel_language(chan), sensitivity);
+
+ return res;
+}
+
static int pbx_builtin_saycharacters(struct ast_channel *chan, const char *data)
{
int res = 0;
- if (data)
- res = ast_say_character_str(chan, data, "", ast_channel_language(chan));
+ if (data) {
+ res = ast_say_character_str(chan, data, "", ast_channel_language(chan), AST_SAY_CASE_NONE);
+ }
+
return res;
}
diff --git a/main/say.c b/main/say.c
index 295d4110f..ed0a7b524 100644
--- a/main/say.c
+++ b/main/say.c
@@ -61,13 +61,15 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
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, int audiofd, int ctrlfd)
+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;
char fnbuf[10], asciibuf[20] = "letters/ascii";
char ltr;
int num = 0;
int res = 0;
+ int upper = 0;
+ int lower = 0;
while (str[num] && !res) {
fn = NULL;
@@ -121,9 +123,35 @@ static int say_character_str_full(struct ast_channel *chan, const char *str, con
break;
default:
ltr = str[num];
- if ('A' <= ltr && ltr <= 'Z') ltr += 'a' - 'A'; /* file names are all lower-case */
- strcpy(fnbuf, "letters/X");
- fnbuf[8] = ltr;
+ if ('A' <= ltr && ltr <= 'Z') {
+ ltr += 'a' - 'A'; /* file names are all lower-case */
+ switch (sensitivity) {
+ case AST_SAY_CASE_UPPER:
+ case AST_SAY_CASE_ALL:
+ upper = !upper;
+ case AST_SAY_CASE_LOWER:
+ case AST_SAY_CASE_NONE:
+ break;
+ }
+ } else if ('a' <= ltr && ltr <= 'z') {
+ switch (sensitivity) {
+ case AST_SAY_CASE_LOWER:
+ case AST_SAY_CASE_ALL:
+ lower = !lower;
+ case AST_SAY_CASE_UPPER:
+ case AST_SAY_CASE_NONE:
+ break;
+ }
+ }
+
+ if (upper) {
+ strcpy(fnbuf, "uppercase");
+ } else if (lower) {
+ strcpy(fnbuf, "lowercase");
+ } else {
+ strcpy(fnbuf, "letters/X");
+ fnbuf[8] = ltr;
+ }
fn = fnbuf;
}
if ((fn && ast_fileexists(fn, NULL, lang) > 0) ||
@@ -137,6 +165,9 @@ static int say_character_str_full(struct ast_channel *chan, const char *str, con
}
ast_stopstream(chan);
}
+ if (upper || lower) {
+ continue;
+ }
num++;
}
diff --git a/res/res_agi.c b/res/res_agi.c
index 6619183fc..74d665bd5 100644
--- a/res/res_agi.c
+++ b/res/res_agi.c
@@ -2313,11 +2313,37 @@ static int handle_saydigits(struct ast_channel *chan, AGI *agi, int argc, const
static int handle_sayalpha(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
{
int res;
+ int sensitivity = AST_SAY_CASE_NONE;
- if (argc != 4)
+ if (argc < 4 || argc > 5) {
return RESULT_SHOWUSAGE;
+ }
- res = ast_say_character_str_full(chan, argv[2], argv[3], ast_channel_language(chan), agi->audio, agi->ctrl);
+ if (argc > 4) {
+ switch (argv[4][0]) {
+ case 'a':
+ case 'A':
+ sensitivity = AST_SAY_CASE_ALL;
+ break;
+ case 'l':
+ case 'L':
+ sensitivity = AST_SAY_CASE_LOWER;
+ break;
+ case 'n':
+ case 'N':
+ sensitivity = AST_SAY_CASE_NONE;
+ break;
+ case 'u':
+ case 'U':
+ sensitivity = AST_SAY_CASE_UPPER;
+ break;
+ case '\0':
+ break;
+ default:
+ return RESULT_SHOWUSAGE;
+ }
+ }
+ res = ast_say_character_str_full(chan, argv[2], argv[3], ast_channel_language(chan), sensitivity, agi->audio, agi->ctrl);
if (res == 1) /* New command */
return RESULT_SUCCESS;
ast_agi_send(agi->fd, chan, "200 result=%d\n", res);