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