Index: say.c =================================================================== RCS file: /usr/cvsroot/asterisk/say.c,v retrieving revision 1.66 diff -u -r1.66 say.c --- say.c 12 Jul 2005 14:58:25 -0000 1.66 +++ say.c 27 Jul 2005 07:22:44 -0000 @@ -280,12 +280,13 @@ no - Norwegian pl - Polish pt - Portuguese + ru - Russian se - Swedish tw - Taiwanese Gender: For Some languages the numbers differ for gender and plural - Use the option argument 'f' for female, 'm' for male and 'n' for neuter in languages like Portuguese, French, Spanish and German. + Use the option argument 'f' for female, 'm' for male and 'n' for neuter in languages like Portuguese, French, Spanish, Russian and German. use the option argument 'c' is for commune and 'n' for neuter gender in nordic languages like Danish, Swedish and Norwegian. use the option argument 'p' for plural enumerations like in German @@ -329,6 +330,7 @@ static int ast_say_number_full_no(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_pl(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_pt(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_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_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_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); @@ -419,6 +421,8 @@ return(ast_say_number_full_pl(chan, num, ints, language, options, audiofd, ctrlfd)); } else if (!strcasecmp(language, "pt") ) { /* Portuguese syntax */ return(ast_say_number_full_pt(chan, num, ints, language, options, 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, "se") ) { /* Swedish syntax */ return(ast_say_number_full_se(chan, num, ints, language, options, audiofd, ctrlfd)); } else if (!strcasecmp(language, "tw")) { /* Taiwanese syntax */ @@ -2002,6 +2006,150 @@ } return res; } + + +/*--- additional files: + + n00 - 100,200,300,400, ... ,900 + 1f - one (in female gender) + 2f - two (in female gender) + 1m - one (in neutral gender) + thousand - (tysjacha) + thousands-i - (tysjachi) + thousands - (tysjach) + million - (million) + millions-a - (milliona) + millions-ov - (millionov) + +*/ + +/*--- structure for sound files names */ +typedef struct { + char *units[3][10]; + char *tens[9]; // tens (10,20 ... 90) + char *hundreds[9]; // thousans (100,200 ... 900) + char *secondten[9]; // 11-19 + char *rank[2][3]; // rank names +} ru_numbers; + +/*--- Send word to Asterisk stream */ +static int ru_stream_word (struct ast_channel *chan, const char *language, int audiofd, int ctrlfd, const char *ints, const char *fn) { + int res = 0; + char file_name[255] = "digits/"; + + strcat (file_name, fn); + ast_log (LOG_DEBUG, "Trying to play: %s\n", file_name); + if (!ast_streamfile (chan, file_name, 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; +} + +/*--- say number from 1 to 999 */ +static int ru_stream_triade (struct ast_channel *chan, const char *language, int audiofd, int ctrlfd, const char *ints, ru_numbers * odm, unsigned int num, int gender) { + int res = 0; + unsigned int units = num % 10; + unsigned int tens = (num / 10) % 10; + unsigned int hundreds = (num / 100) % 10; + if (hundreds > 0) { + res = ru_stream_word (chan, language, audiofd, ctrlfd, ints, odm->hundreds[hundreds-1]); + if (res) + return res; + } + if (tens > 0) { + if ((tens == 1) && (units != 0)) + return ru_stream_word (chan, language, audiofd, ctrlfd, ints, odm->secondten[units-1]); + res = ru_stream_word (chan, language, audiofd, ctrlfd, ints, odm->tens[tens-1]); + if (res) + return res; + } + if (units > 0) { + res = ru_stream_word (chan, language, audiofd, ctrlfd, ints, odm->units[gender][units]); + if (res) + return res; + } + return res; +} +/*--- ast_say_number_full_ru: Russian syntax */ +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) +{ + // Initialize arrays with sets of names for each gender; + // male, female or none + char *units[3][10] = {{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"}, + {"0", "1f", "2f","3", "4", "5", "6", "7", "8", "9"}, + {"0", "1m", "2", "3", "4", "5", "6", "7", "8", "9"}}; + char *tens[] = {"10", "20", "30", "40", "50", "60", "70", "80", "90"}; + char *hundreds[] = {"100", "200", "300", "400", "500", "600", "700", "800", "900"}; + char *secondten[] = {"11", "12", "13", "14", "15", "16", "17", "18", "19"}; + char *rank[2][3] = {{"1000a", "1000i", "1000"}, + {"1000000", "1000000a", "1000000ov"}}; + static ru_numbers *odm = NULL; + int i = 0,res = 0; + int n = num; + unsigned int arg = 0; + unsigned int part = 0; + unsigned int gender[] = {2,1,0}; + + if (odm == NULL) { + odm = (ru_numbers *) malloc (sizeof (ru_numbers)); + // Fill units array + memcpy(odm->units, units, sizeof (odm->units)); + memcpy(odm->tens, tens, sizeof (odm->tens)); + memcpy(odm->hundreds, hundreds, sizeof (odm->hundreds)); + memcpy(odm->secondten, secondten, sizeof (odm->secondten)); + memcpy(odm->rank, rank, sizeof (odm->rank)); + } + // Define gender to spoke + if (options) { + if (strncasecmp (options, "m", 1) == 0) + gender[0] = 0; + else if (strncasecmp (options, "f", 1) == 0) + gender[0] = 1; + else + gender[0] = 2; + } + // Spoke with selected gender + if (n == 0) + return ru_stream_word (chan, language, audiofd, ctrlfd, ints, odm->units[0][0]); + if (n < 0) { + res = ru_stream_word (chan, language, audiofd, ctrlfd, ints, "minus"); + if (res) + return res; + n = -1*n; + } + if (n >= 1000000000) { // 1,000,000,000 + ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num); + return -1; + } + for (i = 2; i >= 0; i--) { + part = (n /(int) pow(1000,i))%1000; + if (part == 0) // If triade is empty, skip + continue; + res = ru_stream_triade (chan, language, audiofd, ctrlfd, ints, odm, part, gender[i]); + if (res) + return res; + // if last triade, skip + if (i == 0) + continue; + // Stream the name of triade + arg = part % 100; + if (arg >= 11 && arg <=14) + arg = 2; + else { + arg %= 10; + arg = 2 - (arg >= 2 && arg <= 4) - (arg == 1)*2; + } + res = ru_stream_word (chan, language, audiofd, ctrlfd, ints, odm->rank[i - 1][arg]); + if (res) + return res; + } + return res; +} + /*--- ast_say_number_full_se: Swedish syntax */ 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)