Skip to content
Snippets Groups Projects
say.c 186 KiB
Newer Older
  • Learn to ignore specific revisions
  • 			snprintf(fn, sizeof(fn), "digits/minus");
    			if ( num > INT_MIN ) {
    				num = -num;
    			} else {
    				num = 0;
    			}	
    		} else if (playa) {
    
    			snprintf(fn, sizeof(fn), "digits/and");
    
    		} else if (num == 1) {
    			if (mf < 0)
    				snprintf(fn, sizeof(fn), "digits/%dF", num);
    
    			else if (mf > 0)
    				snprintf(fn, sizeof(fn), "digits/%dM", num);
    			else 
    
    				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 < 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/100");
    
    		} else if (num < 200) {
    			snprintf(fn, sizeof(fn), "digits/100-and");
    			num -= 100;
    
    		} else {
    			if (num < 1000) {
    				snprintf(fn, sizeof(fn), "digits/%d", (num/100)*100);
    				num -= ((num/100)*100);
    
    			} else if (num < 2000) {
    				num = num % 1000;
    				snprintf(fn, sizeof(fn), "digits/thousand");
    
    					res = ast_say_number_full_es(chan, num / 1000, ints, language, options, audiofd, ctrlfd);
    
    					snprintf(fn, sizeof(fn), "digits/thousand");
    
    				} else {
    					if (num < 2147483640) {
    						if ((num/1000000) == 1) {
    
    							res = ast_say_number_full_es(chan, num / 1000000, ints, language, "M", audiofd, ctrlfd);
    							if (res)
    								return res;
    							snprintf(fn, sizeof(fn), "digits/million");
    
    							res = ast_say_number_full_es(chan, num / 1000000, ints, language, options, audiofd, ctrlfd);
    							if (res)
    								return res;
    							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 (!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);
    
    /*! \brief  ast_say_number_full_fr: French syntax */
    
    /* 	Extra sounds needed:
     	1F: feminin 'une'
     	et: 'and' */
    
    static int ast_say_number_full_fr(struct ast_channel *chan, int num, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
    
    	int mf = 1;                            /* +1 = male; -1 = female */
    
    	char fn[256] = "";
    	if (!num) 
    		return ast_say_digits_full(chan, 0,ints, language, audiofd, ctrlfd);
    
    	
    	if (options && !strncasecmp(options, "f",1))
    		mf = -1;
    
    
    	while(!res && (num || playh || playa)) {
    
    		if (num < 0) {
    			snprintf(fn, sizeof(fn), "digits/minus");
    			if ( num > INT_MIN ) {
    				num = -num;
    			} else {
    				num = 0;
    			}	
    		} else if (playh) {
    
    			snprintf(fn, sizeof(fn), "digits/hundred");
    			playh = 0;
    		} else if (playa) {
    			snprintf(fn, sizeof(fn), "digits/et");
    			playa = 0;
    
    		} else if (num == 1) {
    			if (mf < 0)
    				snprintf(fn, sizeof(fn), "digits/%dF", num);
    			else
    				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 < 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, options, 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, options, 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 > -1) && (ctrlfd > -1))
    
    					res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
    				else
    					res = ast_waitstream(chan, ints);
    			}
    			ast_stopstream(chan);
    		}
    	}
    	return res;
    }
    
    
    /*! \brief  ast_say_number_full_he: Hebrew syntax */
    
    /* 	Extra sounds needed:
     	1F: feminin 'one'
    	ve: 'and'
    	2hundred: 2 hundred
    	2thousands: 2 thousand 
    	thousands: plural of 'thousand'
    	3sF 'Smichut forms (female)
    	4sF
    	5sF
    	6sF
    	7sF
    	8sF
    	9sF
    	3s 'Smichut' forms (male)
    	4s
    	5s
    	6s
    	7s
    	9s
    	10s
    	11s
    	12s
    	13s
    	14s
    	15s
    	16s
    	17s
    	18s
    	19s
    
    TODO: 've' should sometimed be 'hu':
    * before 'shtaym' (2, F)
    * before 'shnaym' (2, M)
    * before 'shlosha' (3, M)
    * before 'shmone' (8, M)
    * before 'shlosim' (30)
    * before 'shmonim' (80)
    
    What about:
    'sheva' (7, F)?
    'tesha' (9, F)?
    */
    #define SAY_NUM_BUF_SIZE 256
    static int ast_say_number_full_he(struct ast_channel *chan, int num, 
        const char *ints, const char *language, const char *options, 
        int audiofd, int ctrlfd)
    {
    	int res = 0;
    	int state = 0; /* no need to save anything */
    	int mf = 1;    /* +1 = Masculin; -1 = Feminin */
    	char fn[SAY_NUM_BUF_SIZE] = "";
    	ast_verbose(VERBOSE_PREFIX_3 "ast_say_digits_full: started. "
    		"num: %d, options=\"%s\"\n",
    		num, options
    	);
    	if (!num) 
    		return ast_say_digits_full(chan, 0,ints, language, audiofd, ctrlfd);
    	
    	if (options && !strncasecmp(options, "f",1))
    		mf = -1;
    
    	/* Do we have work to do? */
    	while(!res && (num || (state>0) ))  {
    		/* first type of work: play a second sound. In this loop
    		 * we can only play one sound file at a time. Thus playing 
    		 * a second one requires repeating the loop just for the 
    		 * second file. The variable 'state' remembers where we were.
    		 * state==0 is the normal mode and it means that we continue
    		 * to check if the number num has yet anything left.
    		 */
    		ast_verbose(VERBOSE_PREFIX_3 "ast_say_digits_full: num: %d, "
    			"state=%d, options=\"%s\", mf=%d\n",
    			num, state, options, mf
    		);
    		if (state==1) {
    			snprintf(fn, sizeof(fn), "digits/hundred");
    			state = 0;
    		} else if (state==2) {
    			snprintf(fn, sizeof(fn), "digits/ve");
    			state = 0;
    		} else if (state==3) {
    			snprintf(fn, sizeof(fn), "digits/thousands");
    			state=0;
    		} else if (num <21) {
    			if (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);
    			num = num % 10;
    			if (num>0) state=2;
    		} else if (num < 200) {
    			snprintf(fn, sizeof(fn), "digits/hundred");
    			num = num - 100;
    		} else if (num < 300) {
    			snprintf(fn, sizeof(fn), "digits/hundred");
    			num = num - 100;
    		} else if (num < 1000) {
    			snprintf(fn, sizeof(fn), "digits/%d", (num/100));
    			state=1;
    			num = num % 100;
    		} else if (num < 2000) {
    			snprintf(fn, sizeof(fn), "digits/thousand");
    			num = num - 1000;
    		} else if (num < 3000) {
    			snprintf(fn, sizeof(fn), "digits/2thousand");
    			num = num - 2000;
                            if (num>0) state=2;
    		} else if (num < 20000) {
    			snprintf(fn, sizeof(fn), "digits/%ds",(num/1000));
    			num = num % 1000;
    			state=3;
    		} else if (num < 1000000) {
    			res = ast_say_number_full_he(chan, num / 1000, ints, language, options, audiofd, ctrlfd);
    			if (res)
    				return res;
    			snprintf(fn, sizeof(fn), "digits/thousand");
    			num = num % 1000;
    		} else	if (num < 1000000000) {
    			res = ast_say_number_full_he(chan, num / 1000000, ints, language, options, 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 > -1) && (ctrlfd > -1))
    					res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
    				else
    					res = ast_waitstream(chan, ints);
    			}
    			ast_stopstream(chan);
    		}
    	}
    	return res;
    }
    
    
    /*! \brief  ast_say_number_full_it:  Italian */
    
    static int ast_say_number_full_it(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd)
    
    	int res = 0;
    	int playh = 0;
    	int tempnum = 0;
    	char fn[256] = "";
    
    		return ast_say_digits_full(chan, 0,ints, language, audiofd, ctrlfd);
    
    		/*
    		Italian support
    
    
    		Like english, numbers up to 20 are a single 'word', and others
    
    		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
    
    		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.
    		
    
    		1000 is one thousand in en, 2000 is two thousand.
    		In it we have 1000 = mille , 2000 = 2 mila 
    
    		For million(s) we use the plural, if more than one
    		Also, one million is abbreviated in it, like on-million,
    		or 'un milione', not 'uno milione'.
    		So the right file is provided.
    		*/
    
    
    			if (num < 0) {
    				snprintf(fn, sizeof(fn), "digits/minus");
    				if ( num > INT_MIN ) {
    					num = -num;
    				} else {
    					num = 0;
    				}	
    			} else 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_it(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_it(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 > -1) && (ctrlfd > -1))
    
    						res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
    					else
    						res = ast_waitstream(chan, ints);
    				}
    				ast_stopstream(chan);
    			}
    		}
    	return res;
    
    /*! \brief  ast_say_number_full_nl: dutch syntax */
    
    static int ast_say_number_full_nl(struct ast_channel *chan, int num, const char *ints, const char *language, int audiofd, int ctrlfd)
    
    	char fn[256] = "";
    	if (!num) 
    		return ast_say_digits_full(chan, 0,ints, language, audiofd, ctrlfd);
    
    		if (num < 0) {
    			snprintf(fn, sizeof(fn), "digits/minus");
    			if ( num > INT_MIN ) {
    				num = -num;
    			} else {
    				num = 0;
    			}	
    		} else 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 > -1) && (ctrlfd > -1))
    
    					res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
    				else
    					res = ast_waitstream(chan, ints);
    			}
    			ast_stopstream(chan);
    		}
    
    /*! \brief  ast_say_number_full_no: Norwegian syntax */
    
    /* New files:
     In addition to American English, the following sounds are required:  "and", "1N"
     */
    
    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)
    
    {
    	int res = 0;
    	int playh = 0;
    	int playa = 0;
    
    	int cn = 1;		/* +1 = commune; -1 = neuter */
    
    	char fn[256] = "";
    	
    	if (!num) 
    		return ast_say_digits_full(chan, 0,ints, language, audiofd, ctrlfd);
    	
    	if (options && !strncasecmp(options, "n",1)) cn = -1;
    
    	while(!res && (num || playh || playa )) {
    		/* The grammar for Norwegian numbers is the same as for English except
    		* for the following:
    
    		* - 1 exists in both commune ("en", file "1") and neuter ("ett", file "1N")
    
    		*   "and" before the last two digits, i.e. 2034 is "two thousand and
    		*   thirty-four" and 1000012 is "one million and twelve".
    		*/
    
    		if (num < 0) {
    			snprintf(fn, sizeof(fn), "digits/minus");
    			if ( num > INT_MIN ) {
    				num = -num;
    			} else {
    				num = 0;
    			}	
    		} else 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) {
    			snprintf(fn, sizeof(fn), "digits/%d", (num /10) * 10);
    			num -= ((num / 10) * 10);
    		} 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_no(chan, num / 1000, ints, language, "n", audiofd, ctrlfd);
    			if (res)
    				return res;
    			snprintf(fn, sizeof(fn), "digits/thousand");
    			num = num % 1000;
    			if (num && num < 100)
    				playa++;
    		} else 	if (num < 1000000000) {
    				int millions = num / 1000000;
    				res = ast_say_number_full_no(chan, millions, ints, language, "c", audiofd, ctrlfd);
    				if (res)
    					return res;
    				snprintf(fn, sizeof(fn), "digits/million");
    				num = num % 1000000;
    				if (num && num < 100)
    					playa++;
    		} 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 > -1) && (ctrlfd > -1)) 
    
    					res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
    				else  
    					res = ast_waitstream(chan, ints);
    			}
    			ast_stopstream(chan);
    		}
    	}
    	return res;
    }
    
    
    typedef struct {  
    	char *separator_dziesiatek;
    	char *cyfry[10];
    	char *cyfry2[10];
    	char *setki[10];
    	char *dziesiatki[10];
    	char *nastki[10];  
    	char *rzedy[3][3];
    } odmiana;
    
    static char *pl_rzad_na_tekst(odmiana *odm, int i, int rzad)
    {
    	if (rzad==0)
    		return "";
     
    	if (i==1)
    		return odm->rzedy[rzad - 1][0];
    	if ((i > 21 || i < 11) &&  i%10 > 1 && i%10 < 5)
    		return odm->rzedy[rzad - 1][1];
    	else
    		return odm->rzedy[rzad - 1][2];
    }
    
    static char* pl_append(char* buffer, char* str)
    {
    	strcpy(buffer, str);
    	buffer += strlen(str); 
    	return buffer;
    }
    
    
    static void pl_odtworz_plik(struct ast_channel *chan, const char *language, int audiofd, int ctrlfd, const char *ints, char *fn)
    
    {    
    	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))
    
    			ast_waitstream_full(chan, ints, audiofd, ctrlfd);
    		else
    			ast_waitstream(chan, ints);
    	}
    	ast_stopstream(chan);
    }
    
    
    static void powiedz(struct ast_channel *chan, const char *language, int audiofd, int ctrlfd, const char *ints, odmiana *odm, int rzad, int i)
    
    {
    	/* Initialise variables to allow compilation on Debian-stable, etc */
    	int m1000E6 = 0;
    	int i1000E6 = 0;
    	int m1000E3 = 0;
    	int i1000E3 = 0;
    	int m1000 = 0;
    	int i1000 = 0;
    	int m100 = 0;
    	int i100 = 0;
    	
    	if (i == 0 && rzad > 0) { 
    		return;
    	}
    	if (i == 0) {
    		pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, odm->cyfry[0]);
    	}
    
    	m1000E6 = i % 1000000000;
    	i1000E6 = i / 1000000000;
    
    	powiedz(chan, language, audiofd, ctrlfd, ints, odm, rzad+3, i1000E6);
    
    	m1000E3 = m1000E6 % 1000000;
    	i1000E3 = m1000E6 / 1000000;
    
    	powiedz(chan, language, audiofd, ctrlfd, ints, odm, rzad+2, i1000E3);
    
    	m1000 = m1000E3 % 1000;
    	i1000 = m1000E3 / 1000;
    
    	powiedz(chan, language, audiofd, ctrlfd, ints, odm, rzad+1, i1000);
    
    	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) {
    		pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, odm->dziesiatki[m100 / 10]);
    	} else if (m100 <= 19 ) {
    		pl_odtworz_plik(chan, language, audiofd, ctrlfd, ints, odm->nastki[m100 % 10]);
    	} else if (m100 != 0) {
    		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);  
    			b = 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));
    	}
    }
    
    
    /* ast_say_number_full_pl: Polish syntax */
    
    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)
    
    /*
    Sounds needed:
    0		zero
    1		jeden
    10		dziesiec
    100		sto
    1000		tysiac
    1000000		milion
    1000000000	miliard
    1000000000.2	miliardy
    1000000000.5	miliardow
    1000000.2	miliony
    1000000.5	milionow
    1000.2		tysiace
    1000.5		tysiecy
    100m		stu
    10m		dziesieciu
    11		jedenascie
    11m		jedenastu
    12		dwanascie
    12m		dwunastu
    13		trzynascie
    13m		trzynastu
    14		czternascie
    14m		czternastu
    15		pietnascie
    15m		pietnastu
    16		szesnascie
    16m		szesnastu
    17		siedemnascie
    17m		siedemnastu
    18		osiemnascie
    18m		osiemnastu
    19		dziewietnascie
    19m		dziewietnastu
    1z		jedna
    2		dwie
    20		dwadziescia
    200		dwiescie
    200m		dwustu
    20m		dwudziestu
    2-1m		dwaj
    2-2m		dwoch
    2z		dwie
    3		trzy
    30		trzydziesci
    300		trzysta
    300m		trzystu
    30m		trzydziestu
    3-1m		trzej
    3-2m		trzech
    4		cztery
    40		czterdziesci
    400		czterysta
    400m		czterystu
    40m		czterdziestu
    4-1m		czterej
    4-2m		czterech
    5		piec
    50		piecdziesiat
    500		piecset
    500m		pieciuset
    50m		piedziesieciu
    5m		pieciu
    6		szesc
    60		szescdziesiat
    600		szescset
    600m		szesciuset
    60m		szescdziesieciu
    6m		szesciu
    7		siedem
    70		siedemdziesiat
    700		siedemset
    700m		siedmiuset
    70m		siedemdziesieciu
    7m		siedmiu
    8		osiem
    80		osiemdziesiat
    800		osiemset
    800m		osmiuset
    80m		osiemdziesieciu
    8m		osmiu
    9		dziewiec
    90		dziewiecdziesiat
    900		dziewiecset
    900m		dziewieciuset
    90m		dziewiedziesieciu
    9m		dziewieciu
    and combinations of eg.: 20_1, 30m_3m, etc...
    
    */
    {
    	char *zenski_cyfry[] = {"0","1z", "2z", "3", "4", "5", "6", "7", "8", "9"};
    
    	char *zenski_cyfry2[] = {"0","1", "2z", "3", "4", "5", "6", "7", "8", "9"};
    
    	char *meski_cyfry[] = {"0","1", "2-1m", "3-1m", "4-1m", "5m",  /*"2-1mdwaj"*/ "6m", "7m", "8m", "9m"};
    
    	char *meski_cyfry2[] = {"0","1", "2-2m", "3-2m", "4-2m", "5m", "6m", "7m", "8m", "9m"};
    
    	char *meski_setki[] = {"", "100m", "200m", "300m", "400m", "500m", "600m", "700m", "800m", "900m"};
    
    	char *meski_dziesiatki[] = {"", "10m", "20m", "30m", "40m", "50m", "60m", "70m", "80m", "90m"};
    
    	char *meski_nastki[] = {"", "11m", "12m", "13m", "14m", "15m", "16m", "17m", "18m", "19m"};
    
    	char *nijaki_cyfry[] = {"0","1", "2", "3", "4", "5", "6", "7", "8", "9"};
    
    	char *nijaki_cyfry2[] = {"0","1", "2", "3", "4", "5", "6", "7", "8", "9"};
    
    	char *nijaki_setki[] = {"", "100", "200", "300", "400", "500", "600", "700", "800", "900"};
    
    	char *nijaki_dziesiatki[] = {"", "10", "20", "30", "40", "50", "60", "70", "80", "90"};
    
    	char *nijaki_nastki[] = {"", "11", "12", "13", "14", "15", "16", "17", "18", "19"};
    
    	char *rzedy[][3] = { {"1000", "1000.2", "1000.5"}, {"1000000", "1000000.2", "1000000.5"}, {"1000000000", "1000000000.2", "1000000000.5"}}; 
    
    	/* Initialise variables to allow compilation on Debian-stable, etc */
    	odmiana *o;
    
    	static odmiana *odmiana_nieosobowa = NULL; 
    	static odmiana *odmiana_meska = NULL; 
    	static odmiana *odmiana_zenska = NULL; 
    
    	if (odmiana_nieosobowa == NULL) {
    		odmiana_nieosobowa = (odmiana *) malloc(sizeof(odmiana));
    
    		odmiana_nieosobowa->separator_dziesiatek = "_";
    
    		memcpy(odmiana_nieosobowa->cyfry, nijaki_cyfry, sizeof(odmiana_nieosobowa->cyfry));
    		memcpy(odmiana_nieosobowa->cyfry2, nijaki_cyfry2, sizeof(odmiana_nieosobowa->cyfry));
    		memcpy(odmiana_nieosobowa->setki, nijaki_setki, sizeof(odmiana_nieosobowa->setki));
    		memcpy(odmiana_nieosobowa->dziesiatki, nijaki_dziesiatki, sizeof(odmiana_nieosobowa->dziesiatki));
    		memcpy(odmiana_nieosobowa->nastki, nijaki_nastki, sizeof(odmiana_nieosobowa->nastki));
    		memcpy(odmiana_nieosobowa->rzedy, rzedy, sizeof(odmiana_nieosobowa->rzedy));
    	}
    
    	if (odmiana_zenska == NULL) {
    		odmiana_zenska = (odmiana *) malloc(sizeof(odmiana));
    
    
    		odmiana_zenska->separator_dziesiatek = " ";
    
    
    		memcpy(odmiana_zenska->cyfry, zenski_cyfry, sizeof(odmiana_zenska->cyfry));
    		memcpy(odmiana_zenska->cyfry2, zenski_cyfry2, sizeof(odmiana_zenska->cyfry));
    		memcpy(odmiana_zenska->setki, nijaki_setki, sizeof(odmiana_zenska->setki));
    		memcpy(odmiana_zenska->dziesiatki, nijaki_dziesiatki, sizeof(odmiana_zenska->dziesiatki));
    		memcpy(odmiana_zenska->nastki, nijaki_nastki, sizeof(odmiana_zenska->nastki));
    		memcpy(odmiana_zenska->rzedy, rzedy, sizeof(odmiana_zenska->rzedy));
    	}
    
    	if (odmiana_meska == NULL) {
    		odmiana_meska = (odmiana *) malloc(sizeof(odmiana));
    
    
    		odmiana_meska->separator_dziesiatek = " ";
    
    
    		memcpy(odmiana_meska->cyfry, meski_cyfry, sizeof(odmiana_meska->cyfry));
    		memcpy(odmiana_meska->cyfry2, meski_cyfry2, sizeof(odmiana_meska->cyfry));
    		memcpy(odmiana_meska->setki, meski_setki, sizeof(odmiana_meska->setki));
    		memcpy(odmiana_meska->dziesiatki, meski_dziesiatki, sizeof(odmiana_meska->dziesiatki));
    		memcpy(odmiana_meska->nastki, meski_nastki, sizeof(odmiana_meska->nastki));
    		memcpy(odmiana_meska->rzedy, rzedy, sizeof(odmiana_meska->rzedy));
    	}
    
    	if (options) {
    		if (strncasecmp(options, "f", 1) == 0)
    			o = odmiana_zenska;
    		else if (strncasecmp(options, "m", 1) == 0)
    			o = odmiana_meska;
    		else
    			o = odmiana_nieosobowa;
    	} else
    		o = odmiana_nieosobowa;
    
    
    	powiedz(chan, language, audiofd, ctrlfd, ints, o, 0, num);
    
    /* 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, const char *ints, const char *language, const char *options, int audiofd, int ctrlfd)
    
    	int mf = 1;                            /* +1 = male; -1 = female */
    
    	if (!num) 
    		return ast_say_digits_full(chan, 0,ints, language, audiofd, ctrlfd);
    
    
    	if (options && !strncasecmp(options, "f",1))
    		mf = -1;
    
    	while(!res && num ) {
    
    		if (num < 0) {
    			snprintf(fn, sizeof(fn), "digits/minus");
    			if ( num > INT_MIN ) {
    				num = -num;
    			} else {
    				num = 0;
    			}	
    		} else 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");