9cfdfc4a8cf66cae5436d57875e8b4b1734fe626
[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         char fn[256] = "";
23         int num = 0;
24         int res = 0;
25         while(fn2[num] && !res) {
26                 snprintf(fn, sizeof(fn), "digits/%c", fn2[num]);
27                 res = ast_streamfile(chan, fn, lang);
28                 if (!res) 
29                         res = ast_waitstream(chan, ints);
30                 ast_stopstream(chan);
31                 num++;
32         }
33         return res;
34 }
35
36 int ast_say_digits(struct ast_channel *chan, int num, char *ints, char *lang)
37 {
38         char fn2[256];
39         snprintf(fn2, sizeof(fn2), "%d", num);
40         return ast_say_digit_str(chan, fn2, ints, lang);
41 }
42 int ast_say_number(struct ast_channel *chan, int num, char *ints, char *language)
43 {
44         int res = 0;
45         int playh = 0;
46         char fn[256] = "";
47         if (!num) 
48                 return ast_say_digits(chan, 0,ints, language);
49         if (0) {
50         /* XXX Only works for english XXX */
51         } else {
52                 /* Use english numbers */
53                 language = "en";
54                 while(!res && (num || playh)) {
55                         if (playh) {
56                                 snprintf(fn, sizeof(fn), "digits/hundred");
57                                 playh = 0;
58                         } else
59                         if (num < 20) {
60                                 snprintf(fn, sizeof(fn), "digits/%d", num);
61                                 num = 0;
62                         } else
63                         if (num < 100) {
64                                 snprintf(fn, sizeof(fn), "digits/%d", (num /10) * 10);
65                                 num -= ((num / 10) * 10);
66                         } else {
67                                 if (num < 1000){
68                                         snprintf(fn, sizeof(fn), "digits/%d", (num/100));
69                                         playh++;
70                                         num -= ((num / 100) * 100);
71                                 } else {
72                                         if (num < 1000000) {
73                                                 res = ast_say_number(chan, num / 1000, ints, language);
74                                                 if (res)
75                                                         return res;
76                                                 num = num % 1000;
77                                                 snprintf(fn, sizeof(fn), "digits/thousand");
78                                         } else {
79                                                 if (num < 1000000000) {
80                                                         res = ast_say_number(chan, num / 1000000, ints, language);
81                                                         if (res)
82                                                                 return res;
83                                                         num = num % 1000000;
84                                                         snprintf(fn, sizeof(fn), "digits/million");
85                                                 } else {
86                                                         ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num);
87                                                         res = -1;
88                                                 }
89                                         }
90                                 }
91                         }
92                         if (!res) {
93                                 res = ast_streamfile(chan, fn, language);
94                                 if (!res) 
95                                         res = ast_waitstream(chan, ints);
96                                 ast_stopstream(chan);
97                         }
98                         
99                 }
100         }
101         return res;
102 }
103
104 int ast_say_date(struct ast_channel *chan, time_t t, char *ints, char *lang)
105 {
106         struct tm *tm;
107         char fn[256];
108         int res = 0;
109         tm = localtime(&t);
110         if (!tm) {
111                 ast_log(LOG_WARNING, "Unable to derive local time\n");
112                 return -1;
113         }
114         if (!res) {
115                 snprintf(fn, sizeof(fn), "digits/day-%d", tm->tm_wday);
116                 res = ast_streamfile(chan, fn, lang);
117                 if (!res)
118                         res = ast_waitstream(chan, ints);
119         }
120         if (!res) {
121                 snprintf(fn, sizeof(fn), "digits/mon-%d", tm->tm_mon);
122                 res = ast_streamfile(chan, fn, lang);
123                 if (!res)
124                         res = ast_waitstream(chan, ints);
125         }
126         if (!res)
127                 res = ast_say_number(chan, tm->tm_mday, ints, lang);
128
129         if (!res)
130                 res = ast_waitstream(chan, ints);
131         if (!res)
132                 res = ast_say_number(chan, tm->tm_year + 1900, ints, lang);
133         return res;
134 }
135
136 int ast_say_time(struct ast_channel *chan, time_t t, char *ints, char *lang)
137 {
138         struct tm *tm;
139         int res = 0;
140         int hour, pm=0;
141         tm = localtime(&t);
142         if (!tm) {
143                 ast_log(LOG_WARNING, "Unable to derive local time\n");
144                 return -1;
145         }
146         hour = tm->tm_hour;
147         if (!hour)
148                 hour = 12;
149         else if (hour == 12)
150                 pm = 1;
151         else if (hour > 12) {
152                 hour -= 12;
153                 pm = 1;
154         }
155         if (!res)
156                 res = ast_say_number(chan, hour, ints, lang);
157
158         if (tm->tm_min > 9) {
159                 if (!res)
160                         res = ast_say_number(chan, tm->tm_min, ints, lang);
161         } else if (tm->tm_min) {
162                 if (!res)
163                         res = ast_streamfile(chan, "digits/oh", lang);
164                 if (!res)
165                         res = ast_waitstream(chan, ints);
166                 if (!res)
167                         res = ast_say_number(chan, tm->tm_min, ints, lang);
168         } else {
169                 if (!res)
170                         res = ast_streamfile(chan, "digits/oclock", lang);
171                 if (!res)
172                         res = ast_waitstream(chan, ints);
173         }
174         if (pm) {
175                 if (!res)
176                         res = ast_streamfile(chan, "digits/p-m", lang);
177         } else {
178                 if (!res)
179                         res = ast_streamfile(chan, "digits/a-m", lang);
180         }
181         if (!res)
182                 res = ast_waitstream(chan, ints);
183         return res;
184 }
185
186 int ast_say_datetime(struct ast_channel *chan, time_t t, char *ints, char *lang)
187 {
188         struct tm *tm;
189         char fn[256];
190         int res = 0;
191         int hour, pm=0;
192         tm = localtime(&t);
193         if (!tm) {
194                 ast_log(LOG_WARNING, "Unable to derive local time\n");
195                 return -1;
196         }
197         if (!res) {
198                 snprintf(fn, sizeof(fn), "digits/day-%d", tm->tm_wday);
199                 res = ast_streamfile(chan, fn, lang);
200                 if (!res)
201                         res = ast_waitstream(chan, ints);
202         }
203         if (!res) {
204                 snprintf(fn, sizeof(fn), "digits/mon-%d", tm->tm_mon);
205                 res = ast_streamfile(chan, fn, lang);
206                 if (!res)
207                         res = ast_waitstream(chan, ints);
208         }
209         if (!res)
210                 res = ast_say_number(chan, tm->tm_mday, ints, lang);
211
212         hour = tm->tm_hour;
213         if (!hour)
214                 hour = 12;
215         else if (hour == 12)
216                 pm = 1;
217         else if (hour > 12) {
218                 hour -= 12;
219                 pm = 1;
220         }
221         if (!res)
222                 res = ast_say_number(chan, hour, ints, lang);
223
224         if (tm->tm_min > 9) {
225                 if (!res)
226                         res = ast_say_number(chan, tm->tm_min, ints, lang);
227         } else if (tm->tm_min) {
228                 if (!res)
229                         res = ast_streamfile(chan, "digits/oh", lang);
230                 if (!res)
231                         res = ast_waitstream(chan, ints);
232                 if (!res)
233                         res = ast_say_number(chan, tm->tm_min, ints, lang);
234         } else {
235                 if (!res)
236                         res = ast_streamfile(chan, "digits/oclock", lang);
237                 if (!res)
238                         res = ast_waitstream(chan, ints);
239         }
240         if (pm) {
241                 if (!res)
242                         res = ast_streamfile(chan, "digits/p-m", lang);
243         } else {
244                 if (!res)
245                         res = ast_streamfile(chan, "digits/a-m", lang);
246         }
247         if (!res)
248                 res = ast_waitstream(chan, ints);
249         if (!res)
250                 res = ast_say_number(chan, tm->tm_year + 1900, ints, lang);
251         return res;
252 }
253
254 int ast_say_datetime_from_now(struct ast_channel *chan, time_t t, char *ints, char *lang)
255 {
256         int res=0;
257         time_t nowt;
258         int daydiff;
259         struct tm *tm;
260         struct tm tm2;
261         struct tm *now;
262         char fn[256];
263
264         time(&nowt);
265
266         tm = localtime(&t);
267         if (!tm) {
268                 ast_log(LOG_WARNING, "Unable to derive local time\n");
269                 return -1;
270         }
271         memcpy(&tm2, tm, sizeof(struct tm));
272         tm = &tm2;
273         now = localtime(&nowt);
274         daydiff = now->tm_yday - tm->tm_yday;
275         if ((daydiff < 0) || (daydiff > 6)) {
276                 /* Day of month and month */
277                 if (!res) {
278                         snprintf(fn, sizeof(fn), "digits/mon-%d", tm->tm_mon);
279                         res = ast_streamfile(chan, fn, lang);
280                         if (!res)
281                                 res = ast_waitstream(chan, ints);
282                 }
283                 if (!res)
284                         res = ast_say_number(chan, tm->tm_mday, ints, lang);
285
286         } else if (daydiff) {
287                 /* Just what day of the week */
288                 if (!res) {
289                         snprintf(fn, sizeof(fn), "digits/day-%d", tm->tm_wday);
290                         res = ast_streamfile(chan, fn, lang);
291                         if (!res)
292                                 res = ast_waitstream(chan, ints);
293                 }
294         } /* Otherwise, it was today */
295         if (!res)
296                 res = ast_say_time(chan, t, ints, lang);
297         return res;
298 }
299