aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordhubbard <dhubbard@f38db490-d61c-443f-a65b-d21fe96a405b>2007-03-03 00:59:24 +0000
committerdhubbard <dhubbard@f38db490-d61c-443f-a65b-d21fe96a405b>2007-03-03 00:59:24 +0000
commit4328496d5b59ae137344a6aadc7b3bd3a389cca8 (patch)
tree3a2a5e9bb408ecd7d2636cae66a353fcf81777c0
parent2fb66af75870eee27eaf10087b1823eecd9bfd4c (diff)
submitted patch for Georgian language, issue 9010, submitted by Alexander Shaduri
git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.4@57620 f38db490-d61c-443f-a65b-d21fe96a405b
-rw-r--r--main/say.c389
1 files changed, 389 insertions, 0 deletions
diff --git a/main/say.c b/main/say.c
index a8a207135..e0491f2e9 100644
--- a/main/say.c
+++ b/main/say.c
@@ -25,6 +25,8 @@
*
* \note 12-16-2004 : Support for Greek added by InAccess Networks (work funded by HOL, www.hol.gr) George Konstantoulakis <gkon@inaccessnetworks.com>
*
+ * \note 2007-02-08 : Support for Georgian added by Alexander Shaduri <ashaduri@gmail.com>,
+ * Next Generation Networks (NGN).
*/
#include "asterisk.h"
@@ -274,6 +276,7 @@ static int say_digit_str_full(struct ast_channel *chan, const char *str, const c
\arg \b se - Swedish
\arg \b tw - Taiwanese / Chinese
\arg \b ru - Russian
+ \arg \b ge - Georgian
\par Gender:
For Some languages the numbers differ for gender and plural.
@@ -328,6 +331,7 @@ static int ast_say_number_full_se(struct ast_channel *chan, int num, const char
static int ast_say_number_full_tw(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_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_ge(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd);
/* Forward declarations of language specific variants of ast_say_enumeration_full */
static int ast_say_enumeration_full_en(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd);
@@ -342,6 +346,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_ge(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
static int ast_say_date_with_format_en(struct ast_channel *chan, time_t time, const char *ints, const char *lang, const char *format, const char *timezone);
static int ast_say_date_with_format_da(struct ast_channel *chan, time_t time, const char *ints, const char *lang, const char *format, const char *timezone);
@@ -364,6 +369,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_tw(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_ge(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
static int ast_say_datetime_en(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
static int ast_say_datetime_de(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
@@ -373,10 +379,12 @@ 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_tw(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_ge(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
static int ast_say_datetime_from_now_en(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
static int ast_say_datetime_from_now_fr(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
static int ast_say_datetime_from_now_pt(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
+static int ast_say_datetime_from_now_ge(struct ast_channel *chan, time_t t, const char *ints, const char *lang);
static int wait_file(struct ast_channel *chan, const char *ints, const char *file, const char *lang)
{
@@ -426,6 +434,8 @@ static int say_number_full(struct ast_channel *chan, int num, const char *ints,
return(ast_say_number_full_gr(chan, num, ints, language, audiofd, ctrlfd));
} else if (!strcasecmp(language, "ru") ) { /* Russian syntax */
return(ast_say_number_full_ru(chan, num, ints, language, options, audiofd, ctrlfd));
+ } else if (!strcasecmp(language, "ge") ) { /* Georgian syntax */
+ return(ast_say_number_full_ge(chan, num, ints, language, options, audiofd, ctrlfd));
}
/* Default to english */
@@ -2707,6 +2717,8 @@ static int say_date(struct ast_channel *chan, time_t t, const char *ints, const
return(ast_say_date_pt(chan, t, ints, lang));
} else if (!strcasecmp(lang, "gr") ) { /* Greek syntax */
return(ast_say_date_gr(chan, t, ints, lang));
+ } else if (!strcasecmp(lang, "ge") ) { /* Georgian syntax */
+ return(ast_say_date_ge(chan, t, ints, lang));
}
/* Default to English */
@@ -5466,6 +5478,8 @@ static int say_time(struct ast_channel *chan, time_t t, const char *ints, const
return(ast_say_time_tw(chan, t, ints, lang));
} else if (!strcasecmp(lang, "gr") ) { /* Greek syntax */
return(ast_say_time_gr(chan, t, ints, lang));
+ } else if (!strcasecmp(lang, "ge") ) { /* Georgian syntax */
+ return(ast_say_time_ge(chan, t, ints, lang));
}
/* Default to English */
@@ -5685,6 +5699,8 @@ static int say_datetime(struct ast_channel *chan, time_t t, const char *ints, co
return(ast_say_datetime_tw(chan, t, ints, lang));
} else if (!strcasecmp(lang, "gr") ) { /* Greek syntax */
return(ast_say_datetime_gr(chan, t, ints, lang));
+ } else if (!strcasecmp(lang, "ge") ) { /* Georgian syntax */
+ return(ast_say_datetime_ge(chan, t, ints, lang));
}
/* Default to English */
@@ -5968,6 +5984,8 @@ static int say_datetime_from_now(struct ast_channel *chan, time_t t, const char
return(ast_say_datetime_from_now_fr(chan, t, ints, lang));
} else if (!strcasecmp(lang, "pt") || !strcasecmp(lang, "pt_BR")) { /* Portuguese syntax */
return(ast_say_datetime_from_now_pt(chan, t, ints, lang));
+ } else if (!strcasecmp(lang, "ge") ) { /* Georgian syntax */
+ return(ast_say_datetime_from_now_ge(chan, t, ints, lang));
}
/* Default to English */
@@ -6536,6 +6554,377 @@ static int ast_say_date_with_format_gr(struct ast_channel *chan, time_t time, co
return res;
}
+
+
+
+/*********************************** Georgian Support ***************************************/
+
+
+/*
+ Convert a number into a semi-localized string. Only for Georgian.
+ res must be of at least 256 bytes, preallocated.
+ The output corresponds to Georgian spoken numbers, so
+ it may be either converted to real words by applying a direct conversion
+ table, or played just by substituting the entities with played files.
+
+ Output may consist of the following tokens (separated by spaces):
+ 0, minus.
+ 1-9, 1_-9_. (erti, ori, sami, otxi, ... . erti, or, sam, otx, ...).
+ 10-19.
+ 20, 40, 60, 80, 20_, 40_, 60_, 80_. (oci, ormoci, ..., ocda, ormocda, ...).
+ 100, 100_, 200, 200_, ..., 900, 900_. (asi, as, orasi, oras, ...).
+ 1000, 1000_. (atasi, atas).
+ 1000000, 1000000_. (milioni, milion).
+ 1000000000, 1000000000_. (miliardi, miliard).
+
+ To be able to play the sounds, each of the above tokens needs
+ a corresponding sound file. (e.g. 200_.gsm).
+*/
+static char* ast_translate_number_ge(int num, char* res, int res_len)
+{
+ char buf[256];
+ int digit = 0;
+ int remainder = 0;
+
+
+ if (num < 0) {
+ strncat(res, "minus ", res_len - strlen(res) - 1);
+ if ( num > INT_MIN ) {
+ num = -num;
+ } else {
+ num = 0;
+ }
+ }
+
+
+ /* directly read the numbers */
+ if (num <= 20 || num == 40 || num == 60 || num == 80 || num == 100) {
+ snprintf(buf, sizeof(buf), "%d", num);
+ strncat(res, buf, res_len - strlen(res) - 1);
+ return res;
+ }
+
+
+ if (num < 40) { /* ocda... */
+ strncat(res, "20_ ", res_len - strlen(res) - 1);
+ return ast_translate_number_ge(num - 20, res, res_len);
+ }
+
+ if (num < 60) { /* ormocda... */
+ strncat(res, "40_ ", res_len - strlen(res) - 1);
+ return ast_translate_number_ge(num - 40, res, res_len);
+ }
+
+ if (num < 80) { /* samocda... */
+ strncat(res, "60_ ", res_len - strlen(res) - 1);
+ return ast_translate_number_ge(num - 60, res, res_len);
+ }
+
+ if (num < 100) { /* otxmocda... */
+ strncat(res, "80_ ", res_len - strlen(res) - 1);
+ return ast_translate_number_ge(num - 80, res, res_len);
+ }
+
+
+ if (num < 1000) { /* as, oras, samas, ..., cxraas. asi, orasi, ..., cxraasi. */
+ remainder = num % 100;
+ digit = (num - remainder) / 100;
+
+ if (remainder == 0) {
+ snprintf(buf, sizeof(buf), "%d", num);
+ strncat(res, buf, res_len - strlen(res) - 1);
+ return res;
+ } else {
+ snprintf(buf, sizeof(buf), "%d_ ", digit*100);
+ strncat(res, buf, res_len - strlen(res) - 1);
+ return ast_translate_number_ge(remainder, res, res_len);
+ }
+ }
+
+
+ if (num == 1000) {
+ strncat(res, "1000", res_len - strlen(res) - 1);
+ return res;
+ }
+
+
+ if (num < 1000000) {
+ remainder = num % 1000;
+ digit = (num - remainder) / 1000;
+
+ if (remainder == 0) {
+ ast_translate_number_ge(digit, res, res_len);
+ strncat(res, " 1000", res_len - strlen(res) - 1);
+ return res;
+ }
+
+ if (digit == 1) {
+ strncat(res, "1000_ ", res_len - strlen(res) - 1);
+ return ast_translate_number_ge(remainder, res, res_len);
+ }
+
+ ast_translate_number_ge(digit, res, res_len);
+ strncat(res, " 1000_ ", res_len - strlen(res) - 1);
+ return ast_translate_number_ge(remainder, res, res_len);
+
+ }
+
+
+ if (num == 1000000) {
+ strncat(res, "1 1000000", res_len - strlen(res) - 1);
+ return res;
+ }
+
+
+ if (num < 1000000000) {
+ remainder = num % 1000000;
+ digit = (num - remainder) / 1000000;
+
+ if (remainder == 0) {
+ ast_translate_number_ge(digit, res, res_len);
+ strncat(res, " 1000000", res_len - strlen(res) - 1);
+ return res;
+ }
+
+ ast_translate_number_ge(digit, res, res_len);
+ strncat(res, " 1000000_ ", res_len - strlen(res) - 1);
+ return ast_translate_number_ge(remainder, res, res_len);
+
+ }
+
+
+ if (num == 1000000000) {
+ strncat(res, "1 1000000000", res_len - strlen(res) - 1);
+ return res;
+ }
+
+
+ if (num > 1000000000) {
+ remainder = num % 1000000000;
+ digit = (num - remainder) / 1000000000;
+
+ if (remainder == 0) {
+ ast_translate_number_ge(digit, res, res_len);
+ strncat(res, " 1000000000", res_len - strlen(res) - 1);
+ return res;
+ }
+
+ ast_translate_number_ge(digit, res, res_len);
+ strncat(res, " 1000000000_ ", res_len - strlen(res) - 1);
+ return ast_translate_number_ge(remainder, res, res_len);
+
+ }
+
+ return res;
+
+}
+
+
+
+/*! \brief ast_say_number_full_ge: Georgian syntax */
+static int ast_say_number_full_ge(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
+{
+ int res = 0;
+ char fn[512] = "";
+ if (!num)
+ return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd);
+
+
+ ast_translate_number_ge(num, fn, 512);
+
+
+ char* s = 0;
+ const char* remainder = fn;
+
+ while (res == 0 && (s = strstr(remainder, " "))) {
+ size_t len = s - remainder;
+ char* new_string = malloc(len + 1 + strlen("digits/"));
+
+ sprintf(new_string, "digits/");
+ strncat(new_string, remainder, len); /* we can't sprintf() it, it's not null-terminated. */
+/* new_string[len + strlen("digits/")] = '\0'; */
+
+ if (!ast_streamfile(chan, new_string, language)) {
+ if ((audiofd > -1) && (ctrlfd > -1))
+ res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
+ else
+ res = ast_waitstream(chan, ints);
+ }
+ ast_stopstream(chan);
+
+ free(new_string);
+
+ remainder = s + 1; /* position just after the found space char. */
+ while(*remainder == ' ') /* skip multiple spaces */
+ remainder++;
+ }
+
+
+ /* the last chunk. */
+ if (res == 0 && *remainder) {
+
+ char* new_string = malloc(strlen(remainder) + 1 + strlen("digits/"));
+ sprintf(new_string, "digits/%s", remainder);
+
+ if (!ast_streamfile(chan, new_string, language)) {
+ if ((audiofd > -1) && (ctrlfd > -1))
+ res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
+ else
+ res = ast_waitstream(chan, ints);
+ }
+ ast_stopstream(chan);
+
+ free(new_string);
+
+ }
+
+
+ return res;
+
+}
+
+
+
+/*
+Georgian support for date/time requires the following files (*.gsm):
+
+mon-1, mon-2, ... (ianvari, tebervali, ...)
+day-1, day-2, ... (orshabati, samshabati, ...)
+saati_da
+tsuti
+tslis
+*/
+
+
+
+/* Georgian syntax. e.g. "oriatas xuti tslis 5 noemberi". */
+static int ast_say_date_ge(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
+{
+ struct tm tm;
+ char fn[256];
+ int res = 0;
+ ast_localtime(&t,&tm,NULL);
+
+ if (!res)
+ res = ast_say_number(chan, tm.tm_year + 1900, ints, lang, (char *) NULL);
+
+ if (!res) {
+ snprintf(fn, sizeof(fn), "digits/tslis %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)
+ 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);
+ }
+ return res;
+
+}
+
+
+
+
+
+/* Georgian syntax. e.g. "otxi saati da eqvsi tsuti" */
+static int ast_say_time_ge(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
+{
+ struct tm tm;
+ int res = 0;
+ localtime_r(&t,&tm);
+
+ res = ast_say_number(chan, tm.tm_hour, ints, lang, (char*)NULL);
+ if (!res) {
+ res = ast_streamfile(chan, "digits/saati_da", lang);
+ if (!res)
+ res = ast_waitstream(chan, ints);
+ }
+
+ if (tm.tm_min) {
+ if (!res) {
+ res = ast_say_number(chan, tm.tm_min, ints, lang, (char*)NULL);
+
+ if (!res) {
+ res = ast_streamfile(chan, "digits/tsuti", lang);
+ if (!res)
+ res = ast_waitstream(chan, ints);
+ }
+ }
+ }
+ return res;
+}
+
+
+
+/* Georgian syntax. Say date, then say time. */
+static int ast_say_datetime_ge(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
+{
+ struct tm tm;
+ int res = 0;
+ localtime_r(&t,&tm);
+ res = ast_say_date(chan, t, ints, lang);
+ if (!res)
+ ast_say_time(chan, t, ints, lang);
+ return res;
+
+}
+
+
+
+
+/* Georgian syntax */
+static int ast_say_datetime_from_now_ge(struct ast_channel *chan, time_t t, const char *ints, const 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) {
+ snprintf(fn, sizeof(fn), "digits/mon-%d", tm.tm_mon);
+ res = ast_streamfile(chan, fn, lang);
+ if (!res)
+ res = ast_waitstream(chan, ints);
+ }
+
+ } else if (daydiff) {
+ /* Just what day of the week */
+ 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);
+ }
+ } /* Otherwise, it was today */
+ if (!res)
+ res = ast_say_time(chan, t, ints, lang);
+
+ return res;
+}
+
+
+
/*
* remap the 'say' functions to use those in this file
*/