summaryrefslogtreecommitdiff
path: root/main/say.c
diff options
context:
space:
mode:
authorMatthew Jordan <mjordan@digium.com>2014-06-30 04:00:19 +0000
committerMatthew Jordan <mjordan@digium.com>2014-06-30 04:00:19 +0000
commitaf90afd90c64c5183c2207d061f9aa15138081b2 (patch)
treec0410d6aa8b719dd5df0b1bcaddd4cdfaa187b9e /main/say.c
parent44dba37bd1d3f7035b59e677ac54dc679ecba87a (diff)
app_voicemail, say: Add support for Japanese Language
This patch adds support for the Japanese language to both the say family of applications, as well as for VoiceMail and VoiceMailMain. A new pack of language sounds will be released at the same time as the next major version of Asterisk to support the new language features. The language features can be enabled using a language code of 'ja'. Review: https://reviewboard.asterisk.org/r/3477 ASTERISK-23324 #close Reported by: Kevin McCoy patches: app_voicemail.c.20140226.jb.patch uploaded by Kevin McCoy (License 6586) say.c.20140226.jb.patch uploaded by Kevin McCoy (License 6586) git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@417591 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'main/say.c')
-rw-r--r--main/say.c543
1 files changed, 518 insertions, 25 deletions
diff --git a/main/say.c b/main/say.c
index bda1da3c3..ef80dfa7d 100644
--- a/main/say.c
+++ b/main/say.c
@@ -381,6 +381,7 @@ static int ast_say_number_full_pt(struct ast_channel *chan, int num, const char
static int ast_say_number_full_se(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd);
static int ast_say_number_full_zh(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd);
static int ast_say_number_full_gr(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd);
+static int ast_say_number_full_ja(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd);
static int ast_say_number_full_ru(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd);
static int ast_say_number_full_ka(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd);
static int ast_say_number_full_hu(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd);
@@ -403,6 +404,7 @@ static int ast_say_date_fr(struct ast_channel *chan, time_t t, const char *ints,
static int ast_say_date_nl(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
static int ast_say_date_pt(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
static int ast_say_date_gr(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
+static int ast_say_date_ja(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
static int ast_say_date_ka(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
static int ast_say_date_hu(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
static int ast_say_date_th(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
@@ -420,6 +422,7 @@ static int ast_say_date_with_format_pl(struct ast_channel *chan, time_t t, const
static int ast_say_date_with_format_pt(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone);
static int ast_say_date_with_format_zh(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone);
static int ast_say_date_with_format_gr(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone);
+static int ast_say_date_with_format_ja(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone);
static int ast_say_date_with_format_th(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone);
static int ast_say_date_with_format_vi(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone);
@@ -431,6 +434,7 @@ static int ast_say_time_pt(struct ast_channel *chan, time_t t, const char *ints,
static int ast_say_time_pt_BR(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
static int ast_say_time_zh(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
static int ast_say_time_gr(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
+static int ast_say_time_ja(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
static int ast_say_time_ka(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
static int ast_say_time_hu(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
static int ast_say_time_th(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
@@ -444,6 +448,7 @@ static int ast_say_datetime_pt(struct ast_channel *chan, time_t t, const char *i
static int ast_say_datetime_pt_BR(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
static int ast_say_datetime_zh(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
static int ast_say_datetime_gr(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
+static int ast_say_datetime_ja(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
static int ast_say_datetime_ka(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
static int ast_say_datetime_hu(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
static int ast_say_datetime_th(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
@@ -500,6 +505,8 @@ static int say_number_full(struct ast_channel *chan, int num, const char *ints,
return ast_say_number_full_ka(chan, num, ints, language, options, audiofd, ctrlfd);
} else if (!strncasecmp(language, "gr", 2)) { /* Greek syntax */
return ast_say_number_full_gr(chan, num, ints, language, audiofd, ctrlfd);
+ } else if (!strncasecmp(language, "ja", 2)) { /* Japanese syntax */
+ return ast_say_number_full_ja(chan, num, ints, language, audiofd, ctrlfd);
} else if (!strncasecmp(language, "he", 2)) { /* Hebrew syntax */
return ast_say_number_full_he(chan, num, ints, language, options, audiofd, ctrlfd);
} else if (!strncasecmp(language, "hu", 2)) { /* Hungarian syntax */
@@ -1929,31 +1936,31 @@ static void powiedz(struct ast_channel *chan, const char *language, int audiofd,
m100 = m1000 % 100;
i100 = m1000 / 100;
- if (i100>0)
- pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, odm->setki[i100]);
-
- if (m100 > 0 && m100 <= 9) {
- if (m1000 > 0)
- pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, odm->cyfry2[m100]);
- else
- pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, odm->cyfry[m100]);
- } else if (m100 % 10 == 0 && m100 != 0) {
- pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, odm->dziesiatki[m100 / 10]);
- } else if (m100 > 10 && m100 <= 19) {
- pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, odm->nastki[m100 % 10]);
- } else if (m100 > 20) {
- if (odm->separator_dziesiatek[0] == ' ') {
- pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, odm->dziesiatki[m100 / 10]);
- pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, odm->cyfry2[m100 % 10]);
- } else {
- char buf[10];
- char *b = buf;
- b = pl_append(b, odm->dziesiatki[m100 / 10]);
- b = pl_append(b, odm->separator_dziesiatek);
- pl_append(b, odm->cyfry2[m100 % 10]);
- pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, buf);
- }
- }
+ if (i100>0)
+ pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, odm->setki[i100]);
+
+ if (m100 > 0 && m100 <= 9) {
+ if (m1000 > 0)
+ pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, odm->cyfry2[m100]);
+ else
+ pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, odm->cyfry[m100]);
+ } else if (m100 % 10 == 0 && m100 != 0) {
+ pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, odm->dziesiatki[m100 / 10]);
+ } else if (m100 > 10 && m100 <= 19) {
+ pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, odm->nastki[m100 % 10]);
+ } else if (m100 > 20) {
+ if (odm->separator_dziesiatek[0] == ' ') {
+ pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, odm->dziesiatki[m100 / 10]);
+ pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, odm->cyfry2[m100 % 10]);
+ } else {
+ char buf[10];
+ char *b = buf;
+ b = pl_append(b, odm->dziesiatki[m100 / 10]);
+ b = pl_append(b, odm->separator_dziesiatek);
+ pl_append(b, odm->cyfry2[m100 % 10]);
+ pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, buf);
+ }
+ }
if (rzad > 0) {
pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, pl_rzad_na_tekst(odm, i, rzad));
@@ -3340,6 +3347,8 @@ static int say_date(struct ast_channel *chan, time_t t, const char *ints, const
return ast_say_date_ka(chan, t, ints, lang);
} else if (!strncasecmp(lang, "gr", 2)) { /* Greek syntax */
return ast_say_date_gr(chan, t, ints, lang);
+ } else if (!strncasecmp(lang, "ja", 2)) { /* Japanese syntax */
+ return ast_say_date_ja(chan, t, ints, lang);
} else if (!strncasecmp(lang, "he", 2)) { /* Hebrew syntax */
return ast_say_date_he(chan, t, ints, lang);
} else if (!strncasecmp(lang, "hu", 2)) { /* Hungarian syntax */
@@ -3689,6 +3698,8 @@ static int say_date_with_format(struct ast_channel *chan, time_t t, const char *
return ast_say_date_with_format_fr(chan, t, ints, lang, format, tzone);
} else if (!strncasecmp(lang, "gr", 2)) { /* Greek syntax */
return ast_say_date_with_format_gr(chan, t, ints, lang, format, tzone);
+ } else if (!strncasecmp(lang, "ja", 2)) { /* Japanese syntax */
+ return ast_say_date_with_format_ja(chan, t, ints, lang, format, tzone);
} else if (!strncasecmp(lang, "it", 2)) { /* Italian syntax */
return ast_say_date_with_format_it(chan, t, ints, lang, format, tzone);
} else if (!strncasecmp(lang, "mx", 2)) { /* deprecated Mexican syntax */
@@ -6321,6 +6332,8 @@ static int say_time(struct ast_channel *chan, time_t t, const char *ints, const
return ast_say_time_ka(chan, t, ints, lang);
} else if (!strncasecmp(lang, "gr", 2)) { /* Greek syntax */
return ast_say_time_gr(chan, t, ints, lang);
+ } else if (!strncasecmp(lang, "ja", 2)) { /* Japanese syntax */
+ return ast_say_time_ja(chan, t, ints, lang);
} else if (!strncasecmp(lang, "he", 2)) { /* Hebrew syntax */
return ast_say_time_he(chan, t, ints, lang);
} else if (!strncasecmp(lang, "hu", 2)) { /* Hungarian syntax */
@@ -6652,6 +6665,8 @@ static int say_datetime(struct ast_channel *chan, time_t t, const char *ints, co
return ast_say_datetime_ka(chan, t, ints, lang);
} else if (!strncasecmp(lang, "gr", 2)) { /* Greek syntax */
return ast_say_datetime_gr(chan, t, ints, lang);
+ } else if (!strncasecmp(lang, "ja", 2)) { /* Japanese syntax */
+ return ast_say_datetime_ja(chan, t, ints, lang);
} else if (!strncasecmp(lang, "he", 2)) { /* Hebrew syntax */
return ast_say_datetime_he(chan, t, ints, lang);
} else if (!strncasecmp(lang, "hu", 2)) { /* Hungarian syntax */
@@ -7394,6 +7409,71 @@ static int ast_say_number_full_gr(struct ast_channel *chan, int num, const char
return res;
}
+/* Japanese syntax */
+static int ast_say_number_full_ja(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd)
+{
+ int res = 0;
+ int playh = 0;
+ char fn[256] = "";
+ if (!num)
+ return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
+
+ while (!res && (num || playh)) {
+ if (num < 0) {
+ ast_copy_string(fn, "digits/minus", sizeof(fn));
+ if ( num > INT_MIN ) {
+ num = -num;
+ } else {
+ num = 0;
+ }
+ } else if (playh) {
+ ast_copy_string(fn, "digits/hundred", sizeof(fn));
+ playh = 0;
+ } else if (num < 20) {
+ snprintf(fn, sizeof(fn), "digits/%d", num);
+ num = 0;
+ } else if (num < 100) {
+ snprintf(fn, sizeof(fn), "digits/%d", (num /10) * 10);
+ num %= 10;
+ } else {
+ if (num < 1000){
+ snprintf(fn, sizeof(fn), "digits/%d", (num/100));
+ playh++;
+ num %= 100;
+ } else {
+ if (num < 1000000) { /* 1,000,000 */
+ res = ast_say_number_full_en(chan, num / 1000, ints, language, audiofd, ctrlfd);
+ if (res)
+ return res;
+ num %= 1000;
+ snprintf(fn, sizeof(fn), "digits/thousand");
+ } else {
+ if (num < 1000000000) { /* 1,000,000,000 */
+ res = ast_say_number_full_en(chan, num / 1000000, ints, language, audiofd, ctrlfd);
+ if (res)
+ return res;
+ num %= 1000000;
+ ast_copy_string(fn, "digits/million", sizeof(fn));
+ } else {
+ ast_debug(1, "Number '%d' is too big for me\n", num);
+ res = -1;
+ }
+ }
+ }
+ }
+ if (!res) {
+ if (!ast_streamfile(chan, fn, language)) {
+ if ((audiofd > -1) && (ctrlfd > -1))
+ res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
+ else
+ res = ast_waitstream(chan, ints);
+ }
+ ast_stopstream(chan);
+ }
+ }
+ return res;
+}
+
/*! \brief Greek support
*
@@ -7439,6 +7519,39 @@ static int ast_say_date_gr(struct ast_channel *chan, time_t t, const char *ints,
}
+/* Japanese syntax */
+int ast_say_date_ja(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
+{
+ struct ast_tm tm;
+ struct timeval tv = { t, 0 };
+ char fn[256];
+ int res = 0;
+ ast_localtime(&tv, &tm, NULL);
+ if (!res)
+ res = ast_say_number(chan, tm.tm_year + 1900, ints, lang, (char *) NULL);
+ if (!res)
+ res = ast_waitstream(chan, ints);
+ if (!res)
+ res = ast_streamfile(chan, "digits/nen", lang);
+ if (!res) {
+ snprintf(fn, sizeof(fn), "digits/mon-%d", tm.tm_mon);
+ res = ast_streamfile(chan, fn, lang);
+ if (!res)
+ res = ast_waitstream(chan, ints);
+ }
+ if (!res)
+ res = ast_say_number(chan, tm.tm_mday, ints, lang, (char * ) NULL);
+ if (!res)
+ res = ast_streamfile(chan, "digits/nichi", lang);
+ if (!res) {
+ snprintf(fn, sizeof(fn), "digits/day-%d", tm.tm_wday);
+ res = ast_streamfile(chan, fn, lang);
+ if (!res)
+ res = ast_waitstream(chan, ints);
+ }
+ return res;
+}
+
/*! \brief Greek support
*
@@ -7496,6 +7609,52 @@ static int ast_say_time_gr(struct ast_channel *chan, time_t t, const char *ints,
}
+/* Japanese */
+static int ast_say_time_ja(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
+{
+
+ struct timeval tv = { t, 0 };
+ struct ast_tm tm;
+ int res = 0;
+ int hour, pm=0;
+
+ ast_localtime(&tv, &tm, NULL);
+ hour = tm.tm_hour;
+
+ if (!hour)
+ hour = 12;
+ else if (hour == 12)
+ pm = 1;
+ else if (hour > 12) {
+ hour -= 12;
+ pm = 1;
+ }
+
+ if (pm) {
+ if (!res)
+ res = ast_streamfile(chan, "digits/p-m", lang);
+ } else {
+ if (!res)
+ res = ast_streamfile(chan, "digits/a-m", lang);
+ }
+ if (hour == 9 || hour == 21) {
+ if (!res)
+ res = ast_streamfile(chan, "digits/9_2", lang);
+ } else {
+ if (!res)
+ res = ast_say_number(chan, hour, ints, lang, (char *) NULL);
+ }
+ if (!res)
+ res = ast_streamfile(chan, "digits/ji", lang);
+ if (!res)
+ res = ast_say_number(chan, tm.tm_min, ints, lang, (char *) NULL);
+ if (!res)
+ res = ast_streamfile(chan, "digits/fun", lang);
+ if (!res)
+ res = ast_waitstream(chan, ints);
+ return res;
+}
+
/*! \brief Greek support
*/
@@ -7531,6 +7690,72 @@ static int ast_say_datetime_gr(struct ast_channel *chan, time_t t, const char *i
return res;
}
+/* Japanese syntax */
+int ast_say_datetime_ja(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
+{
+ struct timeval tv = { t, 0 };
+ struct ast_tm tm;
+ char fn[256];
+ int res = 0;
+ int hour, pm=0;
+
+ ast_localtime(&tv, &tm, NULL);
+
+ if (!res)
+ res = ast_say_number(chan, tm.tm_year + 1900, ints, lang, (char *) NULL);
+ if (!res)
+ res = ast_streamfile(chan, "digits/nen", lang);
+ if (!res) {
+ snprintf(fn, sizeof(fn), "digits/mon-%d", tm.tm_mon);
+ res = ast_streamfile(chan, fn, lang);
+ if (!res)
+ res = ast_waitstream(chan, ints);
+ }
+ if (!res)
+ res = ast_say_number(chan, tm.tm_mday, ints, lang, (char *) NULL);
+ if (!res)
+ res = ast_streamfile(chan, "digits/nichi", lang);
+ if (!res) {
+ snprintf(fn, sizeof(fn), "digits/day-%d", tm.tm_wday);
+ res = ast_streamfile(chan, fn, lang);
+ if (!res)
+ res = ast_waitstream(chan, ints);
+ }
+
+ hour = tm.tm_hour;
+ if (!hour)
+ hour = 12;
+ else if (hour == 12)
+ pm = 1;
+ else if (hour > 12) {
+ hour -= 12;
+ pm = 1;
+ }
+ if (pm) {
+ if (!res)
+ res = ast_streamfile(chan, "digits/p-m", lang);
+ } else {
+ if (!res)
+ res = ast_streamfile(chan, "digits/a-m", lang);
+ }
+ if (hour == 9 || hour == 21) {
+ if (!res)
+ res = ast_streamfile(chan, "digits/9_2", lang);
+ } else {
+ if (!res)
+ res = ast_say_number(chan, hour, ints, lang, (char *) NULL);
+ }
+ if (!res)
+ res = ast_streamfile(chan, "digits/ji", lang);
+ if (!res)
+ res = ast_say_number(chan, tm.tm_min, ints, lang, (char *) NULL);
+ if (!res)
+ res = ast_streamfile(chan, "digits/fun", lang);
+ if (!res)
+ res = ast_waitstream(chan, ints);
+ return res;
+}
+
/*! \brief Greek support
*/
static int ast_say_date_with_format_gr(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone)
@@ -7704,6 +7929,274 @@ static int ast_say_date_with_format_gr(struct ast_channel *chan, time_t t, const
return res;
}
+/* Japanese syntax */
+int ast_say_date_with_format_ja(struct ast_channel *chan, time_t time, const char *ints, const char *lang, const char *format, const char *timezone)
+{
+ struct timeval tv = { time, 0 };
+ struct ast_tm tm;
+ int res=0, offset, sndoffset;
+ char sndfile[256], nextmsg[256];
+
+ if (!format)
+ format = "YbdAPIMS";
+
+ ast_localtime(&tv, &tm, timezone);
+
+ for (offset=0 ; format[offset] != '\0' ; offset++) {
+ ast_log(LOG_DEBUG, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
+ switch (format[offset]) {
+ /* NOTE: if you add more options here, please try to be consistent with strftime(3) */
+ case '\'':
+ /* Literal name of a sound file */
+ sndoffset=0;
+ for (sndoffset=0 ; (format[++offset] != '\'') && (sndoffset < 256) ; sndoffset++)
+ sndfile[sndoffset] = format[offset];
+ sndfile[sndoffset] = '\0';
+ res = wait_file(chan,ints,sndfile,lang);
+ break;
+ case 'A':
+ case 'a':
+ /* Sunday - Saturday */
+ snprintf(nextmsg,sizeof(nextmsg), "digits/day-%d", tm.tm_wday);
+ res = wait_file(chan,ints,nextmsg,lang);
+ break;
+ case 'B':
+ case 'b':
+ case 'h':
+ /* January - December */
+ snprintf(nextmsg,sizeof(nextmsg), "digits/mon-%d", tm.tm_mon);
+ res = wait_file(chan,ints,nextmsg,lang);
+ break;
+ case 'd':
+ case 'e':
+ /* First - Thirtyfirst */
+ if (tm.tm_mday < 21) {
+ snprintf(nextmsg,sizeof(nextmsg), "digits/h-%d_2", tm.tm_mday);
+ res = wait_file(chan,ints,nextmsg,lang);
+ } else if (tm.tm_mday < 30) {
+ /* Between 21 and 29 - two sounds */
+ res = wait_file(chan,ints, "digits/20",lang);
+ if (!res) {
+ snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_mday - 20);
+ res = wait_file(chan,ints,nextmsg,lang);
+ }
+ res = wait_file(chan,ints, "digits/nichi",lang);
+ } else if (tm.tm_mday == 30) {
+ /* 30 */
+ res = wait_file(chan,ints, "digits/h-30_2",lang);
+ } else {
+ /* 31 */
+ res = wait_file(chan,ints, "digits/30",lang);
+ res = wait_file(chan,ints, "digits/1",lang);
+ res = wait_file(chan,ints, "digits/nichi",lang);
+ }
+ break;
+ case 'Y':
+ /* Year */
+ if (tm.tm_year > 99) {
+ res = wait_file(chan,ints, "digits/2",lang);
+ if (!res) {
+ res = wait_file(chan,ints, "digits/thousand",lang);
+ }
+ if (tm.tm_year > 100) {
+ if (!res) {
+ /* This works until the end of 2020 */
+ snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_year - 100);
+ res = wait_file(chan,ints,nextmsg,lang);
+ }
+ }
+ } else {
+ if (tm.tm_year < 1) {
+ /* I'm not going to handle 1900 and prior */
+ /* We'll just be silent on the year, instead of bombing out. */
+ } else {
+ res = wait_file(chan,ints, "digits/19",lang);
+ if (!res) {
+ if (tm.tm_year <= 9) {
+ /* 1901 - 1909 */
+ res = wait_file(chan,ints, "digits/oh",lang);
+ if (!res) {
+ snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_year);
+ res = wait_file(chan,ints,nextmsg,lang);
+ }
+ } else if (tm.tm_year <= 20) {
+ /* 1910 - 1920 */
+ snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_year);
+ res = wait_file(chan,ints,nextmsg,lang);
+ } else {
+ /* 1921 - 1999 */
+ int ten, one;
+ ten = tm.tm_year / 10;
+ one = tm.tm_year % 10;
+ snprintf(nextmsg,sizeof(nextmsg), "digits/%d", ten * 10);
+ res = wait_file(chan,ints,nextmsg,lang);
+ if (!res) {
+ if (one != 0) {
+ snprintf(nextmsg,sizeof(nextmsg), "digits/%d", one);
+ res = wait_file(chan,ints,nextmsg,lang);
+ }
+ }
+ }
+ }
+ }
+ }
+ res = wait_file(chan,ints, "digits/nen",lang);
+ break;
+ case 'P':
+ case 'p':
+ /* AM/PM */
+ if (tm.tm_hour > 11)
+ snprintf(nextmsg,sizeof(nextmsg), "digits/p-m");
+ else
+ snprintf(nextmsg,sizeof(nextmsg), "digits/a-m");
+ res = wait_file(chan,ints,nextmsg,lang);
+ break;
+ case 'I':
+ case 'l':
+ /* 12-Hour */
+ if (tm.tm_hour == 0)
+ snprintf(nextmsg,sizeof(nextmsg), "digits/12");
+ else if (tm.tm_hour == 9 || tm.tm_hour == 21)
+ snprintf(nextmsg,sizeof(nextmsg), "digits/9_2");
+ else if (tm.tm_hour > 12)
+ snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_hour - 12);
+ else
+ snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_hour);
+ res = wait_file(chan,ints,nextmsg,lang);
+ if(!res) res = wait_file(chan,ints, "digits/ji",lang);
+ break;
+ case 'H':
+ case 'k':
+ if (!res) {
+ if (tm.tm_hour != 0) {
+ int remainder = tm.tm_hour;
+ if (tm.tm_hour > 20) {
+ res = wait_file(chan,ints, "digits/20",lang);
+ remainder -= 20;
+ }
+ if (!res) {
+ snprintf(nextmsg,sizeof(nextmsg), "digits/%d", remainder);
+ res = wait_file(chan,ints,nextmsg,lang);
+ }
+ }
+ }
+ res = wait_file(chan,ints, "digits/ji",lang);
+ break;
+ case 'M':
+ /* Minute */
+ if ((tm.tm_min < 21) || (tm.tm_min % 10 == 0)) {
+ snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_min);
+ res = wait_file(chan,ints,nextmsg,lang);
+ } else {
+ int ten, one;
+ ten = (tm.tm_min / 10) * 10;
+ one = (tm.tm_min % 10);
+ snprintf(nextmsg,sizeof(nextmsg), "digits/%d", ten);
+ res = wait_file(chan,ints,nextmsg,lang);
+ if (!res) {
+ /* Fifty, not fifty-zero */
+ if (one != 0) {
+ snprintf(nextmsg,sizeof(nextmsg), "digits/%d", one);
+ res = wait_file(chan,ints,nextmsg,lang);
+ }
+ }
+ }
+ res = wait_file(chan,ints, "digits/fun",lang);
+ break;
+ case 'Q':
+ /* Shorthand for "Today", "Yesterday", or ABdY */
+ {
+ struct timeval now;
+ struct ast_tm tmnow;
+ time_t beg_today;
+
+ gettimeofday(&now,NULL);
+ ast_localtime(&now,&tmnow,timezone);
+ /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
+ /* In any case, it saves not having to do ast_mktime() */
+ beg_today = now.tv_sec - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
+ if (beg_today < time) {
+ /* Today */
+ res = wait_file(chan,ints, "digits/today",lang);
+ } else if (beg_today - 86400 < time) {
+ /* Yesterday */
+ res = wait_file(chan,ints, "digits/yesterday",lang);
+ } else {
+ res = ast_say_date_with_format(chan, time, ints, lang, "ABdY", timezone);
+ }
+ }
+ break;
+ case 'q':
+ /* Shorthand for "" (today), "Yesterday", A (weekday), or ABdY */
+ {
+ struct timeval now;
+ struct ast_tm tmnow;
+ time_t beg_today;
+
+ gettimeofday(&now,NULL);
+ ast_localtime(&now,&tmnow,timezone);
+ /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
+ /* In any case, it saves not having to do ast_mktime() */
+ beg_today = now.tv_sec - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
+ if (beg_today < time) {
+ /* Today */
+ } else if ((beg_today - 86400) < time) {
+ /* Yesterday */
+ res = wait_file(chan,ints, "digits/yesterday",lang);
+ } else if (beg_today - 86400 * 6 < time) {
+ /* Within the last week */
+ res = ast_say_date_with_format(chan, time, ints, lang, "A", timezone);
+ } else {
+ res = ast_say_date_with_format(chan, time, ints, lang, "ABdY", timezone);
+ }
+ }
+ break;
+ case 'R':
+ res = ast_say_date_with_format(chan, time, ints, lang, "HM", timezone);
+ break;
+ case 'S':
+ /* Seconds */
+ if (tm.tm_sec == 0) {
+ snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_sec);
+ res = wait_file(chan,ints,nextmsg,lang);
+ } else if ((tm.tm_sec < 21) || (tm.tm_sec % 10 == 0)) {
+ snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_sec);
+ res = wait_file(chan,ints,nextmsg,lang);
+ } else {
+ int ten, one;
+ ten = (tm.tm_sec / 10) * 10;
+ one = (tm.tm_sec % 10);
+ snprintf(nextmsg,sizeof(nextmsg), "digits/%d", ten);
+ res = wait_file(chan,ints,nextmsg,lang);
+ if (!res) {
+ /* Fifty, not fifty-zero */
+ if (one != 0) {
+ snprintf(nextmsg,sizeof(nextmsg), "digits/%d", one);
+ res = wait_file(chan,ints,nextmsg,lang);
+ }
+ }
+ }
+ res = wait_file(chan,ints, "digits/byou",lang);
+ break;
+ case 'T':
+ res = ast_say_date_with_format(chan, time, ints, lang, "HMS", timezone);
+ break;
+ case ' ':
+ case ' ':
+ /* Just ignore spaces and tabs */
+ break;
+ default:
+ /* Unknown character */
+ ast_log(LOG_WARNING, "Unknown character in datetime format %s: %c at pos %d\n", format, format[offset], offset);
+ }
+ /* Jump out on DTMF */
+ if (res) {
+ break;
+ }
+ }
+ return res;
+}
+
/*! \brief Vietnamese syntax */
int ast_say_date_with_format_vi(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *tzone)
{