00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include <sys/types.h>
00015 #include <string.h>
00016 #include <stdlib.h>
00017 #include <netinet/in.h>
00018 #include <time.h>
00019 #include <asterisk/file.h>
00020 #include <asterisk/channel.h>
00021 #include <asterisk/logger.h>
00022 #include <asterisk/say.h>
00023 #include <asterisk/lock.h>
00024 #include <asterisk/localtime.h>
00025 #include "asterisk.h"
00026 #include <stdio.h>
00027
00028 #define DIGITS_DIR AST_SOUNDS "/digits/"
00029
00030 int ast_say_digit_str(struct ast_channel *chan, char *fn2, char *ints, char *lang)
00031 {
00032
00033 char fn[256] = "";
00034 int num = 0;
00035 int res = 0;
00036 while(fn2[num] && !res) {
00037 switch (fn2[num]) {
00038 case ('*'):
00039 snprintf(fn, sizeof(fn), "digits/star");
00040 break;
00041 case ('#'):
00042 snprintf(fn, sizeof(fn), "digits/pound");
00043 break;
00044 default:
00045 snprintf(fn, sizeof(fn), "digits/%c", fn2[num]);
00046 }
00047 res = ast_streamfile(chan, fn, lang);
00048 if (!res)
00049 res = ast_waitstream(chan, ints);
00050 ast_stopstream(chan);
00051 num++;
00052 }
00053 return res;
00054 }
00055
00056 int ast_say_digit_str_full(struct ast_channel *chan, char *fn2, char *ints, char *lang, int audiofd, int ctrlfd)
00057 {
00058 char fn[256] = "";
00059 int num = 0;
00060 int res = 0;
00061 while(fn2[num] && !res) {
00062 snprintf(fn, sizeof(fn), "digits/%c", fn2[num]);
00063 res = ast_streamfile(chan, fn, lang);
00064 if (!res)
00065 res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
00066 ast_stopstream(chan);
00067 num++;
00068 }
00069 return res;
00070 }
00071
00072 int ast_say_digits(struct ast_channel *chan, int num, char *ints, char *lang)
00073 {
00074
00075 char fn2[256];
00076 snprintf(fn2, sizeof(fn2), "%d", num);
00077 return ast_say_digit_str(chan, fn2, ints, lang);
00078 }
00079
00080 int ast_say_digits_full(struct ast_channel *chan, int num, char *ints, char *lang, int audiofd, int ctrlfd)
00081 {
00082 char fn2[256];
00083 snprintf(fn2, sizeof(fn2), "%d", num);
00084 return ast_say_digit_str_full(chan, fn2, ints, lang, audiofd, ctrlfd);
00085 }
00086
00087 int ast_say_number_full(struct ast_channel *chan, int num, char *ints, char *language, int audiofd, int ctrlfd)
00088 {
00089 int res = 0;
00090 int playh = 0;
00091 char fn[256] = "";
00092 if (!num)
00093 return ast_say_digits_full(chan, 0,ints, language, audiofd, ctrlfd);
00094 if (0) {
00095
00096 } else {
00097
00098 language = "en";
00099 while(!res && (num || playh)) {
00100 if (playh) {
00101 snprintf(fn, sizeof(fn), "digits/hundred");
00102 playh = 0;
00103 } else
00104 if (num < 20) {
00105 snprintf(fn, sizeof(fn), "digits/%d", num);
00106 num = 0;
00107 } else
00108 if (num < 100) {
00109 snprintf(fn, sizeof(fn), "digits/%d", (num /10) * 10);
00110 num -= ((num / 10) * 10);
00111 } else {
00112 if (num < 1000){
00113 snprintf(fn, sizeof(fn), "digits/%d", (num/100));
00114 playh++;
00115 num -= ((num / 100) * 100);
00116 } else {
00117 if (num < 1000000) {
00118 res = ast_say_number_full(chan, num / 1000, ints, language, audiofd, ctrlfd);
00119 if (res)
00120 return res;
00121 num = num % 1000;
00122 snprintf(fn, sizeof(fn), "digits/thousand");
00123 } else {
00124 if (num < 1000000000) {
00125 res = ast_say_number_full(chan, num / 1000000, ints, language, audiofd, ctrlfd);
00126 if (res)
00127 return res;
00128 num = num % 1000000;
00129 snprintf(fn, sizeof(fn), "digits/million");
00130 } else {
00131 ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num);
00132 res = -1;
00133 }
00134 }
00135 }
00136 }
00137 if (!res) {
00138 res = ast_streamfile(chan, fn, language);
00139 if (!res)
00140 res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
00141 ast_stopstream(chan);
00142 }
00143
00144 }
00145 }
00146 return res;
00147 }
00148
00149 int ast_say_number(struct ast_channel *chan, int num, char *ints, char *language)
00150 {
00151
00152 int res = 0;
00153 int playh = 0;
00154 char fn[256] = "";
00155 if (!num)
00156 return ast_say_digits(chan, 0,ints, language);
00157 if (0) {
00158
00159 } else {
00160
00161 language = "en";
00162 while(!res && (num || playh)) {
00163 if (playh) {
00164 snprintf(fn, sizeof(fn), "digits/hundred");
00165 playh = 0;
00166 } else
00167 if (num < 20) {
00168 snprintf(fn, sizeof(fn), "digits/%d", num);
00169 num = 0;
00170 } else
00171 if (num < 100) {
00172 snprintf(fn, sizeof(fn), "digits/%d", (num /10) * 10);
00173 num -= ((num / 10) * 10);
00174 } else {
00175 if (num < 1000){
00176 snprintf(fn, sizeof(fn), "digits/%d", (num/100));
00177 playh++;
00178 num -= ((num / 100) * 100);
00179 } else {
00180 if (num < 1000000) {
00181 res = ast_say_number(chan, num / 1000, ints, language);
00182 if (res)
00183 return res;
00184 num = num % 1000;
00185 snprintf(fn, sizeof(fn), "digits/thousand");
00186 } else {
00187 if (num < 1000000000) {
00188 res = ast_say_number(chan, num / 1000000, ints, language);
00189 if (res)
00190 return res;
00191 num = num % 1000000;
00192 snprintf(fn, sizeof(fn), "digits/million");
00193 } else {
00194 ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num);
00195 res = -1;
00196 }
00197 }
00198 }
00199 }
00200 if (!res) {
00201 res = ast_streamfile(chan, fn, language);
00202 if (!res)
00203 res = ast_waitstream(chan, ints);
00204 ast_stopstream(chan);
00205 }
00206
00207 }
00208 }
00209 return res;
00210 }
00211 int ast_say_date(struct ast_channel *chan, time_t t, char *ints, char *lang)
00212 {
00213 struct tm tm;
00214 char fn[256];
00215 int res = 0;
00216 ast_localtime(&t,&tm,NULL);
00217 if (!res) {
00218 snprintf(fn, sizeof(fn), "digits/day-%d", tm.tm_wday);
00219 res = ast_streamfile(chan, fn, lang);
00220 if (!res)
00221 res = ast_waitstream(chan, ints);
00222 }
00223 if (!res) {
00224 snprintf(fn, sizeof(fn), "digits/mon-%d", tm.tm_mon);
00225 res = ast_streamfile(chan, fn, lang);
00226 if (!res)
00227 res = ast_waitstream(chan, ints);
00228 }
00229 if (!res)
00230 res = ast_say_number(chan, tm.tm_mday, ints, lang);
00231
00232 if (!res)
00233 res = ast_waitstream(chan, ints);
00234 if (!res)
00235 res = ast_say_number(chan, tm.tm_year + 1900, ints, lang);
00236 return res;
00237 }
00238
00239 static int wait_file(struct ast_channel *chan, char *ints, char *file, char *lang)
00240 {
00241 int res;
00242 if ((res = ast_streamfile(chan, file, lang)))
00243 ast_log(LOG_WARNING, "Unable to play message %s\n", file);
00244 if (!res)
00245 res = ast_waitstream(chan, ints);
00246 return res;
00247 }
00248
00249 int ast_say_date_with_format(struct ast_channel *chan, time_t time, char *ints, char *lang, char *format, char *timezone)
00250 {
00251 struct tm tm;
00252 int res=0, offset, sndoffset;
00253 char sndfile[256], nextmsg[256];
00254
00255 ast_localtime(&time,&tm,timezone);
00256
00257 for (offset=0 ; format[offset] != '\0' ; offset++) {
00258 ast_log(LOG_DEBUG, "Parsing %c (offset %d) in %s\n", format[offset], offset, format);
00259 switch (format[offset]) {
00260
00261 case '\'':
00262
00263 sndoffset=0;
00264 for (sndoffset=0 ; (format[++offset] != '\'') && (sndoffset < 256) ; sndoffset++)
00265 sndfile[sndoffset] = format[offset];
00266 sndfile[sndoffset] = '\0';
00267 snprintf(nextmsg,sizeof(nextmsg), AST_SOUNDS "/%s", sndfile);
00268 res = wait_file(chan,ints,nextmsg,lang);
00269 break;
00270 case 'A':
00271 case 'a':
00272
00273 snprintf(nextmsg,sizeof(nextmsg), DIGITS_DIR "day-%d", tm.tm_wday);
00274 res = wait_file(chan,ints,nextmsg,lang);
00275 break;
00276 case 'B':
00277 case 'b':
00278 case 'h':
00279
00280 snprintf(nextmsg,sizeof(nextmsg), DIGITS_DIR "mon-%d", tm.tm_mon);
00281 res = wait_file(chan,ints,nextmsg,lang);
00282 break;
00283 case 'd':
00284 case 'e':
00285
00286 if ((tm.tm_mday < 21) || (tm.tm_mday == 30)) {
00287 snprintf(nextmsg,sizeof(nextmsg), DIGITS_DIR "h-%d", tm.tm_mday);
00288 res = wait_file(chan,ints,nextmsg,lang);
00289 } else if (tm.tm_mday == 31) {
00290
00291 res = wait_file(chan,ints,DIGITS_DIR "30",lang);
00292 if (!res) {
00293 res = wait_file(chan,ints,DIGITS_DIR "h-1",lang);
00294 }
00295 } else {
00296
00297 res = wait_file(chan,ints,DIGITS_DIR "20",lang);
00298 if (!res) {
00299 snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "h-%d", tm.tm_mday - 20);
00300 res = wait_file(chan,ints,nextmsg,lang);
00301 }
00302 }
00303 break;
00304 case 'Y':
00305
00306 if (tm.tm_year > 99) {
00307 res = wait_file(chan,ints,DIGITS_DIR "2",lang);
00308 if (!res) {
00309 res = wait_file(chan,ints,DIGITS_DIR "thousand",lang);
00310 }
00311 if (tm.tm_year > 100) {
00312 if (!res) {
00313
00314 snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "%d", tm.tm_year - 100);
00315 res = wait_file(chan,ints,nextmsg,lang);
00316 }
00317 }
00318 } else {
00319 if (tm.tm_year < 1) {
00320
00321
00322 } else {
00323 res = wait_file(chan,ints,DIGITS_DIR "19",lang);
00324 if (!res) {
00325 if (tm.tm_year <= 9) {
00326
00327 res = wait_file(chan,ints,DIGITS_DIR "oh",lang);
00328 if (!res) {
00329 snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "%d", tm.tm_year);
00330 res = wait_file(chan,ints,nextmsg,lang);
00331 }
00332 } else if (tm.tm_year <= 20) {
00333
00334 snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "%d", tm.tm_year);
00335 res = wait_file(chan,ints,nextmsg,lang);
00336 } else {
00337
00338 int ten, one;
00339 ten = tm.tm_year / 10;
00340 one = tm.tm_year % 10;
00341 snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "%d", ten * 10);
00342 res = wait_file(chan,ints,nextmsg,lang);
00343 if (!res) {
00344 if (one != 0) {
00345 snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "%d", one);
00346 res = wait_file(chan,ints,nextmsg,lang);
00347 }
00348 }
00349 }
00350 }
00351 }
00352 }
00353 break;
00354 case 'I':
00355 case 'l':
00356
00357 if (tm.tm_hour == 0)
00358 snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "12");
00359 else if (tm.tm_hour > 12)
00360 snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "%d", tm.tm_hour - 12);
00361 else
00362 snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "%d", tm.tm_hour);
00363 res = wait_file(chan,ints,nextmsg,lang);
00364 break;
00365 case 'H':
00366 case 'k':
00367
00368 if (format[offset] == 'H') {
00369
00370 if (tm.tm_hour < 10) {
00371 res = wait_file(chan,ints,DIGITS_DIR "oh",lang);
00372 }
00373 } else {
00374
00375 if (tm.tm_hour == 0) {
00376 res = wait_file(chan,ints,DIGITS_DIR "oh",lang);
00377 }
00378 }
00379 if (!res) {
00380 if (tm.tm_hour != 0) {
00381 int remainder = tm.tm_hour;
00382 if (tm.tm_hour > 20) {
00383 res = wait_file(chan,ints,AST_SOUNDS "/digits/20",lang);
00384 remainder -= 20;
00385 }
00386 if (!res) {
00387 snprintf(nextmsg,sizeof(nextmsg), AST_SOUNDS "/digits/%d", remainder);
00388 res = wait_file(chan,ints,nextmsg,lang);
00389 }
00390 }
00391 }
00392 break;
00393 case 'M':
00394
00395 if (tm.tm_min == 0) {
00396 res = wait_file(chan,ints,DIGITS_DIR "oclock",lang);
00397 } else if (tm.tm_min < 10) {
00398 res = wait_file(chan,ints,DIGITS_DIR "oh",lang);
00399 if (!res) {
00400 snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "%d", tm.tm_min);
00401 res = wait_file(chan,ints,nextmsg,lang);
00402 }
00403 } else if ((tm.tm_min < 21) || (tm.tm_min % 10 == 0)) {
00404 snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "%d", tm.tm_min);
00405 res = wait_file(chan,ints,nextmsg,lang);
00406 } else {
00407 int ten, one;
00408 ten = (tm.tm_min / 10) * 10;
00409 one = (tm.tm_min % 10);
00410 snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "%d", ten);
00411 res = wait_file(chan,ints,nextmsg,lang);
00412 if (!res) {
00413
00414 if (one != 0) {
00415 snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "%d", one);
00416 res = wait_file(chan,ints,nextmsg,lang);
00417 }
00418 }
00419 }
00420 break;
00421 case 'P':
00422 case 'p':
00423
00424 if (tm.tm_hour > 11)
00425 snprintf(nextmsg,sizeof(nextmsg), DIGITS_DIR "p-m");
00426 else
00427 snprintf(nextmsg,sizeof(nextmsg), DIGITS_DIR "a-m");
00428 res = wait_file(chan,ints,nextmsg,lang);
00429 break;
00430 case 'Q':
00431
00432 {
00433 struct timeval now;
00434 struct tm tmnow;
00435 time_t beg_today;
00436
00437 gettimeofday(&now,NULL);
00438 ast_localtime(&now.tv_sec,&tmnow,timezone);
00439
00440
00441 beg_today = now.tv_sec - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
00442 if (beg_today < time) {
00443
00444 res = wait_file(chan,ints,DIGITS_DIR "today",lang);
00445 } else if (beg_today - 86400 < time) {
00446
00447 res = wait_file(chan,ints,DIGITS_DIR "yesterday",lang);
00448 } else {
00449 res = ast_say_date_with_format(chan, time, ints, lang, "ABdY", timezone);
00450 }
00451 }
00452 break;
00453 case 'q':
00454
00455 {
00456 struct timeval now;
00457 struct tm tmnow;
00458 time_t beg_today;
00459
00460 gettimeofday(&now,NULL);
00461 ast_localtime(&now.tv_sec,&tmnow,timezone);
00462
00463
00464 beg_today = now.tv_sec - (tmnow.tm_hour * 3600) - (tmnow.tm_min * 60) - (tmnow.tm_sec);
00465 if (beg_today < time) {
00466
00467 } else if ((beg_today - 86400) < time) {
00468
00469 res = wait_file(chan,ints,DIGITS_DIR "yesterday",lang);
00470 } else if (beg_today - 86400 * 6 < time) {
00471
00472 res = ast_say_date_with_format(chan, time, ints, lang, "A", timezone);
00473 } else {
00474 res = ast_say_date_with_format(chan, time, ints, lang, "ABdY", timezone);
00475 }
00476 }
00477 break;
00478 case 'R':
00479 res = ast_say_date_with_format(chan, time, ints, lang, "HM", timezone);
00480 break;
00481 case 'S':
00482
00483 if (tm.tm_sec == 0) {
00484 snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "%d", tm.tm_sec);
00485 res = wait_file(chan,ints,nextmsg,lang);
00486 } else if (tm.tm_sec < 10) {
00487 res = wait_file(chan,ints,DIGITS_DIR "oh",lang);
00488 if (!res) {
00489 snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "%d", tm.tm_sec);
00490 res = wait_file(chan,ints,nextmsg,lang);
00491 }
00492 } else if ((tm.tm_sec < 21) || (tm.tm_sec % 10 == 0)) {
00493 snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "%d", tm.tm_sec);
00494 res = wait_file(chan,ints,nextmsg,lang);
00495 } else {
00496 int ten, one;
00497 ten = (tm.tm_sec / 10) * 10;
00498 one = (tm.tm_sec % 10);
00499 snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "%d", ten);
00500 res = wait_file(chan,ints,nextmsg,lang);
00501 if (!res) {
00502
00503 if (one != 0) {
00504 snprintf(nextmsg,sizeof(nextmsg),DIGITS_DIR "%d", one);
00505 res = wait_file(chan,ints,nextmsg,lang);
00506 }
00507 }
00508 }
00509 break;
00510 case 'T':
00511 res = ast_say_date_with_format(chan, time, ints, lang, "HMS", timezone);
00512 break;
00513 case ' ':
00514 case ' ':
00515
00516 break;
00517 default:
00518
00519 ast_log(LOG_WARNING, "Unknown character in datetime format %s: %c at pos %d\n", format, format[offset], offset);
00520 }
00521
00522 if (res) {
00523 break;
00524 }
00525 }
00526 return res;
00527 }
00528
00529 int ast_say_time(struct ast_channel *chan, time_t t, char *ints, char *lang)
00530 {
00531 struct tm tm;
00532 int res = 0;
00533 int hour, pm=0;
00534 localtime_r(&t,&tm);
00535 hour = tm.tm_hour;
00536 if (!hour)
00537 hour = 12;
00538 else if (hour == 12)
00539 pm = 1;
00540 else if (hour > 12) {
00541 hour -= 12;
00542 pm = 1;
00543 }
00544 if (!res)
00545 res = ast_say_number(chan, hour, ints, lang);
00546
00547 if (tm.tm_min > 9) {
00548 if (!res)
00549 res = ast_say_number(chan, tm.tm_min, ints, lang);
00550 } else if (tm.tm_min) {
00551 if (!res)
00552 res = ast_streamfile(chan, "digits/oh", lang);
00553 if (!res)
00554 res = ast_waitstream(chan, ints);
00555 if (!res)
00556 res = ast_say_number(chan, tm.tm_min, ints, lang);
00557 } else {
00558 if (!res)
00559 res = ast_streamfile(chan, "digits/oclock", lang);
00560 if (!res)
00561 res = ast_waitstream(chan, ints);
00562 }
00563 if (pm) {
00564 if (!res)
00565 res = ast_streamfile(chan, "digits/p-m", lang);
00566 } else {
00567 if (!res)
00568 res = ast_streamfile(chan, "digits/a-m", lang);
00569 }
00570 if (!res)
00571 res = ast_waitstream(chan, ints);
00572 return res;
00573 }
00574
00575 int ast_say_datetime(struct ast_channel *chan, time_t t, char *ints, char *lang)
00576 {
00577 struct tm tm;
00578 char fn[256];
00579 int res = 0;
00580 int hour, pm=0;
00581 localtime_r(&t,&tm);
00582 if (!res) {
00583 snprintf(fn, sizeof(fn), "digits/day-%d", tm.tm_wday);
00584 res = ast_streamfile(chan, fn, lang);
00585 if (!res)
00586 res = ast_waitstream(chan, ints);
00587 }
00588 if (!res) {
00589 snprintf(fn, sizeof(fn), "digits/mon-%d", tm.tm_mon);
00590 res = ast_streamfile(chan, fn, lang);
00591 if (!res)
00592 res = ast_waitstream(chan, ints);
00593 }
00594 if (!res)
00595 res = ast_say_number(chan, tm.tm_mday, ints, lang);
00596
00597 hour = tm.tm_hour;
00598 if (!hour)
00599 hour = 12;
00600 else if (hour == 12)
00601 pm = 1;
00602 else if (hour > 12) {
00603 hour -= 12;
00604 pm = 1;
00605 }
00606 if (!res)
00607 res = ast_say_number(chan, hour, ints, lang);
00608
00609 if (tm.tm_min > 9) {
00610 if (!res)
00611 res = ast_say_number(chan, tm.tm_min, ints, lang);
00612 } else if (tm.tm_min) {
00613 if (!res)
00614 res = ast_streamfile(chan, "digits/oh", lang);
00615 if (!res)
00616 res = ast_waitstream(chan, ints);
00617 if (!res)
00618 res = ast_say_number(chan, tm.tm_min, ints, lang);
00619 } else {
00620 if (!res)
00621 res = ast_streamfile(chan, "digits/oclock", lang);
00622 if (!res)
00623 res = ast_waitstream(chan, ints);
00624 }
00625 if (pm) {
00626 if (!res)
00627 res = ast_streamfile(chan, "digits/p-m", lang);
00628 } else {
00629 if (!res)
00630 res = ast_streamfile(chan, "digits/a-m", lang);
00631 }
00632 if (!res)
00633 res = ast_waitstream(chan, ints);
00634 if (!res)
00635 res = ast_say_number(chan, tm.tm_year + 1900, ints, lang);
00636 return res;
00637 }
00638
00639 int ast_say_datetime_from_now(struct ast_channel *chan, time_t t, char *ints, char *lang)
00640 {
00641 int res=0;
00642 time_t nowt;
00643 int daydiff;
00644 struct tm tm;
00645 struct tm now;
00646 char fn[256];
00647
00648 time(&nowt);
00649
00650 localtime_r(&t,&tm);
00651 localtime_r(&nowt,&now);
00652 daydiff = now.tm_yday - tm.tm_yday;
00653 if ((daydiff < 0) || (daydiff > 6)) {
00654
00655 if (!res) {
00656 snprintf(fn, sizeof(fn), "digits/mon-%d", tm.tm_mon);
00657 res = ast_streamfile(chan, fn, lang);
00658 if (!res)
00659 res = ast_waitstream(chan, ints);
00660 }
00661 if (!res)
00662 res = ast_say_number(chan, tm.tm_mday, ints, lang);
00663
00664 } else if (daydiff) {
00665
00666 if (!res) {
00667 snprintf(fn, sizeof(fn), "digits/day-%d", tm.tm_wday);
00668 res = ast_streamfile(chan, fn, lang);
00669 if (!res)
00670 res = ast_waitstream(chan, ints);
00671 }
00672 }
00673 if (!res)
00674 res = ast_say_time(chan, t, ints, lang);
00675 return res;
00676 }
00677