Index: include/asterisk/say.h =================================================================== RCS file: /usr/cvsroot/asterisk/include/asterisk/say.h,v retrieving revision 1.8 diff -u -r1.8 say.h --- include/asterisk/say.h 29 Apr 2004 02:30:14 -0000 1.8 +++ include/asterisk/say.h 2 May 2004 20:16:44 -0000 @@ -61,6 +61,10 @@ */ int ast_say_digit_str(struct ast_channel *chan, char *num, char *ints, char *lang); int ast_say_digit_str_full(struct ast_channel *chan, char *num, char *ints, char *lang, int audiofd, int ctrlfd); +int ast_say_character_str(struct ast_channel *chan, char *num, char *ints, char *lang); +int ast_say_character_str_full(struct ast_channel *chan, char *num, char *ints, char *lang, int audiofd, int ctrlfd); +int ast_say_phonetic_str(struct ast_channel *chan, char *num, char *ints, char *lang); +int ast_say_phonetic_str_full(struct ast_channel *chan, char *num, char *ints, char *lang, int audiofd, int ctrlfd); int ast_say_datetime(struct ast_channel *chan, time_t t, char *ints, char *lang); Index: pbx.c =================================================================== RCS file: /usr/cvsroot/asterisk/pbx.c,v retrieving revision 1.116 diff -u -r1.116 pbx.c --- pbx.c 29 Apr 2004 02:30:14 -0000 1.116 +++ pbx.c 2 May 2004 20:16:45 -0000 @@ -169,6 +169,8 @@ static int pbx_builtin_gotoiftime(struct ast_channel *, void *); static int pbx_builtin_saynumber(struct ast_channel *, void *); static int pbx_builtin_saydigits(struct ast_channel *, void *); +static int pbx_builtin_saycharacters(struct ast_channel *, void *); +static int pbx_builtin_sayphonetic(struct ast_channel *, void *); int pbx_builtin_setvar(struct ast_channel *, void *); void pbx_builtin_setvar_helper(struct ast_channel *chan, char *name, char *value); char *pbx_builtin_getvar_helper(struct ast_channel *chan, char *name); @@ -293,6 +295,14 @@ "Say Digits", " SayDigits(digits): Says the passed digits\n" }, + { "SayAlpha", pbx_builtin_saycharacters, +"Say Alpha", +" SayAlpha(string): Spells the passed string\n" }, + + { "SayPhonetic", pbx_builtin_sayphonetic, +"Say Phonetic", +" SayPhonetic(string): Spells the passed string with phonetic alphabet\n" }, + { "SetAccount", pbx_builtin_setaccount, "Sets account code", " SetAccount([account]): Set the channel account code for billing\n" @@ -4598,6 +4608,22 @@ int res = 0; if (data) res = ast_say_digit_str(chan, (char *)data, "", chan->language); + return res; +} + +static int pbx_builtin_saycharacters(struct ast_channel *chan, void *data) +{ + int res = 0; + if (data) + res = ast_say_character_str(chan, (char *)data, "", chan->language); + return res; +} + +static int pbx_builtin_sayphonetic(struct ast_channel *chan, void *data) +{ + int res = 0; + if (data) + res = ast_say_phonetic_str(chan, (char *)data, "", chan->language); return res; } Index: say.c =================================================================== RCS file: /usr/cvsroot/asterisk/say.c,v retrieving revision 1.20 diff -u -r1.20 say.c --- say.c 29 Apr 2004 04:41:37 -0000 1.20 +++ say.c 2 May 2004 20:16:45 -0000 @@ -45,13 +45,13 @@ snprintf(fn, sizeof(fn), "digits/pound"); break; default: - if((fn2[num] >= '0') && (fn2[num] <= '9')){ /* Must be in {0-9} */ + if((fn2[num] >= '0') && (fn2[num] <= '9')){ /* Must be in {0-9} */ snprintf(fn, sizeof(fn), "digits/%c", fn2[num]); } - } + } if(strlen(fn)){ /* if length == 0, then skip this digit as it is invalid */ res = ast_streamfile(chan, fn, lang); - if (!res) + if (!res) res = ast_waitstream(chan, ints); ast_stopstream(chan); } @@ -60,6 +60,179 @@ return res; } +int ast_say_character_str(struct ast_channel *chan, char *fn2, char *ints, char *lang) +{ + /* XXX Merge with full version? XXX */ + char fn[256] = ""; + char ltr; + int num = 0; + int res = 0; + while(fn2[num] && !res) { + fn[0] = '\0'; + switch (fn2[num]) { + case ('*'): + snprintf(fn, sizeof(fn), "digits/star"); + break; + case ('#'): + snprintf(fn, sizeof(fn), "digits/pound"); + break; + case ('0'): + case ('1'): + case ('2'): + case ('3'): + case ('4'): + case ('5'): + case ('6'): + case ('7'): + case ('8'): + case ('9'): + snprintf(fn, sizeof(fn), "digits/%c", fn2[num]); + break; + case ('!'): + strncpy(fn, "exclaimation-point", sizeof(fn)); + break; + case ('@'): + strncpy(fn, "at", sizeof(fn)); + break; + case ('$'): + strncpy(fn, "dollar", sizeof(fn)); + break; + case ('-'): + strncpy(fn, "dash", sizeof(fn)); + break; + case ('.'): + strncpy(fn, "dot", sizeof(fn)); + break; + case ('='): + strncpy(fn, "equals", sizeof(fn)); + break; + case ('+'): + strncpy(fn, "plus", sizeof(fn)); + break; + case ('/'): + strncpy(fn, "slash", sizeof(fn)); + break; + case (' '): + strncpy(fn, "space", sizeof(fn)); + break; + default: + ltr = fn2[num]; + if ('A' <= ltr && ltr <= 'Z') ltr += 'a' - 'A'; /* file names are all lower-case */ + snprintf(fn, sizeof(fn), "letters/%c", ltr); + } + if(strlen(fn)){ /* if length == 0, then skip this digit as it is invalid */ + res = ast_streamfile(chan, fn, lang); + if (!res) + res = ast_waitstream(chan, ints); + } ast_stopstream(chan); + num++; + } + return res; +} + +int ast_say_phonetic_str(struct ast_channel *chan, char *fn2, char *ints, char *lang) +{ + /* XXX Merge with full version? XXX */ + char fn[256] = ""; + char ltr; + int num = 0; + int res = 0; + int temp; + int play; + char hex[3]; +/* while(fn2[num] && !res) { */ + while(fn2[num]) { + play=1; + switch (fn2[num]) { + case ('*'): + snprintf(fn, sizeof(fn), "digits/star"); + break; + case ('#'): + snprintf(fn, sizeof(fn), "digits/pound"); + break; + case ('0'): + case ('1'): + case ('2'): + case ('3'): + case ('4'): + case ('5'): + case ('6'): + case ('7'): + case ('8'): + snprintf(fn, sizeof(fn), "digits/%c", fn2[num]); + break; + case ('!'): + strncpy(fn, "exclaimation-point", sizeof(fn)); + break; + case ('@'): + strncpy(fn, "at", sizeof(fn)); + break; + case ('$'): + strncpy(fn, "dollar", sizeof(fn)); + break; + case ('-'): + strncpy(fn, "dash", sizeof(fn)); + break; + case ('.'): + strncpy(fn, "dot", sizeof(fn)); + break; + case ('='): + strncpy(fn, "equals", sizeof(fn)); + break; + case ('+'): + strncpy(fn, "plus", sizeof(fn)); + break; + case ('/'): + strncpy(fn, "slash", sizeof(fn)); + break; + case (' '): + strncpy(fn, "space", sizeof(fn)); + break; + case ('%'): + play=0; + /* check if we have 2 chars after the % */ + if (strlen(fn2)>num+2) + { + hex[0]=fn2[num+1]; + hex[1]=fn2[num+2]; + hex[2]='\0'; + if (sscanf(hex,"%x", &temp)) + { /* Hex to char convertion successfull */ + fn2[num+2]=temp; + num++; + if (temp==37) + { /* If it is a percent, play it now */ + strncpy(fn, "percent", sizeof(fn)); + num++; + play=1; + } + /* check for invalid characters */ + if ((temp<32) || (temp>126)) + { + num++; + } + } + } + else + num++; + break; + default: /* '9' falls through to here, too */ + ltr = fn2[num]; + if ('A' <= ltr && ltr <= 'Z') ltr += 'a' - 'A'; /* file names are all lower-case */ + snprintf(fn, sizeof(fn), "phonetic/%c", ltr); + } + if (play) + { + res = ast_streamfile(chan, fn, lang); + if (!res) + res = ast_waitstream(chan, ints); + ast_stopstream(chan); + } + num++; + } + return res; +} + int ast_say_digit_str_full(struct ast_channel *chan, char *fn2, char *ints, char *lang, int audiofd, int ctrlfd) { char fn[256] = ""; @@ -67,6 +240,141 @@ int res = 0; while(fn2[num] && !res) { snprintf(fn, sizeof(fn), "digits/%c", fn2[num]); + res = ast_streamfile(chan, fn, lang); + if (!res) + res = ast_waitstream_full(chan, ints, audiofd, ctrlfd); + ast_stopstream(chan); + num++; + } + return res; +} + +int ast_say_character_str_full(struct ast_channel *chan, char *fn2, char *ints, char *lang, int audiofd, int ctrlfd) +{ + char fn[256] = ""; + char ltr; + int num = 0; + int res = 0; + while(fn2[num] && !res) { + switch (fn2[num]) { + case ('*'): + snprintf(fn, sizeof(fn), "digits/star"); + break; + case ('#'): + snprintf(fn, sizeof(fn), "digits/pound"); + break; + case ('0'): + case ('1'): + case ('2'): + case ('3'): + case ('4'): + case ('5'): + case ('6'): + case ('7'): + case ('8'): + case ('9'): + snprintf(fn, sizeof(fn), "digits/%c", fn2[num]); + break; + case ('!'): + strncpy(fn, "exclaimation-point", sizeof(fn)); + break; + case ('@'): + strncpy(fn, "at", sizeof(fn)); + break; + case ('$'): + strncpy(fn, "dollar", sizeof(fn)); + break; + case ('-'): + strncpy(fn, "dash", sizeof(fn)); + break; + case ('.'): + strncpy(fn, "dot", sizeof(fn)); + break; + case ('='): + strncpy(fn, "equals", sizeof(fn)); + break; + case ('+'): + strncpy(fn, "plus", sizeof(fn)); + break; + case ('/'): + strncpy(fn, "slash", sizeof(fn)); + break; + case (' '): + strncpy(fn, "space", sizeof(fn)); + break; + default: + ltr = fn2[num]; + if ('A' <= ltr && ltr <= 'Z') ltr += 'a' - 'A'; /* file names are all lower-case */ + snprintf(fn, sizeof(fn), "letters/%c", ltr); + } + /* snprintf(fn, sizeof(fn), "digits/%c", fn2[num]); */ + res = ast_streamfile(chan, fn, lang); + if (!res) + res = ast_waitstream_full(chan, ints, audiofd, ctrlfd); + ast_stopstream(chan); + num++; + } + return res; +} + +int ast_say_phonetic_str_full(struct ast_channel *chan, char *fn2, char *ints, char *lang, int audiofd, int ctrlfd) +{ + char fn[256] = ""; + char ltr; + int num = 0; + int res = 0; + while(fn2[num] && !res) { + switch (fn2[num]) { + case ('*'): + snprintf(fn, sizeof(fn), "digits/star"); + break; + case ('#'): + snprintf(fn, sizeof(fn), "digits/pound"); + break; + case ('0'): + case ('1'): + case ('2'): + case ('3'): + case ('4'): + case ('5'): + case ('6'): + case ('7'): + case ('8'): + snprintf(fn, sizeof(fn), "digits/%c", fn2[num]); + break; + case ('!'): + strncpy(fn, "exclaimation-point", sizeof(fn)); + break; + case ('@'): + strncpy(fn, "at", sizeof(fn)); + break; + case ('$'): + strncpy(fn, "dollar", sizeof(fn)); + break; + case ('-'): + strncpy(fn, "dash", sizeof(fn)); + break; + case ('.'): + strncpy(fn, "dot", sizeof(fn)); + break; + case ('='): + strncpy(fn, "equals", sizeof(fn)); + break; + case ('+'): + strncpy(fn, "plus", sizeof(fn)); + break; + case ('/'): + strncpy(fn, "slash", sizeof(fn)); + break; + case (' '): + strncpy(fn, "space", sizeof(fn)); + break; + default: /* '9' falls here... */ + ltr = fn2[num]; + if ('A' <= ltr && ltr <= 'Z') ltr += 'a' - 'A'; /* file names are all lower-case */ + snprintf(fn, sizeof(fn), "phonetic/%c", ltr); + } + /* snprintf(fn, sizeof(fn), "digits/%c", fn2[num]); */ res = ast_streamfile(chan, fn, lang); if (!res) res = ast_waitstream_full(chan, ints, audiofd, ctrlfd); Index: apps/app_agi.c =================================================================== RCS file: /usr/cvsroot/asterisk/apps/app_agi.c,v retrieving revision 1.36 diff -u -r1.36 app_agi.c --- apps/app_agi.c 23 Apr 2004 04:38:11 -0000 1.36 +++ apps/app_agi.c 2 May 2004 20:16:45 -0000 @@ -385,10 +385,12 @@ { int res; int num; + if (argc != 4) return RESULT_SHOWUSAGE; if (sscanf(argv[2], "%i", &num) != 1) return RESULT_SHOWUSAGE; + res = ast_say_digit_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl); if (res == 1) /* New command */ return RESULT_SUCCESS; @@ -417,6 +419,23 @@ return RESULT_FAILURE; } +static int handle_sayphonetic(struct ast_channel *chan, AGI *agi, int argc, char *argv[]) +{ + int res; + + if (argc != 4) + return RESULT_SHOWUSAGE; + + res = ast_say_phonetic_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl); + if (res == 1) /* New command */ + return RESULT_SUCCESS; + fdprintf(agi->fd, "200 result=%d\n", res); + if (res >= 0) + return RESULT_SUCCESS; + else + return RESULT_FAILURE; +} + static int handle_getdata(struct ast_channel *chan, AGI *agi, int argc, char *argv[]) { int res; @@ -1031,6 +1050,13 @@ " completes without a digit being pressed, or the ASCII numerical value of the\n" " digit if one was pressed or -1 on error/hangup.\n"; +static char usage_sayphonetic[] = +" Usage: SAY PHONETIC \n" +" Say a given character string with phonetics, returning early if any of the given DTMF digits\n" +" are received on the channel. Returns 0 if playback completes without a digit\n" +" being pressed, or the ASCII numerical value of the digit if one was pressed or\n" +" -1 on error/hangup.\n"; + static char usage_getdata[] = " Usage: GET DATA [timeout] [max digits]\n" " Stream the given file, and recieve DTMF data. Returns the digits recieved\n" @@ -1080,6 +1106,7 @@ { { "send", "image", NULL }, handle_sendimage, "Sends images to channels supporting it", usage_sendimage }, { { "say", "digits", NULL }, handle_saydigits, "Says a given digit string", usage_saydigits }, { { "say", "number", NULL }, handle_saynumber, "Says a given number", usage_saynumber }, + { { "say", "phonetic", NULL }, handle_sayphonetic, "Says a given character string with phonetics", usage_sayphonetic }, { { "say", "time", NULL }, handle_saytime, "Says a given time", usage_saytime }, { { "get", "data", NULL }, handle_getdata, "Gets data on a channel", usage_getdata }, { { "set", "context", NULL }, handle_setcontext, "Sets channel context", usage_setcontext },