CLeanup PBX patch and add localtime stuff for saytime (bug #168)
[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 <string.h>
16 #include <stdlib.h>
17 #include <netinet/in.h>
18 #include <time.h>
19 #include <asterisk/file.h>
20 #include <asterisk/channel.h>
21 #include <asterisk/logger.h>
22 #include <asterisk/say.h>
23 #include <asterisk/lock.h>
24 #include <asterisk/localtime.h>
25 #include "asterisk.h"
26 #include <stdio.h>
27
28 #define DIGITS_DIR      AST_SOUNDS "/digits/"
29
30 int ast_say_digit_str(struct ast_channel *chan, char *fn2, char *ints, char *lang)
31 {
32         /* XXX Merge with full version? XXX */
33         char fn[256] = "";
34         int num = 0;
35         int res = 0;
36         while(fn2[num] && !res) {
37                 switch (fn2[num]) {
38                         case ('*'):
39                                 snprintf(fn, sizeof(fn), "digits/star");
40                                 break;
41                         case ('#'):
42                                 snprintf(fn, sizeof(fn), "digits/pound");
43                                 break;
44                         default:
45                                 snprintf(fn, sizeof(fn), "digits/%c", fn2[num]);
46                         }
47                 res = ast_streamfile(chan, fn, lang);
48                 if (!res) 
49                         res = ast_waitstream(chan, ints);
50                 ast_stopstream(chan);
51                 num++;
52         }
53         return res;
54 }
55
56 int ast_say_digit_str_full(struct ast_channel *chan, char *fn2, char *ints, char *lang, int audiofd, int ctrlfd)
57 {
58         char fn[256] = "";
59         int num = 0;
60         int res = 0;
61         while(fn2[num] && !res) {
62                 snprintf(fn, sizeof(fn), "digits/%c", fn2[num]);
63                 res = ast_streamfile(chan, fn, lang);
64                 if (!res) 
65                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
66                 ast_stopstream(chan);
67                 num++;
68         }
69         return res;
70 }
71
72 int ast_say_digits(struct ast_channel *chan, int num, char *ints, char *lang)
73 {
74         /* XXX Should I be merged with say_digits_full XXX */
75         char fn2[256];
76         snprintf(fn2, sizeof(fn2), "%d", num);
77         return ast_say_digit_str(chan, fn2, ints, lang);
78 }
79
80 int ast_say_digits_full(struct ast_channel *chan, int num, char *ints, char *lang, int audiofd, int ctrlfd)
81 {
82         char fn2[256];
83         snprintf(fn2, sizeof(fn2), "%d", num);
84         return ast_say_digit_str_full(chan, fn2, ints, lang, audiofd, ctrlfd);
85 }
86
87 int ast_say_number_full(struct ast_channel *chan, int num, char *ints, char *language, int audiofd, int ctrlfd)
88 {
89         int res = 0;
90         int playh = 0;
91         char fn[256] = "";
92         if (!num) 
93                 return ast_say_digits_full(chan, 0,ints, language, audiofd, ctrlfd);
94         if (0) {
95         /* XXX Only works for english XXX */
96         } else {
97                 /* Use english numbers */
98                 language = "en";
99                 while(!res && (num || playh)) {
100                         if (playh) {
101                                 snprintf(fn, sizeof(fn), "digits/hundred");
102                                 playh = 0;
103                         } else
104                         if (num < 20) {
105                                 snprintf(fn, sizeof(fn), "digits/%d", num);
106                                 num = 0;
107                         } else
108                         if (num < 100) {
109                                 snprintf(fn, sizeof(fn), "digits/%d", (num /10) * 10);
110                                 num -= ((num / 10) * 10);
111                         } else {
112                                 if (num < 1000){
113                                         snprintf(fn, sizeof(fn), "digits/%d", (num/100));
114                                         playh++;
115                                         num -= ((num / 100) * 100);
116                                 } else {
117                                         if (num < 1000000) { /* 1,000,000 */
118                                                 res = ast_say_number_full(chan, num / 1000, ints, language, audiofd, ctrlfd);
119                                                 if (res)
120                                                         return res;
121                                                 num = num % 1000;
122                                                 snprintf(fn, sizeof(fn), "digits/thousand");
123                                         } else {
124                                                 if (num < 1000000000) { /* 1,000,000,000 */
125                                                         res = ast_say_number_full(chan, num / 1000000, ints, language, audiofd, ctrlfd);
126                                                         if (res)
127                                                                 return res;
128                                                         num = num % 1000000;
129                                                         snprintf(fn, sizeof(fn), "digits/million");
130                                                 } else {
131                                                         ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num);
132                                                         res = -1;
133                                                 }
134                                         }
135                                 }
136                         }
137                         if (!res) {
138                                 res = ast_streamfile(chan, fn, language);
139                                 if (!res) 
140                                         res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
141                                 ast_stopstream(chan);
142                         }
143                         
144                 }
145         }
146         return res;
147 }
148
149 int ast_say_number(struct ast_channel *chan, int num, char *ints, char *language)
150 {
151         /* XXX Should I be merged with ast_say_number_full XXX */
152         int res = 0;
153         int playh = 0;
154         char fn[256] = "";
155         if (!num) 
156                 return ast_say_digits(chan, 0,ints, language);
157         if (0) {
158         /* XXX Only works for english XXX */
159         } else {
160                 /* Use english numbers */
161                 language = "en";
162                 while(!res && (num || playh)) {
163                         if (playh) {
164                                 snprintf(fn, sizeof(fn), "digits/hundred");
165                                 playh = 0;
166                         } else
167                         if (num < 20) {
168                                 snprintf(fn, sizeof(fn), "digits/%d", num);
169                                 num = 0;
170                         } else
171                         if (num < 100) {
172                                 snprintf(fn, sizeof(fn), "digits/%d", (num /10) * 10);
173                                 num -= ((num / 10) * 10);
174                         } else {
175                                 if (num < 1000){
176                                         snprintf(fn, sizeof(fn), "digits/%d", (num/100));
177                                         playh++;
178                                         num -= ((num / 100) * 100);
179                                 } else {
180                                         if (num < 1000000) {
181                                                 res = ast_say_number(chan, num / 1000, ints, language);
182                                                 if (res)
183                                                         return res;
184                                                 num = num % 1000;
185                                                 snprintf(fn, sizeof(fn), "digits/thousand");
186                                         } else {
187                                                 if (num < 1000000000) {
188                                                         res = ast_say_number(chan, num / 1000000, ints, language);
189                                                         if (res)
190                                                                 return res;
191                                                         num = num % 1000000;
192                                                         snprintf(fn, sizeof(fn), "digits/million");
193                                                 } else {
194                                                         ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num);
195                                                         res = -1;
196                                                 }
197                                         }
198                                 }
199                         }
200                         if (!res) {
201                                 res = ast_streamfile(chan, fn, language);
202                                 if (!res) 
203                                         res = ast_waitstream(chan, ints);
204                                 ast_stopstream(chan);
205                         }
206                         
207                 }
208         }
209         return res;
210 }
211 int ast_say_date(struct ast_channel *chan, time_t t, char *ints, char *lang)
212 {
213         struct tm tm;
214         char fn[256];
215         int res = 0;
216         ast_localtime(&t,&tm,NULL);
217         if (!res) {
218                 snprintf(fn, sizeof(fn), "digits/day-%d", tm.tm_wday);
219                 res = ast_streamfile(chan, fn, lang);
220                 if (!res)
221                         res = ast_waitstream(chan, ints);
222         }
223         if (!res) {
224                 snprintf(fn, sizeof(fn), "digits/mon-%d", tm.tm_mon);
225                 res = ast_streamfile(chan, fn, lang);
226                 if (!res)
227                         res = ast_waitstream(chan, ints);
228         }
229         if (!res)
230                 res = ast_say_number(chan, tm.tm_mday, ints, lang);
231
232         if (!res)
233                 res = ast_waitstream(chan, ints);
234         if (!res)
235                 res = ast_say_number(chan, tm.tm_year + 1900, ints, lang);
236         return res;
237 }
238
239 static int wait_file(struct ast_channel *chan, char *ints, char *file, char *lang) 
240 {
241         int res;
242         if ((res = ast_streamfile(chan, file, lang)))
243                 ast_log(LOG_WARNING, "Unable to play message %s\n", file);
244         if (!res)
245                 res = ast_waitstream(chan, ints);
246         return res;
247 }
248
249 int ast_say_date_with_format(struct ast_channel *chan, time_t time, char *ints, char *lang, char *format, char *timezone)
250 {
251         struct tm tm;
252         int res=0, offset, sndoffset;
253         char sndfile[256], nextmsg[256];
254
255         ast_log(LOG_DEBUG, "ast_say_date_with_format() called\n");
256
257         ast_localtime(&time,&tm,timezone);
258
259         ast_log(LOG_DEBUG, "ast_localtime() returned\n");
260
261         for (offset=0 ; format[offset] != '\0' ; offset++) {
262                 ast_log(LOG_DEBUG, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
263                 switch (format[offset]) {
264                         /* NOTE:  if you add more options here, please try to be consistent with strftime(3) */
265                         case '\'':
266                                 /* Literal name of a sound file */
267                                 sndoffset=0;
268                                 for (sndoffset=0 ; (format[++offset] != '\'') && (sndoffset < 256) ; sndoffset++)
269                                         sndfile[sndoffset] = format[offset];
270                                 sndfile[sndoffset] = '\0';
271                                 snprintf(nextmsg,sizeof(nextmsg), AST_SOUNDS "/%s", sndfile);
272                                 res = wait_file(chan,ints,nextmsg,lang);
273                                 break;
274                         case 'A':
275                         case 'a':
276                                 /* Sunday - Saturday */
277                                 snprintf(nextmsg,sizeof(nextmsg), DIGITS_DIR "day-%d", tm.tm_wday);
278                                 res = wait_file(chan,ints,nextmsg,lang);
279                                 break;
280                         case 'B':
281                         case 'b':
282                         case 'h':
283                                 /* January - December */
284                                 snprintf(nextmsg,sizeof(nextmsg), DIGITS_DIR "mon-%d", tm.tm_mon);
285                                 res = wait_file(chan,ints,nextmsg,lang);
286                                 break;
287                         case 'd':
288                         case 'e':
289                                 /* First - Thirtyfirst */
290                                 if ((tm.tm_mday < 21) || (tm.tm_mday == 30)) {
291                                         snprintf(nextmsg,sizeof(nextmsg), DIGITS_DIR "h-%d", tm.tm_mday);
292                                         res = wait_file(chan,ints,nextmsg,lang);
293                                 } else if (tm.tm_mday == 31) {
294                                         /* "Thirty" and "first" */
295                                         res = wait_file(chan,ints,DIGITS_DIR "30",lang);
296                                         if (!res) {
297                                                 res = wait_file(chan,ints,DIGITS_DIR "h-1",lang);
298                                         }
299                                 } else {
300                                         /* Between 21 and 29 - two sounds */
301                                         res = wait_file(chan,ints,DIGITS_DIR "20",lang);
302                                         if (!res) {
303                                                 snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "h-%d", tm.tm_mday - 20);
304                                                 res = wait_file(chan,ints,nextmsg,lang);
305                                         }
306                                 }
307                                 break;
308                         case 'Y':
309                                 /* Year */
310                                 if (tm.tm_year > 99) {
311                                         res = wait_file(chan,ints,DIGITS_DIR "2",lang);
312                                         if (!res) {
313                                                 res = wait_file(chan,ints,DIGITS_DIR "thousand",lang);
314                                         }
315                                         if (tm.tm_year > 100) {
316                                                 if (!res) {
317                                                         /* This works until the end of 2020 */
318                                                         snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "%d", tm.tm_year - 100);
319                                                         res = wait_file(chan,ints,nextmsg,lang);
320                                                 }
321                                         }
322                                 } else {
323                                         if (tm.tm_year < 1) {
324                                                 /* I'm not going to handle 1900 and prior */
325                                                 /* We'll just be silent on the year, instead of bombing out. */
326                                         } else {
327                                                 res = wait_file(chan,ints,DIGITS_DIR "19",lang);
328                                                 if (!res) {
329                                                         if (tm.tm_year <= 9) {
330                                                                 /* 1901 - 1909 */
331                                                                 res = wait_file(chan,ints,DIGITS_DIR "oh",lang);
332                                                                 if (!res) {
333                                                                         snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "%d", tm.tm_year);
334                                                                         res = wait_file(chan,ints,nextmsg,lang);
335                                                                 }
336                                                         } else if (tm.tm_year <= 20) {
337                                                                 /* 1910 - 1920 */
338                                                                 snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "%d", tm.tm_year);
339                                                                 res = wait_file(chan,ints,nextmsg,lang);
340                                                         } else {
341                                                                 /* 1921 - 1999 */
342                                                                 int ten, one;
343                                                                 ten = tm.tm_year / 10;
344                                                                 one = tm.tm_year % 10;
345                                                                 snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "%d", ten * 10);
346                                                                 res = wait_file(chan,ints,nextmsg,lang);
347                                                                 if (!res) {
348                                                                         if (one != 0) {
349                                                                                 snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "%d", one);
350                                                                                 res = wait_file(chan,ints,nextmsg,lang);
351                                                                         }
352                                                                 }
353                                                         }
354                                                 }
355                                         }
356                                 }
357                                 break;
358                         case 'I':
359                         case 'l':
360                                 /* 12-Hour */
361                                 if (tm.tm_hour == 0)
362                                         snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "12");
363                                 else if (tm.tm_hour > 12)
364                                         snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "%d", tm.tm_hour - 12);
365                                 else
366                                         snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "%d", tm.tm_hour);
367                                 res = wait_file(chan,ints,nextmsg,lang);
368                                 break;
369                         case 'H':
370                         case 'k':
371                                 /* 24-Hour */
372                                 if (format[offset] == 'H') {
373                                         /* e.g. oh-eight */
374                                         if (tm.tm_hour < 10) {
375                                                 res = wait_file(chan,ints,DIGITS_DIR "oh",lang);
376                                         }
377                                 } else {
378                                         /* e.g. eight */
379                                         if (tm.tm_hour == 0) {
380                                                 res = wait_file(chan,ints,DIGITS_DIR "oh",lang);
381                                         }
382                                 }
383                                 if (!res) {
384                                         if (tm.tm_hour != 0) {
385                                                 snprintf(nextmsg,sizeof(nextmsg), AST_SOUNDS "/digits/%d", tm.tm_hour);
386                                                 res = wait_file(chan,ints,nextmsg,lang);
387                                         }
388                                 }
389                                 break;
390                         case 'M':
391                                 /* Minute */
392                                 if (tm.tm_min == 0) {
393                                         res = wait_file(chan,ints,DIGITS_DIR "oclock",lang);
394                                 } else if (tm.tm_min < 10) {
395                                         res = wait_file(chan,ints,DIGITS_DIR "oh",lang);
396                                         if (!res) {
397                                                 snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "%d", tm.tm_min);
398                                                 res = wait_file(chan,ints,nextmsg,lang);
399                                         }
400                                 } else if ((tm.tm_min < 21) || (tm.tm_min % 10 == 0)) {
401                                         snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "%d", tm.tm_min);
402                                         res = wait_file(chan,ints,nextmsg,lang);
403                                 } else {
404                                         int ten, one;
405                                         ten = (tm.tm_min / 10) * 10;
406                                         one = (tm.tm_min % 10);
407                                         snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "%d", ten);
408                                         res = wait_file(chan,ints,nextmsg,lang);
409                                         if (!res) {
410                                                 /* Fifty, not fifty-zero */
411                                                 if (one != 0) {
412                                                         snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "%d", one);
413                                                         res = wait_file(chan,ints,nextmsg,lang);
414                                                 }
415                                         }
416                                 }
417                                 break;
418                         case 'P':
419                         case 'p':
420                                 /* AM/PM */
421                                 if ((tm.tm_hour == 0) || (tm.tm_hour > 11))
422                                         snprintf(nextmsg,sizeof(nextmsg), DIGITS_DIR "p-m");
423                                 else
424                                         snprintf(nextmsg,sizeof(nextmsg), DIGITS_DIR "a-m");
425                                 res = wait_file(chan,ints,nextmsg,lang);
426                                 break;
427                         case 'Q':
428                                 /* Shorthand for "Today", "Yesterday", or ABdY */
429                                 {
430                                         struct timeval now;
431                                         struct tm tmnow;
432                                         time_t beg_today;
433
434                                         gettimeofday(&now,NULL);
435                                         ast_localtime(&now.tv_sec,&tmnow,timezone);
436                                         /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
437                                         /* In any case, it saves not having to do ast_mktime() */
438                                         beg_today = now.tv_sec - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
439                                         if (beg_today < time) {
440                                                 /* Today */
441                                                 res = wait_file(chan,ints,DIGITS_DIR "today",lang);
442                                         } else if (beg_today - 86400 < time) {
443                                                 /* Yesterday */
444                                                 res = wait_file(chan,ints,DIGITS_DIR "yesterday",lang);
445                                         } else {
446                                                 res = ast_say_date_with_format(chan, time, ints, lang, "ABdY", timezone);
447                                         }
448                                 }
449                                 break;
450                         case 'q':
451                                 /* Shorthand for "" (today), "Yesterday", A (weekday), or ABdY */
452                                 {
453                                         struct timeval now;
454                                         struct tm tmnow;
455                                         time_t beg_today;
456
457                                         gettimeofday(&now,NULL);
458                                         ast_localtime(&now.tv_sec,&tmnow,timezone);
459                                         /* This might be slightly off, if we transcend a leap second, but never more off than 1 second */
460                                         /* In any case, it saves not having to do ast_mktime() */
461                                         beg_today = now.tv_sec - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
462                                         if (beg_today < time) {
463                                                 /* Today */
464                                         } else if ((beg_today - 86400) < time) {
465                                                 /* Yesterday */
466                                                 res = wait_file(chan,ints,DIGITS_DIR "yesterday",lang);
467                                         } else if (beg_today - 86400 * 6 < time) {
468                                                 /* Within the last week */
469                                                 res = ast_say_date_with_format(chan, time, ints, lang, "A", timezone);
470                                         } else {
471                                                 res = ast_say_date_with_format(chan, time, ints, lang, "ABdY", timezone);
472                                         }
473                                 }
474                                 break;
475                         case 'R':
476                                 res = ast_say_date_with_format(chan, time, ints, lang, "HM", timezone);
477                                 break;
478                         case ' ':
479                         case '  ':
480                                 /* Just ignore spaces and tabs */
481                                 break;
482                         default:
483                                 /* Unknown character */
484                                 ast_log(LOG_WARNING, "Unknown character in datetime format %s: %c at pos %d\n", format, format[offset], offset);
485                 }
486                 /* Jump out on DTMF */
487                 if (res) {
488                         break;
489                 }
490         }
491         return res;
492 }
493
494 int ast_say_time(struct ast_channel *chan, time_t t, char *ints, char *lang)
495 {
496         struct tm tm;
497         int res = 0;
498         int hour, pm=0;
499         localtime_r(&t,&tm);
500         hour = tm.tm_hour;
501         if (!hour)
502                 hour = 12;
503         else if (hour == 12)
504                 pm = 1;
505         else if (hour > 12) {
506                 hour -= 12;
507                 pm = 1;
508         }
509         if (!res)
510                 res = ast_say_number(chan, hour, ints, lang);
511
512         if (tm.tm_min > 9) {
513                 if (!res)
514                         res = ast_say_number(chan, tm.tm_min, ints, lang);
515         } else if (tm.tm_min) {
516                 if (!res)
517                         res = ast_streamfile(chan, "digits/oh", lang);
518                 if (!res)
519                         res = ast_waitstream(chan, ints);
520                 if (!res)
521                         res = ast_say_number(chan, tm.tm_min, ints, lang);
522         } else {
523                 if (!res)
524                         res = ast_streamfile(chan, "digits/oclock", lang);
525                 if (!res)
526                         res = ast_waitstream(chan, ints);
527         }
528         if (pm) {
529                 if (!res)
530                         res = ast_streamfile(chan, "digits/p-m", lang);
531         } else {
532                 if (!res)
533                         res = ast_streamfile(chan, "digits/a-m", lang);
534         }
535         if (!res)
536                 res = ast_waitstream(chan, ints);
537         return res;
538 }
539
540 int ast_say_datetime(struct ast_channel *chan, time_t t, char *ints, char *lang)
541 {
542         struct tm tm;
543         char fn[256];
544         int res = 0;
545         int hour, pm=0;
546         localtime_r(&t,&tm);
547         if (!res) {
548                 snprintf(fn, sizeof(fn), "digits/day-%d", tm.tm_wday);
549                 res = ast_streamfile(chan, fn, lang);
550                 if (!res)
551                         res = ast_waitstream(chan, ints);
552         }
553         if (!res) {
554                 snprintf(fn, sizeof(fn), "digits/mon-%d", tm.tm_mon);
555                 res = ast_streamfile(chan, fn, lang);
556                 if (!res)
557                         res = ast_waitstream(chan, ints);
558         }
559         if (!res)
560                 res = ast_say_number(chan, tm.tm_mday, ints, lang);
561
562         hour = tm.tm_hour;
563         if (!hour)
564                 hour = 12;
565         else if (hour == 12)
566                 pm = 1;
567         else if (hour > 12) {
568                 hour -= 12;
569                 pm = 1;
570         }
571         if (!res)
572                 res = ast_say_number(chan, hour, ints, lang);
573
574         if (tm.tm_min > 9) {
575                 if (!res)
576                         res = ast_say_number(chan, tm.tm_min, ints, lang);
577         } else if (tm.tm_min) {
578                 if (!res)
579                         res = ast_streamfile(chan, "digits/oh", lang);
580                 if (!res)
581                         res = ast_waitstream(chan, ints);
582                 if (!res)
583                         res = ast_say_number(chan, tm.tm_min, ints, lang);
584         } else {
585                 if (!res)
586                         res = ast_streamfile(chan, "digits/oclock", lang);
587                 if (!res)
588                         res = ast_waitstream(chan, ints);
589         }
590         if (pm) {
591                 if (!res)
592                         res = ast_streamfile(chan, "digits/p-m", lang);
593         } else {
594                 if (!res)
595                         res = ast_streamfile(chan, "digits/a-m", lang);
596         }
597         if (!res)
598                 res = ast_waitstream(chan, ints);
599         if (!res)
600                 res = ast_say_number(chan, tm.tm_year + 1900, ints, lang);
601         return res;
602 }
603
604 int ast_say_datetime_from_now(struct ast_channel *chan, time_t t, char *ints, char *lang)
605 {
606         int res=0;
607         time_t nowt;
608         int daydiff;
609         struct tm tm;
610         struct tm now;
611         char fn[256];
612
613         time(&nowt);
614
615         localtime_r(&t,&tm);
616         localtime_r(&nowt,&now);
617         daydiff = now.tm_yday - tm.tm_yday;
618         if ((daydiff < 0) || (daydiff > 6)) {
619                 /* Day of month and month */
620                 if (!res) {
621                         snprintf(fn, sizeof(fn), "digits/mon-%d", tm.tm_mon);
622                         res = ast_streamfile(chan, fn, lang);
623                         if (!res)
624                                 res = ast_waitstream(chan, ints);
625                 }
626                 if (!res)
627                         res = ast_say_number(chan, tm.tm_mday, ints, lang);
628
629         } else if (daydiff) {
630                 /* Just what day of the week */
631                 if (!res) {
632                         snprintf(fn, sizeof(fn), "digits/day-%d", tm.tm_wday);
633                         res = ast_streamfile(chan, fn, lang);
634                         if (!res)
635                                 res = ast_waitstream(chan, ints);
636                 }
637         } /* Otherwise, it was today */
638         if (!res)
639                 res = ast_say_time(chan, t, ints, lang);
640         return res;
641 }
642