00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
#include <stdio.h>
00015
#include <stdlib.h>
00016
#include <pthread.h>
00017
#include <string.h>
00018
#include <sys/time.h>
00019
#include <signal.h>
00020
#include <errno.h>
00021
#include <unistd.h>
00022
#include <dirent.h>
00023
#include <asterisk/channel.h>
00024
#include <asterisk/pbx.h>
00025
#include <asterisk/file.h>
00026
#include <asterisk/app.h>
00027
#include <asterisk/dsp.h>
00028
#include <asterisk/logger.h>
00029
#include <asterisk/options.h>
00030
#include <asterisk/utils.h>
00031
#include "asterisk.h"
00032
#include "astconf.h"
00033
00034
00035
00036 int ast_app_getdata(
struct ast_channel *c,
char *prompt,
char *s,
int maxlen,
int timeout)
00037 {
00038
int res,to,fto;
00039
00040
if (prompt) {
00041 res =
ast_streamfile(c, prompt, c->
language);
00042
if (res < 0)
00043
return res;
00044 }
00045 fto = c->
pbx ? c->
pbx->
rtimeout * 1000 : 6000;
00046 to = c->
pbx ? c->
pbx->
dtimeout * 1000 : 2000;
00047
00048
if (timeout > 0) fto = to = timeout;
00049
if (timeout < 0) fto = to = 1000000000;
00050 res =
ast_readstring(c,
s, maxlen, to, fto,
"#");
00051
return res;
00052 }
00053
00054
00055 int ast_app_getdata_full(
struct ast_channel *c,
char *prompt,
char *s,
int maxlen,
int timeout,
int audiofd,
int ctrlfd)
00056 {
00057
int res,to,fto;
00058
if (prompt) {
00059 res =
ast_streamfile(c, prompt, c->
language);
00060
if (res < 0)
00061
return res;
00062 }
00063 fto = 6000;
00064 to = 2000;
00065
if (timeout > 0) fto = to = timeout;
00066
if (timeout < 0) fto = to = 1000000000;
00067 res =
ast_readstring_full(c,
s, maxlen, to, fto,
"#", audiofd, ctrlfd);
00068
return res;
00069 }
00070
00071 int ast_app_getvoice(
struct ast_channel *c,
char *dest,
char *dstfmt,
char *prompt,
int silence,
int maxsec)
00072 {
00073
int res;
00074
struct ast_filestream *writer;
00075
int rfmt;
00076
int totalms=0, total;
00077
00078
struct ast_frame *f;
00079
struct ast_dsp *sildet;
00080
00081
if (prompt) {
00082 res =
ast_streamfile(c, prompt, c->
language);
00083
if (res < 0)
00084
return res;
00085 res =
ast_waitstream(c,
"");
00086
if (res < 0)
00087
return res;
00088 }
00089 rfmt = c->
readformat;
00090 res =
ast_set_read_format(c,
AST_FORMAT_SLINEAR);
00091
if (res < 0) {
00092
ast_log(
LOG_WARNING,
"Unable to set to linear mode, giving up\n");
00093
return -1;
00094 }
00095 sildet =
ast_dsp_new();
00096
if (!sildet) {
00097
ast_log(
LOG_WARNING,
"Unable to create silence detector :(\n");
00098
return -1;
00099 }
00100 writer =
ast_writefile(dest, dstfmt,
"Voice file", 0, 0, 0666);
00101
if (!writer) {
00102
ast_log(
LOG_WARNING,
"Unable to open file '%s' in format '%s' for writing\n", dest, dstfmt);
00103
ast_dsp_free(sildet);
00104
return -1;
00105 }
00106
for(;;) {
00107
if ((res =
ast_waitfor(c, 2000)) < 0) {
00108
ast_log(
LOG_NOTICE,
"Waitfor failed while recording file '%s' format '%s'\n", dest, dstfmt);
00109
break;
00110 }
00111
if (res) {
00112 f =
ast_read(c);
00113
if (!f) {
00114
ast_log(
LOG_NOTICE,
"Hungup while recording file '%s' format '%s'\n", dest, dstfmt);
00115
break;
00116 }
00117
if ((f->frametype ==
AST_FRAME_DTMF) && (f->subclass ==
'#')) {
00118
00119
ast_frfree(f);
00120
break;
00121 }
else if (f->frametype ==
AST_FRAME_VOICE) {
00122
ast_dsp_silence(sildet, f, &total);
00123
if (total > silence) {
00124
00125
ast_frfree(f);
00126
break;
00127 }
00128 totalms += f->samples / 8;
00129
if (totalms > maxsec * 1000) {
00130
00131
ast_log(
LOG_NOTICE,
"Constraining voice on '%s' to %d seconds\n", c->
name, maxsec);
00132
ast_frfree(f);
00133
break;
00134 }
00135 }
00136
ast_frfree(f);
00137 }
00138 }
00139 res =
ast_set_read_format(c, rfmt);
00140
if (res)
00141
ast_log(
LOG_WARNING,
"Unable to restore read format on '%s'\n", c->
name);
00142
ast_dsp_free(sildet);
00143
ast_closestream(writer);
00144
return 0;
00145 }
00146
00147 int ast_app_has_voicemail(
const char *mailbox)
00148 {
00149 DIR *dir;
00150
struct dirent *de;
00151
char fn[256];
00152
char tmp[256]=
"";
00153
char *mb, *cur;
00154
char *context;
00155
int ret;
00156
00157
if (ast_strlen_zero(mailbox))
00158
return 0;
00159
if (strchr(mailbox,
',')) {
00160 strncpy(tmp, mailbox,
sizeof(tmp));
00161 mb = tmp;
00162 ret = 0;
00163
while((cur = strsep(&mb,
","))) {
00164
if (!ast_strlen_zero(cur)) {
00165
if (
ast_app_has_voicemail(cur))
00166
return 1;
00167 }
00168 }
00169
return 0;
00170 }
00171 strncpy(tmp, mailbox,
sizeof(tmp) - 1);
00172 context = strchr(tmp,
'@');
00173
if (context) {
00174 *context =
'\0';
00175 context++;
00176 }
else
00177 context =
"default";
00178 snprintf(fn,
sizeof(fn),
"%s/voicemail/%s/%s/INBOX", (
char *)
ast_config_AST_SPOOL_DIR, context, tmp);
00179 dir = opendir(fn);
00180
if (!dir)
00181
return 0;
00182
while ((de = readdir(dir))) {
00183
if (!strncasecmp(de->d_name,
"msg", 3))
00184
break;
00185 }
00186 closedir(dir);
00187
if (de)
00188
return 1;
00189
return 0;
00190 }
00191
00192 int ast_app_messagecount(
const char *mailbox,
int *newmsgs,
int *oldmsgs)
00193 {
00194 DIR *dir;
00195
struct dirent *de;
00196
char fn[256];
00197
char tmp[256]=
"";
00198
char *mb, *cur;
00199
char *context;
00200
int ret;
00201
if (newmsgs)
00202 *newmsgs = 0;
00203
if (oldmsgs)
00204 *oldmsgs = 0;
00205
00206
if (ast_strlen_zero(mailbox))
00207
return 0;
00208
if (strchr(mailbox,
',')) {
00209
int tmpnew, tmpold;
00210 strncpy(tmp, mailbox,
sizeof(tmp));
00211 mb = tmp;
00212 ret = 0;
00213
while((cur = strsep(&mb,
", "))) {
00214
if (!ast_strlen_zero(cur)) {
00215
if (
ast_app_messagecount(cur, newmsgs ? &tmpnew : NULL, oldmsgs ? &tmpold : NULL))
00216
return -1;
00217
else {
00218
if (newmsgs)
00219 *newmsgs += tmpnew;
00220
if (oldmsgs)
00221 *oldmsgs += tmpold;
00222 }
00223 }
00224 }
00225
return 0;
00226 }
00227 strncpy(tmp, mailbox,
sizeof(tmp) - 1);
00228 context = strchr(tmp,
'@');
00229
if (context) {
00230 *context =
'\0';
00231 context++;
00232 }
else
00233 context =
"default";
00234
if (newmsgs) {
00235 snprintf(fn,
sizeof(fn),
"%s/voicemail/%s/%s/INBOX", (
char *)
ast_config_AST_SPOOL_DIR, context, tmp);
00236 dir = opendir(fn);
00237
if (dir) {
00238
while ((de = readdir(dir))) {
00239
if ((strlen(de->d_name) > 3) && !strncasecmp(de->d_name,
"msg", 3) &&
00240 !strcasecmp(de->d_name + strlen(de->d_name) - 3,
"txt"))
00241 (*newmsgs)++;
00242
00243 }
00244 closedir(dir);
00245 }
00246 }
00247
if (oldmsgs) {
00248 snprintf(fn,
sizeof(fn),
"%s/voicemail/%s/%s/Old", (
char *)
ast_config_AST_SPOOL_DIR, context, tmp);
00249 dir = opendir(fn);
00250
if (dir) {
00251
while ((de = readdir(dir))) {
00252
if ((strlen(de->d_name) > 3) && !strncasecmp(de->d_name,
"msg", 3) &&
00253 !strcasecmp(de->d_name + strlen(de->d_name) - 3,
"txt"))
00254 (*oldmsgs)++;
00255
00256 }
00257 closedir(dir);
00258 }
00259 }
00260
return 0;
00261 }
00262
00263 int ast_dtmf_stream(
struct ast_channel *chan,
struct ast_channel *peer,
char *digits,
int between)
00264 {
00265
char *ptr=NULL;
00266
int res=0;
00267
struct ast_frame f;
00268
if (!between)
00269 between = 100;
00270
00271
if (peer)
00272 res =
ast_autoservice_start(peer);
00273
00274
if (!res) {
00275 res =
ast_waitfor(chan,100);
00276
if (res > -1) {
00277
for (ptr=digits;*ptr;*ptr++) {
00278
if (*ptr ==
'w') {
00279 res =
ast_safe_sleep(chan, 500);
00280
if (res)
00281
break;
00282
continue;
00283 }
00284 memset(&f, 0,
sizeof(f));
00285 f.frametype =
AST_FRAME_DTMF;
00286 f.subclass = *ptr;
00287 f.src =
"ast_dtmf_stream";
00288
if (strchr(
"0123456789*#abcdABCD",*ptr)==NULL) {
00289
ast_log(
LOG_WARNING,
"Illegal DTMF character '%c' in string. (0-9*#aAbBcCdD allowed)\n",*ptr);
00290 }
else {
00291 res =
ast_write(chan, &f);
00292
if (res)
00293
break;
00294
00295 res =
ast_safe_sleep(chan,between);
00296
if (res)
00297
break;
00298 }
00299 }
00300 }
00301
if (peer)
00302 res =
ast_autoservice_stop(peer);
00303 }
00304
return res;
00305 }
00306
00307 struct linear_state {
00308 int fd;
00309 int autoclose;
00310 int allowoverride;
00311 int origwfmt;
00312 };
00313
00314
static void linear_release(
struct ast_channel *chan,
void *params)
00315 {
00316
struct linear_state *ls = params;
00317
if (ls->origwfmt &&
ast_set_write_format(chan, ls->origwfmt)) {
00318
ast_log(
LOG_WARNING,
"Unable to restore channel '%s' to format '%d'\n", chan->
name, ls->origwfmt);
00319 }
00320
if (ls->autoclose)
00321 close(ls->fd);
00322
free(params);
00323 }
00324
00325
static int linear_generator(
struct ast_channel *chan,
void *data,
int len,
int samples)
00326 {
00327
struct ast_frame f;
00328
short buf[2048 +
AST_FRIENDLY_OFFSET / 2];
00329
struct linear_state *ls = data;
00330
int res;
00331 len = samples * 2;
00332
if (len >
sizeof(buf) -
AST_FRIENDLY_OFFSET) {
00333
ast_log(LOG_WARNING,
"Can't generate %d bytes of data!\n" ,len);
00334 len =
sizeof(buf) -
AST_FRIENDLY_OFFSET;
00335 }
00336 memset(&f, 0,
sizeof(f));
00337 res = read(ls->fd, buf + AST_FRIENDLY_OFFSET/2, len);
00338
if (res > 0) {
00339 f.
frametype =
AST_FRAME_VOICE;
00340 f.
subclass =
AST_FORMAT_SLINEAR;
00341 f.
data = buf +
AST_FRIENDLY_OFFSET/2;
00342 f.
datalen = res;
00343 f.
samples = res / 2;
00344 f.
offset =
AST_FRIENDLY_OFFSET;
00345
ast_write(chan, &f);
00346
if (res == len)
00347
return 0;
00348 }
00349
return -1;
00350 }
00351
00352
static void *linear_alloc(
struct ast_channel *chan,
void *params)
00353 {
00354
struct linear_state *ls;
00355
00356
if (params) {
00357 ls = params;
00358
if (ls->allowoverride)
00359 chan->
writeinterrupt = 1;
00360
else
00361 chan->
writeinterrupt = 0;
00362 ls->origwfmt = chan->
writeformat;
00363
if (
ast_set_write_format(chan, AST_FORMAT_SLINEAR)) {
00364
ast_log(LOG_WARNING,
"Unable to set '%s' to linear format (write)\n", chan->
name);
00365
free(ls);
00366 ls = params = NULL;
00367 }
00368 }
00369
return params;
00370 }
00371
00372
static struct ast_generator linearstream =
00373 {
00374 alloc: linear_alloc,
00375 release: linear_release,
00376 generate: linear_generator,
00377 };
00378
00379 int ast_linear_stream(
struct ast_channel *chan,
const char *filename,
int fd,
int allowoverride)
00380 {
00381
struct linear_state *lin;
00382
char tmpf[256] =
"";
00383
int res = -1;
00384
int autoclose = 0;
00385
if (fd < 0) {
00386
if (!filename || ast_strlen_zero(filename))
00387
return -1;
00388 autoclose = 1;
00389
if (filename[0] ==
'/')
00390 strncpy(tmpf, filename,
sizeof(tmpf) - 1);
00391
else
00392 snprintf(tmpf,
sizeof(tmpf),
"%s/%s/%s", (
char *)
ast_config_AST_VAR_DIR,
"sounds", filename);
00393 fd = open(tmpf, O_RDONLY);
00394
if (fd < 0){
00395
ast_log(
LOG_WARNING,
"Unable to open file '%s': %s\n", tmpf, strerror(errno));
00396
return -1;
00397 }
00398 }
00399 lin =
malloc(
sizeof(
struct linear_state));
00400
if (lin) {
00401 memset(lin, 0,
sizeof(lin));
00402 lin->fd = fd;
00403 lin->allowoverride = allowoverride;
00404 lin->autoclose = autoclose;
00405 res =
ast_activate_generator(chan, &linearstream, lin);
00406 }
00407
return res;
00408 }
00409
00410 int ast_control_streamfile(
struct ast_channel *chan,
char *file,
char *fwd,
char *rev,
char *stop,
char *pause,
int skipms)
00411 {
00412
struct timeval started, ended;
00413
long elapsed = 0,last_elapsed =0;
00414
char *breaks;
00415
int blen=2;
00416
int res=0;
00417
00418
if (stop)
00419 blen += strlen(stop);
00420
if (pause)
00421 blen += strlen(pause);
00422
00423 breaks = alloca(blen + 1);
00424 breaks[0] =
'\0';
00425 strcat(breaks, stop);
00426 strcat(breaks, pause);
00427
00428
if (chan->
_state !=
AST_STATE_UP)
00429 res =
ast_answer(chan);
00430
00431
if (chan)
00432
ast_stopstream(chan);
00433
00434
for (;;) {
00435 gettimeofday(&started,NULL);
00436
00437
if (chan)
00438
ast_stopstream(chan);
00439 res =
ast_streamfile(chan, file, chan->
language);
00440
if (!res) {
00441 res = 1;
00442
if (elapsed) {
00443
ast_stream_fastforward(chan->
stream, elapsed);
00444 last_elapsed = elapsed - 200;
00445 }
00446
if (res)
00447 res =
ast_waitstream_fr(chan, breaks, fwd, rev, skipms);
00448
else
00449
break;
00450 }
00451
00452
if (res < 1)
00453
break;
00454
00455
if (pause != NULL && strchr(pause, res)) {
00456 gettimeofday(&ended, NULL);
00457 elapsed = (((ended.tv_sec * 1000) + ended.tv_usec / 1000) - ((started.tv_sec * 1000) + started.tv_usec / 1000) + last_elapsed);
00458
for(;;) {
00459
if (chan)
00460
ast_stopstream(chan);
00461 res =
ast_waitfordigit(chan, 1000);
00462
if(res == 0)
00463
continue;
00464
else if(res == -1 || strchr(pause, res) || (stop && strchr(stop, res)))
00465
break;
00466 }
00467
if (res == *pause) {
00468 res = 0;
00469
continue;
00470 }
00471 }
00472
if (res == -1)
00473
break;
00474
00475
if (stop && strchr(stop, res)) {
00476 res = 0;
00477
break;
00478 }
00479 }
00480
if (chan)
00481
ast_stopstream(chan);
00482
00483
return res;
00484 }