From 804779a653f59290679a3d2a11ca68ef61d1799e Mon Sep 17 00:00:00 2001 From: markster Date: Mon, 3 May 2004 04:38:31 +0000 Subject: Internationalize say_date_time, fix small pbx_config seglet (bug #1537) git-svn-id: http://svn.digium.com/svn/asterisk/trunk@2871 f38db490-d61c-443f-a65b-d21fe96a405b --- say.c | 2119 +++++++++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 1401 insertions(+), 718 deletions(-) (limited to 'say.c') diff --git a/say.c b/say.c index 5a318e8c0..1a88efeb0 100755 --- a/say.c +++ b/say.c @@ -414,13 +414,23 @@ int ast_say_digits_full(struct ast_channel *chan, int num, char *ints, char *lan For Portuguese, we're using m & f options to saynumber() to indicate if the gender is masculine or feminine. For Danish, we're using c & n options to saynumber() to indicate if the gender is commune or neutrum. This still needs to be implemented for French, Spanish & German. + + Date/Time functions currently have less languages supported than saynumber(). Note that in future, we need to move to a model where we can differentiate further - e.g. between en_US & en_UK See contrib/i18n.testsuite.conf for some examples of the different syntaxes - OEJ 2004-04-25 - FPB 2004-05-01 + Portuguese sound files needed for Time/Date functions: + pt-ah + pt-ao + pt-de + pt-e + pt-ora + pt-meianoite + pt-meiodia + pt-sss + */ static int ast_say_number_full_en(struct ast_channel *chan, int num, char *ints, char *language, int audiofd, int ctrlfd); @@ -431,6 +441,30 @@ static int ast_say_number_full_fr(struct ast_channel *chan, int num, char *ints, static int ast_say_number_full_it(struct ast_channel *chan, int num, char *ints, char *language, int audiofd, int ctrlfd); static int ast_say_number_full_nl(struct ast_channel *chan, int num, char *ints, char *language, int audiofd, int ctrlfd); static int ast_say_number_full_pt(struct ast_channel *chan, int num, char *ints, char *language, char *options, int audiofd, int ctrlfd); +static int ast_say_date_en(struct ast_channel *chan, time_t t, char *ints, char *lang); +static int ast_say_date_nl(struct ast_channel *chan, time_t t, char *ints, char *lang); +static int ast_say_date_pt(struct ast_channel *chan, time_t t, char *ints, char *lang); +static int ast_say_date_with_format_en(struct ast_channel *chan, time_t time, char *ints, char *lang, char *format, char *timezone); +static int ast_say_date_with_format_nl(struct ast_channel *chan, time_t time, char *ints, char *lang, char *format, char *timezone); +static int ast_say_date_with_format_pt(struct ast_channel *chan, time_t time, char *ints, char *lang, char *format, char *timezone); +static int ast_say_time_en(struct ast_channel *chan, time_t t, char *ints, char *lang); +static int ast_say_time_nl(struct ast_channel *chan, time_t t, char *ints, char *lang); +static int ast_say_time_pt(struct ast_channel *chan, time_t t, char *ints, char *lang); +static int ast_say_datetime_en(struct ast_channel *chan, time_t t, char *ints, char *lang); +static int ast_say_datetime_nl(struct ast_channel *chan, time_t t, char *ints, char *lang); +static int ast_say_datetime_pt(struct ast_channel *chan, time_t t, char *ints, char *lang); +static int ast_say_datetime_from_now_en(struct ast_channel *chan, time_t t, char *ints, char *lang); +static int ast_say_datetime_from_now_pt(struct ast_channel *chan, time_t t, char *ints, char *lang); + +static int wait_file(struct ast_channel *chan, char *ints, char *file, char *lang) +{ + int res; + if ((res = ast_streamfile(chan, file, lang))) + ast_log(LOG_WARNING, "Unable to play message %s\n", file); + if (!res) + res = ast_waitstream(chan, ints); + return res; +} /*--- ast_say_number_full: call language-specific functions */ /* Called from AGI */ @@ -501,12 +535,10 @@ static int ast_say_number_full_en(struct ast_channel *chan, int num, char *ints, if (playh) { snprintf(fn, sizeof(fn), "digits/hundred"); playh = 0; - } else - if (num < 20) { + } else if (num < 20) { snprintf(fn, sizeof(fn), "digits/%d", num); num = 0; - } else - if (num < 100) { + } else if (num < 100) { snprintf(fn, sizeof(fn), "digits/%d", (num /10) * 10); num -= ((num / 10) * 10); } else { @@ -535,14 +567,14 @@ static int ast_say_number_full_en(struct ast_channel *chan, int num, char *ints, } } } - if (!res) { - if(!ast_streamfile(chan, fn, language)) { - if (audiofd && ctrlfd) - res = ast_waitstream_full(chan, ints, audiofd, ctrlfd); - else - res = ast_waitstream(chan, ints); - } - ast_stopstream(chan); + if (!res) { + if(!ast_streamfile(chan, fn, language)) { + if (audiofd && ctrlfd) + res = ast_waitstream_full(chan, ints, audiofd, ctrlfd); + else + res = ast_waitstream(chan, ints); + } + ast_stopstream(chan); } @@ -550,87 +582,6 @@ static int ast_say_number_full_en(struct ast_channel *chan, int num, char *ints, return res; } - -/*--- ast_say_number_full_fr: French syntax */ -static int ast_say_number_full_fr(struct ast_channel *chan, int num, char *ints, char *language, int audiofd, int ctrlfd) -{ - int res = 0; - int playh = 0; - int playa = 0; /* For french */ - char fn[256] = ""; - if (!num) - return ast_say_digits_full(chan, 0,ints, language, audiofd, ctrlfd); - while(!res && (num || playh || playa)) { - if (playh) { - snprintf(fn, sizeof(fn), "digits/hundred"); - playh = 0; - } else - if (playa) { - snprintf(fn, sizeof(fn), "digits/et"); - playa = 0; - } else - if (num < 21) { - snprintf(fn, sizeof(fn), "digits/%d", num); - num = 0; - } else - if (num < 70) { - snprintf(fn, sizeof(fn), "digits/%d", (num/10)*10); - if ((num % 10) == 1) playa++; - num = num % 10; - } else - if (num < 80) { - snprintf(fn, sizeof(fn), "digits/60"); - if ((num % 10) == 1) playa++; - num = num - 60; - } else - if (num < 100) { - snprintf(fn, sizeof(fn), "digits/80"); - num = num - 80; - } else - if (num < 200) { - snprintf(fn, sizeof(fn), "digits/hundred"); - num = num - 100; - } else - if (num < 1000) { - snprintf(fn, sizeof(fn), "digits/%d", (num/100)); - playh++; - num = num % 100; - } else - if (num < 2000) { - snprintf(fn, sizeof(fn), "digits/thousand"); - num = num - 1000; - } else - if (num < 1000000) { - res = ast_say_number_full_fr(chan, num / 1000, ints, language, audiofd, ctrlfd); - if (res) return res; - snprintf(fn, sizeof(fn), "digits/thousand"); - num = num % 1000; - } else - if (num < 1000000000) { - res = ast_say_number_full_fr(chan, num / 1000000, ints, language, audiofd, ctrlfd); - if (res) return res; - snprintf(fn, sizeof(fn), "digits/million"); - num = num % 1000000; - } else { - ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num); - res = -1; - } - if (!res) { - if(!ast_streamfile(chan, fn, language)) { - if (audiofd && ctrlfd) - res = ast_waitstream_full(chan, ints, audiofd, ctrlfd); - else - res = ast_waitstream(chan, ints); - } - ast_stopstream(chan); - - } - - - } - return res; -} - /*--- ast_say_number_full_da: Danish syntax */ /* New files: In addition to English, the following sounds are required: "1N", "millions", "and" and "1-and" through "9-and" @@ -648,92 +599,86 @@ static int ast_say_number_full_da(struct ast_channel *chan, int num, char *ints, if (options && !strncasecmp(options, "n",1)) cn = -1; while(!res && (num || playh || playa )) { - /* The grammar for Danish numbers is the same as for English except - * for the following: + /* The grammar for Danish numbers is the same as for English except + * for the following: * - 1 exists in both commune ("en", file "1N") and neutrum ("et", file "1") - * - numbers 20 through 99 are said in reverse order, i.e. 21 is - * "one-and twenty" and 68 is "eight-and sixty". - * - "million" is different in singular and plural form - * - numbers > 1000 with zero as the third digit from last have an - * "and" before the last two digits, i.e. 2034 is "two thousand and - * four-and thirty" and 1000012 is "one million and twelve". - */ - if (playh) { - snprintf(fn, sizeof(fn), "digits/hundred"); - playh = 0; - } else - if (playa) { - snprintf(fn, sizeof(fn), "digits/and"); - playa = 0; - } else - if (num == 1 && cn == -1) { - snprintf(fn, sizeof(fn), "digits/1N"); + * - numbers 20 through 99 are said in reverse order, i.e. 21 is + * "one-and twenty" and 68 is "eight-and sixty". + * - "million" is different in singular and plural form + * - numbers > 1000 with zero as the third digit from last have an + * "and" before the last two digits, i.e. 2034 is "two thousand and + * four-and thirty" and 1000012 is "one million and twelve". + */ + if (playh) { + snprintf(fn, sizeof(fn), "digits/hundred"); + playh = 0; + } else if (playa) { + snprintf(fn, sizeof(fn), "digits/and"); + playa = 0; + } else if (num == 1 && cn == -1) { + snprintf(fn, sizeof(fn), "digits/1N"); + num = 0; + } else if (num < 20) { + snprintf(fn, sizeof(fn), "digits/%d", num); + num = 0; + } else if (num < 100) { + int ones = num % 10; + if (ones) { + snprintf(fn, sizeof(fn), "digits/%d-and", ones); + num -= ones; + } else { + snprintf(fn, sizeof(fn), "digits/%d", num); num = 0; - } else - if (num < 20) { - snprintf(fn, sizeof(fn), "digits/%d", num); - num = 0; - } else - if (num < 100) { - int ones = num % 10; - if (ones) { - snprintf(fn, sizeof(fn), "digits/%d-and", ones); - num -= ones; - } else { - snprintf(fn, sizeof(fn), "digits/%d", num); - num = 0; - } - } else { - if (num < 1000) { - int hundreds = num / 100; - if (hundreds == 1) - snprintf(fn, sizeof(fn), "digits/1N"); - else - snprintf(fn, sizeof(fn), "digits/%d", (num / 100)); - - playh++; - num -= 100 * hundreds; - if (num) - playa++; - - } else { - if (num < 1000000) { - res = ast_say_number_full_da(chan, num / 1000, ints, language, "n", audiofd, ctrlfd); - if (res) - return res; - num = num % 1000; - snprintf(fn, sizeof(fn), "digits/thousand"); - } else { - if (num < 1000000000) { - int millions = num / 1000000; - res = ast_say_number_full_da(chan, millions, ints, language, "c", audiofd, ctrlfd); - if (res) - return res; - if (millions == 1) - snprintf(fn, sizeof(fn), "digits/million"); - else - snprintf(fn, sizeof(fn), "digits/millions"); - num = num % 1000000; + } + } else { + if (num < 1000) { + int hundreds = num / 100; + if (hundreds == 1) + snprintf(fn, sizeof(fn), "digits/1N"); + else + snprintf(fn, sizeof(fn), "digits/%d", (num / 100)); + + playh++; + num -= 100 * hundreds; + if (num) + playa++; + + } else { + if (num < 1000000) { + res = ast_say_number_full_da(chan, num / 1000, ints, language, "n", audiofd, ctrlfd); + if (res) + return res; + num = num % 1000; + snprintf(fn, sizeof(fn), "digits/thousand"); + } else { + if (num < 1000000000) { + int millions = num / 1000000; + res = ast_say_number_full_da(chan, millions, ints, language, "c", audiofd, ctrlfd); + if (res) + return res; + if (millions == 1) + snprintf(fn, sizeof(fn), "digits/million"); + else + snprintf(fn, sizeof(fn), "digits/millions"); + num = num % 1000000; } else { - ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num); - res = -1; - } - } - if (num && num < 100) - playa++; - } - } - if (!res) { - if(!ast_streamfile(chan, fn, language)) { - if (audiofd && ctrlfd) - res = ast_waitstream_full(chan, ints, audiofd, ctrlfd); - else - res = ast_waitstream(chan, ints); + ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num); + res = -1; + } } - ast_stopstream(chan); - + if (num && num < 100) + playa++; } - + } + if (!res) { + if(!ast_streamfile(chan, fn, language)) { + if (audiofd && ctrlfd) + res = ast_waitstream_full(chan, ints, audiofd, ctrlfd); + else + res = ast_waitstream(chan, ints); + } + ast_stopstream(chan); + } } return res; } @@ -752,217 +697,252 @@ static int ast_say_number_full_de(struct ast_channel *chan, int num, char *ints, return ast_say_digits_full(chan, 0,ints, language, audiofd, ctrlfd); while(!res && (num || playh || playa )) { - /* The grammar for German numbers is the same as for English except - * for the following: - * - numbers 20 through 99 are said in reverse order, i.e. 21 is - * "one-and twenty" and 68 is "eight-and sixty". - * - "million" is different in singular and plural form - * - numbers > 1000 with zero as the third digit from last have an - * "and" before the last two digits, i.e. 2034 is "two thousand and - * four-and thirty" and 1000012 is "one million and twelve". - */ - if (playh) { - snprintf(fn, sizeof(fn), "digits/hundred"); - playh = 0; - } else - if (playa) { - snprintf(fn, sizeof(fn), "digits/and"); - playa = 0; - } else - if (num < 20) { - snprintf(fn, sizeof(fn), "digits/%d", num); - num = 0; - } else - if (num < 100) { - int ones = num % 10; - if (ones) { - snprintf(fn, sizeof(fn), "digits/%d-and", ones); - num -= ones; - } else { - snprintf(fn, sizeof(fn), "digits/%d", num); - num = 0; - } - } else { - if (num < 1000) { - int hundreds = num / 100; - if (hundreds == 1) - snprintf(fn, sizeof(fn), "digits/1N"); - else - snprintf(fn, sizeof(fn), "digits/%d", (num / 100)); - - playh++; - num -= 100 * hundreds; - if (num) - playa++; - - } else { - if (num < 1000000) { - res = ast_say_number_full_da(chan, num / 1000, ints, language, "n", audiofd, ctrlfd); - if (res) - return res; - num = num % 1000; - snprintf(fn, sizeof(fn), "digits/thousand"); - } else { - if (num < 1000000000) { - int millions = num / 1000000; - res = ast_say_number_full_da(chan, millions, ints, language, "c", audiofd, ctrlfd); - if (res) - return res; - if (millions == 1) - snprintf(fn, sizeof(fn), "digits/million"); - else - snprintf(fn, sizeof(fn), "digits/millions"); - num = num % 1000000; + /* The grammar for German numbers is the same as for English except + * for the following: + * - numbers 20 through 99 are said in reverse order, i.e. 21 is + * "one-and twenty" and 68 is "eight-and sixty". + * - "million" is different in singular and plural form + * - numbers > 1000 with zero as the third digit from last have an + * "and" before the last two digits, i.e. 2034 is "two thousand and + * four-and thirty" and 1000012 is "one million and twelve". + */ + if (playh) { + snprintf(fn, sizeof(fn), "digits/hundred"); + playh = 0; + } else if (playa) { + snprintf(fn, sizeof(fn), "digits/and"); + playa = 0; + } else if (num < 20) { + snprintf(fn, sizeof(fn), "digits/%d", num); + num = 0; + } else if (num < 100) { + int ones = num % 10; + if (ones) { + snprintf(fn, sizeof(fn), "digits/%d-and", ones); + num -= ones; + } else { + snprintf(fn, sizeof(fn), "digits/%d", num); + num = 0; + } + } else { + if (num < 1000) { + int hundreds = num / 100; + if (hundreds == 1) + snprintf(fn, sizeof(fn), "digits/1N"); + else + snprintf(fn, sizeof(fn), "digits/%d", (num / 100)); + playh++; + num -= 100 * hundreds; + if (num) + playa++; + } else { + if (num < 1000000) { + res = ast_say_number_full_da(chan, num / 1000, ints, language, "n", audiofd, ctrlfd); + if (res) + return res; + num = num % 1000; + snprintf(fn, sizeof(fn), "digits/thousand"); + } else { + if (num < 1000000000) { + int millions = num / 1000000; + res = ast_say_number_full_da(chan, millions, ints, language, "c", audiofd, ctrlfd); + if (res) + return res; + if (millions == 1) + snprintf(fn, sizeof(fn), "digits/million"); + else + snprintf(fn, sizeof(fn), "digits/millions"); + num = num % 1000000; } else { - ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num); - res = -1; - } - } - if (num && num < 100) - playa++; - } - } - if (!res) { - if(!ast_streamfile(chan, fn, language)) { - if (audiofd && ctrlfd) - res = ast_waitstream_full(chan, ints, audiofd, ctrlfd); - else - res = ast_waitstream(chan, ints); + ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num); + res = -1; + } } - ast_stopstream(chan); - + if (num && num < 100) + playa++; } - + } + if (!res) { + if(!ast_streamfile(chan, fn, language)) { + if (audiofd && ctrlfd) + res = ast_waitstream_full(chan, ints, audiofd, ctrlfd); + else + res = ast_waitstream(chan, ints); + } + ast_stopstream(chan); + } } return res; } -/*------------ Portuguese ----------------------*/ -/* ast_say_number_full_pt: Portuguese syntax */ -/* Extra sounds needed: */ -/* For feminin all sound files end with F */ -/* 100E for 100+ something */ -/* 1000000S for plural */ -/* pt-e for 'and' */ -static int ast_say_number_full_pt(struct ast_channel *chan, int num, char *ints, char *language, char *options, int audiofd, int ctrlfd) +/*--- ast_say_number_full_es: spanish syntax */ +/* New files: + Requires a few new audios: + 21.gsm thru 29.gsm, cien.gsm, mil.gsm, millon.gsm, millones.gsm, 100.gsm, 200.gsm, 300.gsm, 400.gsm, 500.gsm, 600.gsm, 700.gsm, 800.gsm, 900.gsm, y.gsm + */ +static int ast_say_number_full_es(struct ast_channel *chan, int num, char *ints, char *language, int audiofd, int ctrlfd) { int res = 0; - int playh = 0; - int mf = 1; /* +1 = Masculin; -1 = Feminin */ - + int playa = 0; char fn[256] = ""; - if (!num) return ast_say_digits_full(chan, 0,ints, language, audiofd, ctrlfd); + while (!res && num) { + if (playa) { + snprintf(fn, sizeof(fn), "digits/y"); + playa = 0; + } else if (num < 31) { + snprintf(fn, sizeof(fn), "digits/%d", num); + num = 0; + } else if (num < 100) { + snprintf(fn, sizeof(fn), "digits/%d", (num/10)*10); + num -= ((num/10)*10); + if (num) + playa++; + } else if (num == 100) { + snprintf(fn, sizeof(fn), "digits/cien"); + num = 0; + } else { + if (num < 1000) { + snprintf(fn, sizeof(fn), "digits/%d", (num/100)*100); + num -= ((num/100)*100); + } else { + if (num < 1000000) { + res = ast_say_number_full_es(chan, num / 1000, ints, language, audiofd, ctrlfd); + if (res) + return res; + num = num % 1000; + snprintf(fn, sizeof(fn), "digits/mil"); + } else { + if (num < 2147483640) { + res = ast_say_number_full_es(chan, num / 1000000, ints, language, audiofd, ctrlfd); + if (res) + return res; + if ((num/1000000) == 1) { + snprintf(fn, sizeof(fn), "digits/millon"); + } else { + snprintf(fn, sizeof(fn), "digits/millones"); + } + num = num % 1000000; + } else { + ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num); + res = -1; + } + } + } + } - if (options && !strncasecmp(options, "f",1)) mf = -1; - - while(!res && num ) { - - if (num < 20) { - if ((num == 1 || num == 2) && (mf < 0)) - snprintf(fn, sizeof(fn), "digits/%dF", num); - else - snprintf(fn, sizeof(fn), "digits/%d", num); - num = 0; - } else - if (num < 100) { - snprintf(fn, sizeof(fn), "digits/%d", (num / 10) * 10); - if (num % 10) - playh = 1; - num = num % 10; - } else - if (num < 1000) { - if (num == 100) - snprintf(fn, sizeof(fn), "digits/100"); - else if (num < 200) - snprintf(fn, sizeof(fn), "digits/100E"); - else { - if (mf < 0 && num > 199) - snprintf(fn, sizeof(fn), "digits/%dF", (num / 100) * 100); - else - snprintf(fn, sizeof(fn), "digits/%d", (num / 100) * 100); - if (num % 100) - playh = 1; - } - num = num % 100; - } else - if (num < 1000000) { - if (num > 1999) { - res = ast_say_number_full_pt(chan, (num / 1000) * mf, ints, language, options, audiofd, ctrlfd); - if (res) - return res; - } - snprintf(fn, sizeof(fn), "digits/1000"); - if ((num % 1000) && ((num % 1000) < 100 || !(num % 100))) - playh = 1; - num = num % 1000; - } else - if (num < 1000000000) { - res = ast_say_number_full_pt(chan, (num / 1000000), ints, language, options, audiofd, ctrlfd ); - if (res) - return res; - - if (num < 2000000) - snprintf(fn, sizeof(fn), "digits/1000000"); - else - snprintf(fn, sizeof(fn), "digits/1000000S"); - - if ((num % 1000000) && - // no thousands - ((!((num / 1000) % 1000) && ((num % 1000) < 100 || !(num % 100))) || - // no hundreds and below - (!(num % 1000) && (((num / 1000) % 1000) < 100 || !((num / 1000) % 100))) ) ) - playh = 1; - num = num % 1000000; - } - if (!res && playh) { - res = wait_file(chan, ints, "digits/pt-e", language); - ast_stopstream(chan); - playh = 0; - } - if (!res) { - if(!ast_streamfile(chan, fn, language)) { - if (audiofd && ctrlfd) - res = ast_waitstream_full(chan, ints, audiofd, ctrlfd); - else - res = ast_waitstream(chan, ints); - } - ast_stopstream(chan); - - } + if (!res) { + if(!ast_streamfile(chan, fn, language)) { + if (audiofd && ctrlfd) + res = ast_waitstream_full(chan, ints, audiofd, ctrlfd); + else + res = ast_waitstream(chan, ints); + } + ast_stopstream(chan); + } + } return res; } -/*--- ast_say_number_full_it: italian */ +/*--- ast_say_number_full_fr: French syntax */ +static int ast_say_number_full_fr(struct ast_channel *chan, int num, char *ints, char *language, int audiofd, int ctrlfd) +{ + int res = 0; + int playh = 0; + int playa = 0; + char fn[256] = ""; + if (!num) + return ast_say_digits_full(chan, 0,ints, language, audiofd, ctrlfd); + while(!res && (num || playh || playa)) { + if (playh) { + snprintf(fn, sizeof(fn), "digits/hundred"); + playh = 0; + } else if (playa) { + snprintf(fn, sizeof(fn), "digits/et"); + playa = 0; + } else if (num < 21) { + snprintf(fn, sizeof(fn), "digits/%d", num); + num = 0; + } else if (num < 70) { + snprintf(fn, sizeof(fn), "digits/%d", (num/10)*10); + if ((num % 10) == 1) playa++; + num = num % 10; + } else if (num < 80) { + snprintf(fn, sizeof(fn), "digits/60"); + if ((num % 10) == 1) playa++; + num = num - 60; + } else if (num < 100) { + snprintf(fn, sizeof(fn), "digits/80"); + num = num - 80; + } else if (num < 200) { + snprintf(fn, sizeof(fn), "digits/hundred"); + num = num - 100; + } else if (num < 1000) { + snprintf(fn, sizeof(fn), "digits/%d", (num/100)); + playh++; + num = num % 100; + } else if (num < 2000) { + snprintf(fn, sizeof(fn), "digits/thousand"); + num = num - 1000; + } else if (num < 1000000) { + res = ast_say_number_full_fr(chan, num / 1000, ints, language, audiofd, ctrlfd); + if (res) + return res; + snprintf(fn, sizeof(fn), "digits/thousand"); + num = num % 1000; + } else if (num < 1000000000) { + res = ast_say_number_full_fr(chan, num / 1000000, ints, language, audiofd, ctrlfd); + if (res) + return res; + snprintf(fn, sizeof(fn), "digits/million"); + num = num % 1000000; + } else { + ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num); + res = -1; + } + if (!res) { + if(!ast_streamfile(chan, fn, language)) { + if (audiofd && ctrlfd) + res = ast_waitstream_full(chan, ints, audiofd, ctrlfd); + else + res = ast_waitstream(chan, ints); + } + ast_stopstream(chan); + } + } + return res; +} + +/*--- ast_say_number_full_it: Italian */ static int ast_say_number_full_it(struct ast_channel *chan, int num, char *ints, char *language, int audiofd, int ctrlfd) { - int res = 0; - int playh = 0; - int tempnum = 0; - char fn[256] = ""; + int res = 0; + int playh = 0; + int tempnum = 0; + char fn[256] = ""; - if (!num) + if (!num) return ast_say_digits_full(chan, 0,ints, language, audiofd, ctrlfd); /* Italian support - Like english, numbers till 20 are a single 'word', and other + Like english, numbers up to 20 are a single 'word', and others compound, but with exceptions. - For example 21 is not twenty-one, but is a single word in it. + For example 21 is not twenty-one, but there is a single word in 'it'. Idem for 28 (ie when a the 2nd part of a compund number - starts with a wovel) + starts with a vowel) - There're exceptions also for hundred, thounsand and million. + There are exceptions also for hundred, thousand and million. In english 100 = one hundred, 200 is two hundred. In italian 100 = cento , like to say hundred (without one), 200 and more are like english. - Same apply for thousand: + Same applies for thousand: 1000 is one thousand in en, 2000 is two thousand. In it we have 1000 = mille , 2000 = 2 mila @@ -972,289 +952,293 @@ static int ast_say_number_full_it(struct ast_channel *chan, int num, char *ints, So the right file is provided. */ - while(!res && (num || playh)) { - if (playh) { - snprintf(fn, sizeof(fn), "digits/hundred"); - playh = 0; - } else - if (num < 20) { - snprintf(fn, sizeof(fn), "digits/%d", num); - num = 0; - } else - if (num == 21) { - snprintf(fn, sizeof(fn), "digits/%d", num); - num = 0; - } else - if (num == 28) { - snprintf(fn, sizeof(fn), "digits/%d", num); - num = 0; - } else - if (num == 31) { - snprintf(fn, sizeof(fn), "digits/%d", num); - num = 0; - } else - if (num == 38) { - snprintf(fn, sizeof(fn), "digits/%d", num); - num = 0; - } else - if (num == 41) { - snprintf(fn, sizeof(fn), "digits/%d", num); - num = 0; - } else - if (num == 48) { - snprintf(fn, sizeof(fn), "digits/%d", num); - num = 0; - } else - if (num == 51) { - snprintf(fn, sizeof(fn), "digits/%d", num); - num = 0; - } else - if (num == 58) { - snprintf(fn, sizeof(fn), "digits/%d", num); - num = 0; - } else - if (num == 61) { - snprintf(fn, sizeof(fn), "digits/%d", num); - num = 0; - } else - if (num == 68) { - snprintf(fn, sizeof(fn), "digits/%d", num); - num = 0; - } else - if (num == 71) { - snprintf(fn, sizeof(fn), "digits/%d", num); - num = 0; - } else - if (num == 78) { - snprintf(fn, sizeof(fn), "digits/%d", num); - num = 0; - } else - if (num == 81) { - snprintf(fn, sizeof(fn), "digits/%d", num); - num = 0; - } else - if (num == 88) { - snprintf(fn, sizeof(fn), "digits/%d", num); - num = 0; - } else - if (num == 91) { - snprintf(fn, sizeof(fn), "digits/%d", num); - num = 0; - } else - if (num == 98) { - snprintf(fn, sizeof(fn), "digits/%d", num); - num = 0; - } else - if (num < 100) { - snprintf(fn, sizeof(fn), "digits/%d", (num /10) * 10); - num -= ((num / 10) * 10); - } else { - if (num < 1000){ - if ((num / 100) > 1) { - snprintf(fn, sizeof(fn), "digits/%d", (num/100)); - playh++; - } - else { - snprintf(fn, sizeof(fn), "digits/hundred"); - } - num -= ((num / 100) * 100); - } else { - if (num < 1000000) { /* 1,000,000 */ - if ((num/1000) > 1) - res = ast_say_number_full(chan, num / 1000, ints, language, audiofd, ctrlfd); - if (res) - return res; - tempnum = num; - num = num % 1000; - if ((tempnum / 1000) < 2) - snprintf(fn, sizeof(fn), "digits/thousand"); - else /* for 1000 it says mille, for >1000 (eg 2000) says mila */ - snprintf(fn, sizeof(fn), "digits/thousands"); - } else { - if (num < 1000000000) { /* 1,000,000,000 */ - if ((num / 1000000) > 1) - res = ast_say_number_full(chan, num / 1000000, ints, language, audiofd, ctrlfd); - if (res) - return res; - tempnum = num; - num = num % 1000000; - if ((tempnum / 1000000) < 2) - snprintf(fn, sizeof(fn), "digits/million"); - else - snprintf(fn, sizeof(fn), "digits/millions"); - } else { - ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num); - res = -1; - } - } - } - } - if (!res) { - if(!ast_streamfile(chan, fn, language)) { - if (audiofd && ctrlfd) - res = ast_waitstream_full(chan, ints, audiofd, ctrlfd); - else - res = ast_waitstream(chan, ints); - } - ast_stopstream(chan); - - } - } - return res; + while(!res && (num || playh)) { + if (playh) { + snprintf(fn, sizeof(fn), "digits/hundred"); + playh = 0; + } else if (num < 20) { + snprintf(fn, sizeof(fn), "digits/%d", num); + num = 0; + } else if (num == 21) { + snprintf(fn, sizeof(fn), "digits/%d", num); + num = 0; + } else if (num == 28) { + snprintf(fn, sizeof(fn), "digits/%d", num); + num = 0; + } else if (num == 31) { + snprintf(fn, sizeof(fn), "digits/%d", num); + num = 0; + } else if (num == 38) { + snprintf(fn, sizeof(fn), "digits/%d", num); + num = 0; + } else if (num == 41) { + snprintf(fn, sizeof(fn), "digits/%d", num); + num = 0; + } else if (num == 48) { + snprintf(fn, sizeof(fn), "digits/%d", num); + num = 0; + } else if (num == 51) { + snprintf(fn, sizeof(fn), "digits/%d", num); + num = 0; + } else if (num == 58) { + snprintf(fn, sizeof(fn), "digits/%d", num); + num = 0; + } else if (num == 61) { + snprintf(fn, sizeof(fn), "digits/%d", num); + num = 0; + } else if (num == 68) { + snprintf(fn, sizeof(fn), "digits/%d", num); + num = 0; + } else if (num == 71) { + snprintf(fn, sizeof(fn), "digits/%d", num); + num = 0; + } else if (num == 78) { + snprintf(fn, sizeof(fn), "digits/%d", num); + num = 0; + } else if (num == 81) { + snprintf(fn, sizeof(fn), "digits/%d", num); + num = 0; + } else if (num == 88) { + snprintf(fn, sizeof(fn), "digits/%d", num); + num = 0; + } else if (num == 91) { + snprintf(fn, sizeof(fn), "digits/%d", num); + num = 0; + } else if (num == 98) { + snprintf(fn, sizeof(fn), "digits/%d", num); + num = 0; + } else if (num < 100) { + snprintf(fn, sizeof(fn), "digits/%d", (num /10) * 10); + num -= ((num / 10) * 10); + } else { + if (num < 1000) { + if ((num / 100) > 1) { + snprintf(fn, sizeof(fn), "digits/%d", (num/100)); + playh++; + } else { + snprintf(fn, sizeof(fn), "digits/hundred"); + } + num -= ((num / 100) * 100); + } else { + if (num < 1000000) { /* 1,000,000 */ + if ((num/1000) > 1) + res = ast_say_number_full(chan, num / 1000, ints, language, audiofd, ctrlfd); + if (res) + return res; + tempnum = num; + num = num % 1000; + if ((tempnum / 1000) < 2) + snprintf(fn, sizeof(fn), "digits/thousand"); + else /* for 1000 it says mille, for >1000 (eg 2000) says mila */ + snprintf(fn, sizeof(fn), "digits/thousands"); + } else { + if (num < 1000000000) { /* 1,000,000,000 */ + if ((num / 1000000) > 1) + res = ast_say_number_full(chan, num / 1000000, ints, language, audiofd, ctrlfd); + if (res) + return res; + tempnum = num; + num = num % 1000000; + if ((tempnum / 1000000) < 2) + snprintf(fn, sizeof(fn), "digits/million"); + else + snprintf(fn, sizeof(fn), "digits/millions"); + } else { + ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num); + res = -1; + } + } + } + } + if (!res) { + if(!ast_streamfile(chan, fn, language)) { + if (audiofd && ctrlfd) + res = ast_waitstream_full(chan, ints, audiofd, ctrlfd); + else + res = ast_waitstream(chan, ints); + } + ast_stopstream(chan); + } + } + return res; } - -/*--- ast_say_number_full_es: spanish syntax */ -/* New files: - Requires a few new audios: - 21.gsm thru 29.gsm, cien.gsm, mil.gsm, millon.gsm, millones.gsm, 100.gsm, 200.gsm, 300.gsm, 400.gsm, 500.gsm, 600.gsm, 700.gsm, 800.gsm, 900.gsm, y.gsm +/*--- ast_say_number_full_nl: dutch syntax */ +/* New files: digits/nl-en */ -static int ast_say_number_full_es(struct ast_channel *chan, int num, char *ints, char *language, int audiofd, int ctrlfd) +static int ast_say_number_full_nl(struct ast_channel *chan, int num, char *ints, char *language, int audiofd, int ctrlfd) { int res = 0; - int playa = 0; + int playh = 0; + int units = 0; char fn[256] = ""; if (!num) return ast_say_digits_full(chan, 0,ints, language, audiofd, ctrlfd); - while (!res && num) { - if (playa) { - snprintf(fn, sizeof(fn), "digits/y"); - playa = 0; - } else - if (num < 31) { - snprintf(fn, sizeof(fn), "digits/%d", num); - num = 0; - } else - if (num < 100) { - snprintf(fn, sizeof(fn), "digits/%d", (num/10)*10); - num -= ((num/10)*10); - if (num) - playa++; - } else - if (num == 100) { - snprintf(fn, sizeof(fn), "digits/cien"); - num = 0; - } else { - if (num < 1000) { - snprintf(fn, sizeof(fn), "digits/%d", (num/100)*100); - num -= ((num/100)*100); - } else { - if (num < 1000000) { - res = ast_say_number_full_es(chan, num / 1000, ints, language, audiofd, ctrlfd); - if (res) - return res; - num = num % 1000; - snprintf(fn, sizeof(fn), "digits/mil"); - } else { - if (num < 2147483640) { - res = ast_say_number_full_es(chan, num / 1000000, ints, language, audiofd, ctrlfd); - if (res) - return res; - if ((num/1000000) == 1) { - snprintf(fn, sizeof(fn), "digits/millon"); - } else { - snprintf(fn, sizeof(fn), "digits/millones"); - } - num = num % 1000000; - } else { - ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num); - res = -1; - } - } - } - } - - if (!res) { - if(!ast_streamfile(chan, fn, language)) { - if (audiofd && ctrlfd) - res = ast_waitstream_full(chan, ints, audiofd, ctrlfd); - else - res = ast_waitstream(chan, ints); - } - ast_stopstream(chan); + while (!res && (num || playh )) { + if (playh) { + snprintf(fn, sizeof(fn), "digits/hundred"); + playh = 0; + } else if (num < 20) { + snprintf(fn, sizeof(fn), "digits/%d", num); + num = 0; + } else if (num < 100) { + units = num % 10; + if (units > 0) { + res = ast_say_number_full_nl(chan, units, ints, language, audiofd, ctrlfd); + if (res) + return res; + num = num - units; + snprintf(fn, sizeof(fn), "digits/nl-en"); + } else { + snprintf(fn, sizeof(fn), "digits/%d", num - units); + num = 0; + } + } else { + if (num < 1000) { + snprintf(fn, sizeof(fn), "digits/%d", (num/100)); + playh++; + num -= ((num / 100) * 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 = 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 = num % 1000000; + snprintf(fn, sizeof(fn), "digits/million"); + } else { + ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num); + res = -1; + } + } + } + } - } - + if (!res) { + if(!ast_streamfile(chan, fn, language)) { + if (audiofd && ctrlfd) + res = ast_waitstream_full(chan, ints, audiofd, ctrlfd); + else + res = ast_waitstream(chan, ints); + } + ast_stopstream(chan); + } } return res; } -/*--- ast_say_number_full_nl: dutch syntax */ -/* New files: ??? - */ -static int ast_say_number_full_nl(struct ast_channel *chan, int num, char *ints, char *language, int audiofd, int ctrlfd) +/* ast_say_number_full_pt: Portuguese syntax */ +/* Extra sounds needed: */ +/* For feminin all sound files end with F */ +/* 100E for 100+ something */ +/* 1000000S for plural */ +/* pt-e for 'and' */ +static int ast_say_number_full_pt(struct ast_channel *chan, int num, char *ints, char *language, char *options, int audiofd, int ctrlfd) { int res = 0; int playh = 0; - int units = 0; + int mf = 1; /* +1 = Masculin; -1 = Feminin */ char fn[256] = ""; + if (!num) return ast_say_digits_full(chan, 0,ints, language, audiofd, ctrlfd); - while (!res && (num || playh )) { - if (playh) { - snprintf(fn, sizeof(fn), "digits/hundred"); - playh = 0; - } else - if (num < 20) { - snprintf(fn, sizeof(fn), "digits/%d", num); - num = 0; - } else - if (num < 100) { - units = num % 10; - if (units > 0) { - res = ast_say_number_full_nl(chan, units, ints, language, audiofd, ctrlfd); - if (res) - return res; - num = num - units; - snprintf(fn, sizeof(fn), "digits/nl-en"); - } else { - snprintf(fn, sizeof(fn), "digits/%d", num - units); - num = 0; - } - } else { - if (num < 1000){ - snprintf(fn, sizeof(fn), "digits/%d", (num/100)); - playh++; - num -= ((num / 100) * 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 = 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 = num % 1000000; - snprintf(fn, sizeof(fn), "digits/million"); - } else { - ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num); - res = -1; - } - } - } - } - - if (!res) { - if(!ast_streamfile(chan, fn, language)) { - if (audiofd && ctrlfd) - res = ast_waitstream_full(chan, ints, audiofd, ctrlfd); - else - res = ast_waitstream(chan, ints); - } - ast_stopstream(chan); - - } - - } - return res; -} + if (options && !strncasecmp(options, "f",1)) + mf = -1; + + while(!res && num ) { + if (num < 20) { + if ((num == 1 || num == 2) && (mf < 0)) + snprintf(fn, sizeof(fn), "digits/%dF", num); + else + snprintf(fn, sizeof(fn), "digits/%d", num); + num = 0; + } else if (num < 100) { + snprintf(fn, sizeof(fn), "digits/%d", (num / 10) * 10); + if (num % 10) + playh = 1; + num = num % 10; + } else if (num < 1000) { + if (num == 100) + snprintf(fn, sizeof(fn), "digits/100"); + else if (num < 200) + snprintf(fn, sizeof(fn), "digits/100E"); + else { + if (mf < 0 && num > 199) + snprintf(fn, sizeof(fn), "digits/%dF", (num / 100) * 100); + else + snprintf(fn, sizeof(fn), "digits/%d", (num / 100) * 100); + if (num % 100) + playh = 1; + } + num = num % 100; + } else if (num < 1000000) { + if (num > 1999) { + res = ast_say_number_full_pt(chan, (num / 1000) * mf, ints, language, options, audiofd, ctrlfd); + if (res) + return res; + } + snprintf(fn, sizeof(fn), "digits/1000"); + if ((num % 1000) && ((num % 1000) < 100 || !(num % 100))) + playh = 1; + num = num % 1000; + } else if (num < 1000000000) { + res = ast_say_number_full_pt(chan, (num / 1000000), ints, language, options, audiofd, ctrlfd ); + if (res) + return res; + if (num < 2000000) + snprintf(fn, sizeof(fn), "digits/1000000"); + else + snprintf(fn, sizeof(fn), "digits/1000000S"); + + if ((num % 1000000) && + // no thousands + ((!((num / 1000) % 1000) && ((num % 1000) < 100 || !(num % 100))) || + // no hundreds and below + (!(num % 1000) && (((num / 1000) % 1000) < 100 || !((num / 1000) % 100))) ) ) + playh = 1; + num = num % 1000000; + } + if (!res && playh) { + res = wait_file(chan, ints, "digits/pt-e", language); + ast_stopstream(chan); + playh = 0; + } + if (!res) { + if(!ast_streamfile(chan, fn, language)) { + if (audiofd && ctrlfd) + res = ast_waitstream_full(chan, ints, audiofd, ctrlfd); else + res = ast_waitstream(chan, ints); + } + ast_stopstream(chan); + } + } + return res; +} int ast_say_date(struct ast_channel *chan, time_t t, char *ints, char *lang) +{ + if (!strcasecmp(lang,"en") ) { /* English syntax */ + return(ast_say_date_en(chan, t, ints, lang)); + } else if (!strcasecmp(lang, "nl") ) { /* Dutch syntax */ + return(ast_say_date_nl(chan, t, ints, lang)); + } else if (!strcasecmp(lang, "pt") ) { /* Portuguese syntax */ + return(ast_say_date_pt(chan, t, ints, lang)); + } + + /* Default to English */ + return(ast_say_date_en(chan, t, ints, lang)); +} + + +/* English syntax */ +int ast_say_date_en(struct ast_channel *chan, time_t t, char *ints, char *lang) { struct tm tm; char fn[256]; @@ -1274,8 +1258,6 @@ int ast_say_date(struct ast_channel *chan, time_t t, char *ints, char *lang) } if (!res) res = ast_say_number(chan, tm.tm_mday, ints, lang, (char * ) NULL); - /* Should portuguese add a gender here? Defaults to masculin */ - if (!res) res = ast_waitstream(chan, ints); if (!res) @@ -1283,17 +1265,76 @@ int ast_say_date(struct ast_channel *chan, time_t t, char *ints, char *lang) return res; } -static int wait_file(struct ast_channel *chan, char *ints, char *file, char *lang) +/* Dutch syntax */ +int ast_say_date_nl(struct ast_channel *chan, time_t t, char *ints, char *lang) { - int res; - if ((res = ast_streamfile(chan, file, lang))) - ast_log(LOG_WARNING, "Unable to play message %s\n", file); + struct tm tm; + char fn[256]; + int res = 0; + ast_localtime(&t,&tm,NULL); + 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); + } + if (!res) + res = ast_say_number(chan, tm.tm_mday, ints, lang, (char * ) NULL); + 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_waitstream(chan, ints); + if (!res) + res = ast_say_number(chan, tm.tm_year + 1900, ints, lang, (char *) NULL); + return res; +} + +/* Portuguese syntax */ +int ast_say_date_pt(struct ast_channel *chan, time_t t, char *ints, char *lang) +{ + struct tm tm; + char fn[256]; + int res = 0; + ast_localtime(&t,&tm,NULL); + localtime_r(&t,&tm); + snprintf(fn, sizeof(fn), "digits/day-%d", tm.tm_wday); + if (!res) + res = wait_file(chan, ints, fn, lang); + if (!res) + res = ast_say_number(chan, tm.tm_mday, ints, lang, (char *) NULL); + if (!res) + res = wait_file(chan, ints, "digits/pt-de", lang); + snprintf(fn, sizeof(fn), "digits/mon-%d", tm.tm_mon); + if (!res) + res = wait_file(chan, ints, fn, lang); + if (!res) + res = wait_file(chan, ints, "digits/pt-de", lang); + if (!res) + res = ast_say_number(chan, tm.tm_year + 1900, ints, lang, (char *) NULL); + return res; } int ast_say_date_with_format(struct ast_channel *chan, time_t time, char *ints, char *lang, char *format, char *timezone) +{ + if (!strcasecmp(lang, "en") ) { /* English syntax */ + return(ast_say_date_with_format_en(chan, time, ints, lang, format, timezone)); + } else if (!strcasecmp(lang, "nl") ) { /* Dutch syntax */ + return(ast_say_date_with_format_nl(chan, time, ints, lang, format, timezone)); + } else if (!strcasecmp(lang, "pt") ) { /* Portuguese syntax */ + return(ast_say_date_with_format_pt(chan, time, ints, lang, format, timezone)); + } + + /* Default to English */ + return(ast_say_date_with_format_en(chan, time, ints, lang, format, timezone)); +} + +/* English syntax */ +int ast_say_date_with_format_en(struct ast_channel *chan, time_t time, char *ints, char *lang, char *format, char *timezone) { struct tm tm; int res=0, offset, sndoffset; @@ -1350,79 +1391,524 @@ int ast_say_date_with_format(struct ast_channel *chan, time_t time, char *ints, 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); - } - } - } - } - } - } + 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); + } + } + } + } + } + } + break; + case 'I': + case 'l': + /* 12-Hour */ + if (tm.tm_hour == 0) + snprintf(nextmsg,sizeof(nextmsg), "digits/12"); + 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); + break; + case 'H': + case 'k': + /* 24-Hour */ + if (format[offset] == 'H') { + /* e.g. oh-eight */ + if (tm.tm_hour < 10) { + res = wait_file(chan,ints, "digits/oh",lang); + } + } else { + /* e.g. eight */ + if (tm.tm_hour == 0) { + res = wait_file(chan,ints, "digits/oh",lang); + } + } + 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); + } + } + } + break; + case 'M': + /* Minute */ + if (tm.tm_min == 0) { + res = wait_file(chan,ints, "digits/oclock",lang); + } else if (tm.tm_min < 10) { + res = wait_file(chan,ints, "digits/oh",lang); + if (!res) { + snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_min); + res = wait_file(chan,ints,nextmsg,lang); + } + } else 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); + } + } + } + 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 'Q': + /* Shorthand for "Today", "Yesterday", or ABdY */ + { + struct timeval now; + struct tm tmnow; + time_t beg_today; + + gettimeofday(&now,NULL); + ast_localtime(&now.tv_sec,&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 tm tmnow; + time_t beg_today; + + gettimeofday(&now,NULL); + ast_localtime(&now.tv_sec,&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 < 10) { + res = wait_file(chan,ints, "digits/oh",lang); + if (!res) { + 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); + } + } + } + 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; +} + +/* Dutch syntax */ +int ast_say_date_with_format_nl(struct ast_channel *chan, time_t time, char *ints, char *lang, char *format, char *timezone) +{ + struct tm tm; + int res=0, offset, sndoffset; + char sndfile[256], nextmsg[256]; + + ast_localtime(&time,&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'; + snprintf(nextmsg,sizeof(nextmsg), AST_SOUNDS "/%s", sndfile); + res = wait_file(chan,ints,nextmsg,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 */ + res = ast_say_number(chan, tm.tm_mday, ints, lang, NULL); + 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); + } + } + } + } + } + } + break; + case 'I': + case 'l': + /* 12-Hour */ + if (tm.tm_hour == 0) + snprintf(nextmsg,sizeof(nextmsg), "digits/12"); + 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); + break; + case 'H': + case 'k': + /* 24-Hour */ + res = ast_say_number(chan, tm.tm_hour, ints, lang, (char *) NULL); + if (!res) { + res = wait_file(chan,ints, "digits/nl-uur",lang); + } + break; + case 'M': + /* Minute */ + res = ast_say_number(chan, tm.tm_min, ints, lang, (char *) NULL); + 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 'Q': + /* Shorthand for "Today", "Yesterday", or ABdY */ + { + struct timeval now; + struct tm tmnow; + time_t beg_today; + + gettimeofday(&now,NULL); + ast_localtime(&now.tv_sec,&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 tm tmnow; + time_t beg_today; + + gettimeofday(&now,NULL); + ast_localtime(&now.tv_sec,&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 < 10) { + res = wait_file(chan,ints, "digits/oh",lang); + if (!res) { + 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); + } + } + } + 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; +} + +/* Portuguese syntax */ +int ast_say_date_with_format_pt(struct ast_channel *chan, time_t time, char *ints, char *lang, char *format, char *timezone) +{ + struct tm tm; + int res=0, offset, sndoffset; + char sndfile[256], nextmsg[256]; + + ast_localtime(&time,&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'; + snprintf(nextmsg,sizeof(nextmsg), "%s", sndfile); + res = wait_file(chan,ints,nextmsg,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 */ + res = ast_say_number(chan, tm.tm_mday, ints, lang, (char *) NULL); + break; + case 'Y': + /* Year */ + res = ast_say_number(chan, tm.tm_year + 1900, ints, lang, (char *) NULL); break; case 'I': case 'l': /* 12-Hour */ - if (tm.tm_hour == 0) - snprintf(nextmsg,sizeof(nextmsg), "digits/12"); - 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 (tm.tm_hour == 0) { + if (format[offset] == 'I') + res = wait_file(chan, ints, "digits/pt-ah", lang); + if (!res) + res = wait_file(chan, ints, "digits/pt-meianoite", lang); + } + else if (tm.tm_hour == 12) { + if (format[offset] == 'I') + res = wait_file(chan, ints, "digits/pt-ao", lang); + if (!res) + res = wait_file(chan, ints, "digits/pt-meiodia", lang); + } + else { + if (format[offset] == 'I') { + res = wait_file(chan, ints, "digits/pt-ah", lang); + if ((tm.tm_hour % 12) != 1) + if (!res) + res = wait_file(chan, ints, "digits/pt-sss", lang); + } + if (!res) + res = ast_say_number(chan, (tm.tm_hour % 12), ints, lang, "f"); + } break; case 'H': case 'k': /* 24-Hour */ - if (format[offset] == 'H') { - /* e.g. oh-eight */ - if (tm.tm_hour < 10) { - res = wait_file(chan,ints, "digits/oh",lang); - } - } else { - /* e.g. eight */ - if (tm.tm_hour == 0) { - res = wait_file(chan,ints, "digits/oh",lang); - } - } + res = ast_say_number(chan, -tm.tm_hour, ints, lang, NULL); if (!res) { if (tm.tm_hour != 0) { int remainder = tm.tm_hour; @@ -1440,39 +1926,22 @@ int ast_say_date_with_format(struct ast_channel *chan, time_t time, char *ints, case 'M': /* Minute */ if (tm.tm_min == 0) { - res = wait_file(chan,ints, "digits/oclock",lang); - } else if (tm.tm_min < 10) { - res = wait_file(chan,ints, "digits/oh",lang); - if (!res) { - snprintf(nextmsg,sizeof(nextmsg), "digits/%d", tm.tm_min); - res = wait_file(chan,ints,nextmsg,lang); - } - } else 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/pt-hora", lang); + if (tm.tm_hour != 1) + if (!res) + res = wait_file(chan, ints, "digits/pt-sss", lang); } else { + res = wait_file(chan,ints,"digits/pt-e",lang); + if (!res) + res = ast_say_number(chan, tm.tm_min, ints, lang, (char *) NULL); } 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); + if (tm.tm_hour > 12) + res = wait_file(chan, ints, "digits/p-m", lang); + else if (tm.tm_hour && tm.tm_hour < 12) + res = wait_file(chan, ints, "digits/a-m", lang); break; case 'Q': /* Shorthand for "Today", "Yesterday", or ABdY */ @@ -1493,7 +1962,7 @@ int ast_say_date_with_format(struct ast_channel *chan, time_t time, char *ints, /* Yesterday */ res = wait_file(chan,ints, "digits/yesterday",lang); } else { - res = ast_say_date_with_format(chan, time, ints, lang, "ABdY", timezone); + res = ast_say_date_with_format(chan, time, ints, lang, "Ad 'digits/pt-de' B 'digits/pt-de' Y", timezone); } } break; @@ -1518,12 +1987,12 @@ int ast_say_date_with_format(struct ast_channel *chan, time_t time, char *ints, /* 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); + res = ast_say_date_with_format(chan, time, ints, lang, "Ad 'digits/pt-de' B 'digits/pt-de' Y", timezone); } } break; case 'R': - res = ast_say_date_with_format(chan, time, ints, lang, "HM", timezone); + res = ast_say_date_with_format(chan, time, ints, lang, "H 'digits/pt-e' M", timezone); break; case 'S': /* Seconds */ @@ -1574,6 +2043,21 @@ int ast_say_date_with_format(struct ast_channel *chan, time_t time, char *ints, } int ast_say_time(struct ast_channel *chan, time_t t, char *ints, char *lang) +{ + if (!strcasecmp(lang, "en") ) { /* English syntax */ + return(ast_say_time_en(chan, t, ints, lang)); + } else if (!strcasecmp(lang, "nl") ) { /* Dutch syntax */ + return(ast_say_time_nl(chan, t, ints, lang)); + } else if (!strcasecmp(lang, "pt") ) { /* Portuguese syntax */ + return(ast_say_time_pt(chan, t, ints, lang)); + } + + /* Default to English */ + return(ast_say_time_en(chan, t, ints, lang)); +} + +/* English syntax */ +int ast_say_time_en(struct ast_channel *chan, time_t t, char *ints, char *lang) { struct tm tm; int res = 0; @@ -1596,14 +2080,14 @@ int ast_say_time(struct ast_channel *chan, time_t t, char *ints, char *lang) res = ast_say_number(chan, tm.tm_min, ints, lang, (char *) NULL); } else if (tm.tm_min) { if (!res) - res = ast_streamfile(chan, "digits/oh", lang); /* This is very english ! */ + res = ast_streamfile(chan, "digits/oh", lang); if (!res) res = ast_waitstream(chan, ints); if (!res) res = ast_say_number(chan, tm.tm_min, ints, lang, (char *) NULL); } else { if (!res) - res = ast_streamfile(chan, "digits/oclock", lang); /* This is very english ! */ + res = ast_streamfile(chan, "digits/oclock", lang); if (!res) res = ast_waitstream(chan, ints); } @@ -1619,7 +2103,152 @@ int ast_say_time(struct ast_channel *chan, time_t t, char *ints, char *lang) return res; } +/* Dutch syntax */ +int ast_say_time_nl(struct ast_channel *chan, time_t t, char *ints, char *lang) +{ + struct tm tm; + int res = 0; + int hour; + localtime_r(&t,&tm); + hour = tm.tm_hour; + if (!res) + res = ast_say_number(chan, hour, ints, lang, (char *) NULL); + + if (!res) + res = ast_streamfile(chan, "digits/nl-uur", lang); + if (!res) + res = ast_waitstream(chan, ints); + if (!res) + if (tm.tm_min > 0) + res = ast_say_number(chan, tm.tm_min, ints, lang, NULL); + return res; +} + +/* Portuguese syntax */ +int ast_say_time_pt(struct ast_channel *chan, time_t t, char *ints, char *lang) +{ + struct tm tm; + int res = 0; + int hour; + localtime_r(&t,&tm); + hour = tm.tm_hour; + if (!res) + res = ast_say_number(chan, hour, ints, lang, "f"); + if (tm.tm_min) { + if (!res) + res = wait_file(chan, ints, "digits/pt-e", lang); + if (!res) + res = ast_say_number(chan, tm.tm_min, ints, lang, (char *) NULL); + } else { + if (!res) + res = wait_file(chan, ints, "digits/pt-hora", lang); + if (tm.tm_hour != 1) + if (!res) + res = wait_file(chan, ints, "digits/pt-sss", lang); + } + if (!res) + res = ast_say_number(chan, hour, ints, lang, (char *) NULL); + return res; +} + int ast_say_datetime(struct ast_channel *chan, time_t t, char *ints, char *lang) +{ + if (!strcasecmp(lang, "en") ) { /* English syntax */ + return(ast_say_datetime_en(chan, t, ints, lang)); + } else if (!strcasecmp(lang, "nl") ) { /* Dutch syntax */ + return(ast_say_datetime_nl(chan, t, ints, lang)); + } else if (!strcasecmp(lang, "pt") ) { /* Portuguese syntax */ + return(ast_say_datetime_pt(chan, t, ints, lang)); + } + + /* Default to English */ + return(ast_say_datetime_en(chan, t, ints, lang)); +} + +/* English syntax */ +int ast_say_datetime_en(struct ast_channel *chan, time_t t, char *ints, char *lang) +{ + struct tm tm; + char fn[256]; + int res = 0; + int hour, pm=0; + localtime_r(&t,&tm); + 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); + } + 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); + + hour = tm.tm_hour; + if (!hour) + hour = 12; + else if (hour == 12) + pm = 1; + else if (hour > 12) { + hour -= 12; + pm = 1; + } + if (!res) + res = ast_say_number(chan, hour, ints, lang, (char *) NULL); + + if (tm.tm_min > 9) { + if (!res) + res = ast_say_number(chan, tm.tm_min, ints, lang, (char *) NULL); + } else if (tm.tm_min) { + if (!res) + res = ast_streamfile(chan, "digits/oh", lang); + if (!res) + res = ast_waitstream(chan, ints); + if (!res) + res = ast_say_number(chan, tm.tm_min, ints, lang, (char *) NULL); + } else { + if (!res) + res = ast_streamfile(chan, "digits/oclock", lang); + if (!res) + res = ast_waitstream(chan, ints); + } + if (pm) { + if (!res) + res = ast_streamfile(chan, "digits/p-m", lang); + } else { + if (!res) + res = ast_streamfile(chan, "digits/a-m", lang); + } + if (!res) + res = ast_waitstream(chan, ints); + if (!res) + res = ast_say_number(chan, tm.tm_year + 1900, ints, lang, (char *) NULL); + return res; +} + +/* Dutch syntax */ +int ast_say_datetime_nl(struct ast_channel *chan, time_t t, char *ints, char *lang) +{ + struct tm tm; + int res = 0; + localtime_r(&t,&tm); + res = ast_say_date(chan, t, ints, lang); + if (!res) { + res = ast_streamfile(chan, "digits/nl-om", lang); + if (!res) + res = ast_waitstream(chan, ints); + } + if (!res) + ast_say_time(chan, t, ints, lang); + return res; +} + +/* Portuguese syntax */ +int ast_say_datetime_pt(struct ast_channel *chan, time_t t, char *ints, char *lang) { struct tm tm; char fn[256]; @@ -1684,6 +2313,19 @@ int ast_say_datetime(struct ast_channel *chan, time_t t, char *ints, char *lang) } int ast_say_datetime_from_now(struct ast_channel *chan, time_t t, char *ints, char *lang) +{ + if (!strcasecmp(lang, "en") ) { /* English syntax */ + return(ast_say_datetime_from_now_en(chan, t, ints, lang)); + } else if (!strcasecmp(lang, "pt") ) { /* Portuguese syntax */ + return(ast_say_datetime_from_now_pt(chan, t, ints, lang)); + } + + /* Default to English */ + return(ast_say_datetime_from_now_en(chan, t, ints, lang)); +} + +/* English syntax */ +int ast_say_datetime_from_now_en(struct ast_channel *chan, time_t t, char *ints, char *lang) { int res=0; time_t nowt; @@ -1722,3 +2364,44 @@ int ast_say_datetime_from_now(struct ast_channel *chan, time_t t, char *ints, ch return res; } +/* Portuguese syntax */ +int ast_say_datetime_from_now_pt(struct ast_channel *chan, time_t t, char *ints, char *lang) +{ + int res=0; + time_t nowt; + int daydiff; + struct tm tm; + struct tm now; + char fn[256]; + + time(&nowt); + + localtime_r(&t,&tm); + localtime_r(&nowt,&now); + daydiff = now.tm_yday - tm.tm_yday; + if ((daydiff < 0) || (daydiff > 6)) { + /* Day of month and month */ + if (!res) + res = ast_say_number(chan, tm.tm_mday, ints, lang, (char *) NULL); + if (!res) + res = wait_file(chan, ints, "digits/pt-de", lang); + snprintf(fn, sizeof(fn), "digits/mon-%d", tm.tm_mon); + if (!res) + res = wait_file(chan, ints, fn, lang); + + } else if (daydiff) { + /* Just what day of the week */ + snprintf(fn, sizeof(fn), "digits/day-%d", tm.tm_wday); + if (!res) + res = wait_file(chan, ints, fn, lang); + } /* Otherwise, it was today */ + snprintf(fn, sizeof(fn), "digits/pt-ah"); + if (!res) + res = wait_file(chan, ints, fn, lang); + if (tm.tm_hour != 1) + if (!res) + res = wait_file(chan, ints, "digits/pt-sss", lang); + if (!res) + res = ast_say_time(chan, t, ints, lang); + return res; +} -- cgit v1.2.3