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