Sun Feb 23 07:00:00 CET 2003
[asterisk/asterisk.git] / say.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * Say numbers and dates (maybe words one day too)
5  * 
6  * Copyright (C) 1999, Mark Spencer
7  *
8  * Mark Spencer <markster@linux-support.net>
9  *
10  * This program is free software, distributed under the terms of
11  * the GNU General Public License
12  */
13
14 #include <asterisk/file.h>
15 #include <asterisk/channel.h>
16 #include <asterisk/logger.h>
17 #include <asterisk/say.h>
18 #include <stdio.h>
19
20 int ast_say_digit_str(struct ast_channel *chan, char *fn2, char *ints, char *lang)
21 {
22         /* XXX Merge with full version? XXX */
23         char fn[256] = "";
24         int num = 0;
25         int res = 0;
26         while(fn2[num] && !res) {
27                 snprintf(fn, sizeof(fn), "digits/%c", fn2[num]);
28                 res = ast_streamfile(chan, fn, lang);
29                 if (!res) 
30                         res = ast_waitstream(chan, ints);
31                 ast_stopstream(chan);
32                 num++;
33         }
34         return res;
35 }
36
37 int ast_say_digit_str_full(struct ast_channel *chan, char *fn2, char *ints, char *lang, int audiofd, int ctrlfd)
38 {
39         char fn[256] = "";
40         int num = 0;
41         int res = 0;
42         while(fn2[num] && !res) {
43                 snprintf(fn, sizeof(fn), "digits/%c", fn2[num]);
44                 res = ast_streamfile(chan, fn, lang);
45                 if (!res) 
46                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
47                 ast_stopstream(chan);
48                 num++;
49         }
50         return res;
51 }
52
53 int ast_say_digits(struct ast_channel *chan, int num, char *ints, char *lang)
54 {
55         /* XXX Should I be merged with say_digits_full XXX */
56         char fn2[256];
57         snprintf(fn2, sizeof(fn2), "%d", num);
58         return ast_say_digit_str(chan, fn2, ints, lang);
59 }
60
61 int ast_say_digits_full(struct ast_channel *chan, int num, char *ints, char *lang, int audiofd, int ctrlfd)
62 {
63         char fn2[256];
64         snprintf(fn2, sizeof(fn2), "%d", num);
65         return ast_say_digit_str_full(chan, fn2, ints, lang, audiofd, ctrlfd);
66 }
67
68 int ast_say_number_full(struct ast_channel *chan, int num, char *ints, char *language, int audiofd, int ctrlfd)
69 {
70         int res = 0;
71         int playh = 0;
72         char fn[256] = "";
73         if (!num) 
74                 return ast_say_digits_full(chan, 0,ints, language, audiofd, ctrlfd);
75         if (0) {
76         /* XXX Only works for english XXX */
77         } else {
78                 /* Use english numbers */
79                 language = "en";
80                 while(!res && (num || playh)) {
81                         if (playh) {
82                                 snprintf(fn, sizeof(fn), "digits/hundred");
83                                 playh = 0;
84                         } else
85                         if (num < 20) {
86                                 snprintf(fn, sizeof(fn), "digits/%d", num);
87                                 num = 0;
88                         } else
89                         if (num < 100) {
90                                 snprintf(fn, sizeof(fn), "digits/%d", (num /10) * 10);
91                                 num -= ((num / 10) * 10);
92                         } else {
93                                 if (num < 1000){
94                                         snprintf(fn, sizeof(fn), "digits/%d", (num/100));
95                                         playh++;
96                                         num -= ((num / 100) * 100);
97                                 } else {
98                                         if (num < 1000000) {
99                                                 res = ast_say_number_full(chan, num / 1000, ints, language, audiofd, ctrlfd);
100                                                 if (res)
101                                                         return res;
102                                                 num = num % 1000;
103                                                 snprintf(fn, sizeof(fn), "digits/thousand");
104                                         } else {
105                                                 if (num < 1000000000) {
106                                                         res = ast_say_number_full(chan, num / 1000000, ints, language, audiofd, ctrlfd);
107                                                         if (res)
108                                                                 return res;
109                                                         num = num % 1000000;
110                                                         snprintf(fn, sizeof(fn), "digits/million");
111                                                 } else {
112                                                         ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num);
113                                                         res = -1;
114                                                 }
115                                         }
116                                 }
117                         }
118                         if (!res) {
119                                 res = ast_streamfile(chan, fn, language);
120                                 if (!res) 
121                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
122                                 ast_stopstream(chan);
123                         }
124                         
125                 }
126         }
127         return res;
128 }
129
130 int ast_say_number(struct ast_channel *chan, int num, char *ints, char *language)
131 {
132         /* XXX Should I be merged with ast_say_number_full XXX */
133         int res = 0;
134         int playh = 0;
135         char fn[256] = "";
136         if (!num) 
137                 return ast_say_digits(chan, 0,ints, language);
138         if (0) {
139         /* XXX Only works for english XXX */
140         } else {
141                 /* Use english numbers */
142                 language = "en";
143                 while(!res && (num || playh)) {
144                         if (playh) {
145                                 snprintf(fn, sizeof(fn), "digits/hundred");
146                                 playh = 0;
147                         } else
148                         if (num < 20) {
149                                 snprintf(fn, sizeof(fn), "digits/%d", num);
150                                 num = 0;
151                         } else
152                         if (num < 100) {
153                                 snprintf(fn, sizeof(fn), "digits/%d", (num /10) * 10);
154                                 num -= ((num / 10) * 10);
155                         } else {
156                                 if (num < 1000){
157                                         snprintf(fn, sizeof(fn), "digits/%d", (num/100));
158                                         playh++;
159                                         num -= ((num / 100) * 100);
160                                 } else {
161                                         if (num < 1000000) {
162                                                 res = ast_say_number(chan, num / 1000, ints, language);
163                                                 if (res)
164                                                         return res;
165                                                 num = num % 1000;
166                                                 snprintf(fn, sizeof(fn), "digits/thousand");
167                                         } else {
168                                                 if (num < 1000000000) {
169                                                         res = ast_say_number(chan, num / 1000000, ints, language);
170                                                         if (res)
171                                                                 return res;
172                                                         num = num % 1000000;
173                                                         snprintf(fn, sizeof(fn), "digits/million");
174                                                 } else {
175                                                         ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num);
176                                                         res = -1;
177                                                 }
178                                         }
179                                 }
180                         }
181                         if (!res) {
182                                 res = ast_streamfile(chan, fn, language);
183                                 if (!res) 
184                                         res = ast_waitstream(chan, ints);
185                                 ast_stopstream(chan);
186                         }
187                         
188                 }
189         }
190         return res;
191 }
192 int ast_say_date(struct ast_channel *chan, time_t t, char *ints, char *lang)
193 {
194         struct tm *tm;
195         char fn[256];
196         int res = 0;
197         tm = localtime(&t);
198         if (!tm) {
199                 ast_log(LOG_WARNING, "Unable to derive local time\n");
200                 return -1;
201         }
202         if (!res) {
203                 snprintf(fn, sizeof(fn), "digits/day-%d", tm->tm_wday);
204                 res = ast_streamfile(chan, fn, lang);
205                 if (!res)
206                         res = ast_waitstream(chan, ints);
207         }
208         if (!res) {
209                 snprintf(fn, sizeof(fn), "digits/mon-%d", tm->tm_mon);
210                 res = ast_streamfile(chan, fn, lang);
211                 if (!res)
212                         res = ast_waitstream(chan, ints);
213         }
214         if (!res)
215                 res = ast_say_number(chan, tm->tm_mday, ints, lang);
216
217         if (!res)
218                 res = ast_waitstream(chan, ints);
219         if (!res)
220                 res = ast_say_number(chan, tm->tm_year + 1900, ints, lang);
221         return res;
222 }
223
224 int ast_say_time(struct ast_channel *chan, time_t t, char *ints, char *lang)
225 {
226         struct tm *tm;
227         int res = 0;
228         int hour, pm=0;
229         tm = localtime(&t);
230         if (!tm) {
231                 ast_log(LOG_WARNING, "Unable to derive local time\n");
232                 return -1;
233         }
234         hour = tm->tm_hour;
235         if (!hour)
236                 hour = 12;
237         else if (hour == 12)
238                 pm = 1;
239         else if (hour > 12) {
240                 hour -= 12;
241                 pm = 1;
242         }
243         if (!res)
244                 res = ast_say_number(chan, hour, ints, lang);
245
246         if (tm->tm_min > 9) {
247                 if (!res)
248                         res = ast_say_number(chan, tm->tm_min, ints, lang);
249         } else if (tm->tm_min) {
250                 if (!res)
251                         res = ast_streamfile(chan, "digits/oh", lang);
252                 if (!res)
253                         res = ast_waitstream(chan, ints);
254                 if (!res)
255                         res = ast_say_number(chan, tm->tm_min, ints, lang);
256         } else {
257                 if (!res)
258                         res = ast_streamfile(chan, "digits/oclock", lang);
259                 if (!res)
260                         res = ast_waitstream(chan, ints);
261         }
262         if (pm) {
263                 if (!res)
264                         res = ast_streamfile(chan, "digits/p-m", lang);
265         } else {
266                 if (!res)
267                         res = ast_streamfile(chan, "digits/a-m", lang);
268         }
269         if (!res)
270                 res = ast_waitstream(chan, ints);
271         return res;
272 }
273
274 int ast_say_datetime(struct ast_channel *chan, time_t t, char *ints, char *lang)
275 {
276         struct tm *tm;
277         char fn[256];
278         int res = 0;
279         int hour, pm=0;
280         tm = localtime(&t);
281         if (!tm) {
282                 ast_log(LOG_WARNING, "Unable to derive local time\n");
283                 return -1;
284         }
285         if (!res) {
286                 snprintf(fn, sizeof(fn), "digits/day-%d", tm->tm_wday);
287                 res = ast_streamfile(chan, fn, lang);
288                 if (!res)
289                         res = ast_waitstream(chan, ints);
290         }
291         if (!res) {
292                 snprintf(fn, sizeof(fn), "digits/mon-%d", tm->tm_mon);
293                 res = ast_streamfile(chan, fn, lang);
294                 if (!res)
295                         res = ast_waitstream(chan, ints);
296         }
297         if (!res)
298                 res = ast_say_number(chan, tm->tm_mday, ints, lang);
299
300         hour = tm->tm_hour;
301         if (!hour)
302                 hour = 12;
303         else if (hour == 12)
304                 pm = 1;
305         else if (hour > 12) {
306                 hour -= 12;
307                 pm = 1;
308         }
309         if (!res)
310                 res = ast_say_number(chan, hour, ints, lang);
311
312         if (tm->tm_min > 9) {
313                 if (!res)
314                         res = ast_say_number(chan, tm->tm_min, ints, lang);
315         } else if (tm->tm_min) {
316                 if (!res)
317                         res = ast_streamfile(chan, "digits/oh", lang);
318                 if (!res)
319                         res = ast_waitstream(chan, ints);
320                 if (!res)
321                         res = ast_say_number(chan, tm->tm_min, ints, lang);
322         } else {
323                 if (!res)
324                         res = ast_streamfile(chan, "digits/oclock", lang);
325                 if (!res)
326                         res = ast_waitstream(chan, ints);
327         }
328         if (pm) {
329                 if (!res)
330                         res = ast_streamfile(chan, "digits/p-m", lang);
331         } else {
332                 if (!res)
333                         res = ast_streamfile(chan, "digits/a-m", lang);
334         }
335         if (!res)
336                 res = ast_waitstream(chan, ints);
337         if (!res)
338                 res = ast_say_number(chan, tm->tm_year + 1900, ints, lang);
339         return res;
340 }
341
342 int ast_say_datetime_from_now(struct ast_channel *chan, time_t t, char *ints, char *lang)
343 {
344         int res=0;
345         time_t nowt;
346         int daydiff;
347         struct tm *tm;
348         struct tm tm2;
349         struct tm *now;
350         char fn[256];
351
352         time(&nowt);
353
354         tm = localtime(&t);
355         if (!tm) {
356                 ast_log(LOG_WARNING, "Unable to derive local time\n");
357                 return -1;
358         }
359         memcpy(&tm2, tm, sizeof(struct tm));
360         tm = &tm2;
361         now = localtime(&nowt);
362         daydiff = now->tm_yday - tm->tm_yday;
363         if ((daydiff < 0) || (daydiff > 6)) {
364                 /* Day of month and month */
365                 if (!res) {
366                         snprintf(fn, sizeof(fn), "digits/mon-%d", tm->tm_mon);
367                         res = ast_streamfile(chan, fn, lang);
368                         if (!res)
369                                 res = ast_waitstream(chan, ints);
370                 }
371                 if (!res)
372                         res = ast_say_number(chan, tm->tm_mday, ints, lang);
373
374         } else if (daydiff) {
375                 /* Just what day of the week */
376                 if (!res) {
377                         snprintf(fn, sizeof(fn), "digits/day-%d", tm->tm_wday);
378                         res = ast_streamfile(chan, fn, lang);
379                         if (!res)
380                                 res = ast_waitstream(chan, ints);
381                 }
382         } /* Otherwise, it was today */
383         if (!res)
384                 res = ast_say_time(chan, t, ints, lang);
385         return res;
386 }
387