app.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014
  1. /*
  2. * Asterisk -- A telephony toolkit for Linux.
  3. *
  4. * Convenient Application Routines
  5. *
  6. * Copyright (C) 1999-2004, Digium, Inc.
  7. *
  8. * Mark Spencer <markster@digium.com>
  9. *
  10. * This program is free software, distributed under the terms of
  11. * the GNU General Public License
  12. */
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include <sys/time.h>
  17. #include <signal.h>
  18. #include <errno.h>
  19. #include <unistd.h>
  20. #include <dirent.h>
  21. #include <asterisk/channel.h>
  22. #include <asterisk/pbx.h>
  23. #include <asterisk/file.h>
  24. #include <asterisk/app.h>
  25. #include <asterisk/dsp.h>
  26. #include <asterisk/logger.h>
  27. #include <asterisk/options.h>
  28. #include <asterisk/utils.h>
  29. #include <asterisk/lock.h>
  30. #include "asterisk.h"
  31. #include "astconf.h"
  32. #define MAX_OTHER_FORMATS 10
  33. /* set timeout to 0 for "standard" timeouts. Set timeout to -1 for
  34. "ludicrous time" (essentially never times out) */
  35. int ast_app_getdata(struct ast_channel *c, char *prompt, char *s, int maxlen, int timeout)
  36. {
  37. int res,to,fto;
  38. /* XXX Merge with full version? XXX */
  39. if (maxlen)
  40. s[0] = '\0';
  41. if (prompt) {
  42. res = ast_streamfile(c, prompt, c->language);
  43. if (res < 0)
  44. return res;
  45. }
  46. fto = c->pbx ? c->pbx->rtimeout * 1000 : 6000;
  47. to = c->pbx ? c->pbx->dtimeout * 1000 : 2000;
  48. if (timeout > 0) fto = to = timeout;
  49. if (timeout < 0) fto = to = 1000000000;
  50. res = ast_readstring(c, s, maxlen, to, fto, "#");
  51. return res;
  52. }
  53. int ast_app_getdata_full(struct ast_channel *c, char *prompt, char *s, int maxlen, int timeout, int audiofd, int ctrlfd)
  54. {
  55. int res,to,fto;
  56. if (prompt) {
  57. res = ast_streamfile(c, prompt, c->language);
  58. if (res < 0)
  59. return res;
  60. }
  61. fto = 6000;
  62. to = 2000;
  63. if (timeout > 0) fto = to = timeout;
  64. if (timeout < 0) fto = to = 1000000000;
  65. res = ast_readstring_full(c, s, maxlen, to, fto, "#", audiofd, ctrlfd);
  66. return res;
  67. }
  68. int ast_app_getvoice(struct ast_channel *c, char *dest, char *dstfmt, char *prompt, int silence, int maxsec)
  69. {
  70. int res;
  71. struct ast_filestream *writer;
  72. int rfmt;
  73. int totalms=0, total;
  74. struct ast_frame *f;
  75. struct ast_dsp *sildet;
  76. /* Play prompt if requested */
  77. if (prompt) {
  78. res = ast_streamfile(c, prompt, c->language);
  79. if (res < 0)
  80. return res;
  81. res = ast_waitstream(c,"");
  82. if (res < 0)
  83. return res;
  84. }
  85. rfmt = c->readformat;
  86. res = ast_set_read_format(c, AST_FORMAT_SLINEAR);
  87. if (res < 0) {
  88. ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
  89. return -1;
  90. }
  91. sildet = ast_dsp_new();
  92. if (!sildet) {
  93. ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
  94. return -1;
  95. }
  96. writer = ast_writefile(dest, dstfmt, "Voice file", 0, 0, 0666);
  97. if (!writer) {
  98. ast_log(LOG_WARNING, "Unable to open file '%s' in format '%s' for writing\n", dest, dstfmt);
  99. ast_dsp_free(sildet);
  100. return -1;
  101. }
  102. for(;;) {
  103. if ((res = ast_waitfor(c, 2000)) < 0) {
  104. ast_log(LOG_NOTICE, "Waitfor failed while recording file '%s' format '%s'\n", dest, dstfmt);
  105. break;
  106. }
  107. if (res) {
  108. f = ast_read(c);
  109. if (!f) {
  110. ast_log(LOG_NOTICE, "Hungup while recording file '%s' format '%s'\n", dest, dstfmt);
  111. break;
  112. }
  113. if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '#')) {
  114. /* Ended happily with DTMF */
  115. ast_frfree(f);
  116. break;
  117. } else if (f->frametype == AST_FRAME_VOICE) {
  118. ast_dsp_silence(sildet, f, &total);
  119. if (total > silence) {
  120. /* Ended happily with silence */
  121. ast_frfree(f);
  122. break;
  123. }
  124. totalms += f->samples / 8;
  125. if (totalms > maxsec * 1000) {
  126. /* Ended happily with too much stuff */
  127. ast_log(LOG_NOTICE, "Constraining voice on '%s' to %d seconds\n", c->name, maxsec);
  128. ast_frfree(f);
  129. break;
  130. }
  131. }
  132. ast_frfree(f);
  133. }
  134. }
  135. res = ast_set_read_format(c, rfmt);
  136. if (res)
  137. ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", c->name);
  138. ast_dsp_free(sildet);
  139. ast_closestream(writer);
  140. return 0;
  141. }
  142. int ast_app_has_voicemail(const char *mailbox)
  143. {
  144. DIR *dir;
  145. struct dirent *de;
  146. char fn[256];
  147. char tmp[256]="";
  148. char *mb, *cur;
  149. char *context;
  150. int ret;
  151. /* If no mailbox, return immediately */
  152. if (ast_strlen_zero(mailbox))
  153. return 0;
  154. if (strchr(mailbox, ',')) {
  155. strncpy(tmp, mailbox, sizeof(tmp) - 1);
  156. mb = tmp;
  157. ret = 0;
  158. while((cur = strsep(&mb, ","))) {
  159. if (!ast_strlen_zero(cur)) {
  160. if (ast_app_has_voicemail(cur))
  161. return 1;
  162. }
  163. }
  164. return 0;
  165. }
  166. strncpy(tmp, mailbox, sizeof(tmp) - 1);
  167. context = strchr(tmp, '@');
  168. if (context) {
  169. *context = '\0';
  170. context++;
  171. } else
  172. context = "default";
  173. snprintf(fn, sizeof(fn), "%s/voicemail/%s/%s/INBOX", (char *)ast_config_AST_SPOOL_DIR, context, tmp);
  174. dir = opendir(fn);
  175. if (!dir)
  176. return 0;
  177. while ((de = readdir(dir))) {
  178. if (!strncasecmp(de->d_name, "msg", 3))
  179. break;
  180. }
  181. closedir(dir);
  182. if (de)
  183. return 1;
  184. return 0;
  185. }
  186. int ast_app_messagecount(const char *mailbox, int *newmsgs, int *oldmsgs)
  187. {
  188. DIR *dir;
  189. struct dirent *de;
  190. char fn[256];
  191. char tmp[256]="";
  192. char *mb, *cur;
  193. char *context;
  194. int ret;
  195. if (newmsgs)
  196. *newmsgs = 0;
  197. if (oldmsgs)
  198. *oldmsgs = 0;
  199. /* If no mailbox, return immediately */
  200. if (ast_strlen_zero(mailbox))
  201. return 0;
  202. if (strchr(mailbox, ',')) {
  203. int tmpnew, tmpold;
  204. strncpy(tmp, mailbox, sizeof(tmp) - 1);
  205. mb = tmp;
  206. ret = 0;
  207. while((cur = strsep(&mb, ", "))) {
  208. if (!ast_strlen_zero(cur)) {
  209. if (ast_app_messagecount(cur, newmsgs ? &tmpnew : NULL, oldmsgs ? &tmpold : NULL))
  210. return -1;
  211. else {
  212. if (newmsgs)
  213. *newmsgs += tmpnew;
  214. if (oldmsgs)
  215. *oldmsgs += tmpold;
  216. }
  217. }
  218. }
  219. return 0;
  220. }
  221. strncpy(tmp, mailbox, sizeof(tmp) - 1);
  222. context = strchr(tmp, '@');
  223. if (context) {
  224. *context = '\0';
  225. context++;
  226. } else
  227. context = "default";
  228. if (newmsgs) {
  229. snprintf(fn, sizeof(fn), "%s/voicemail/%s/%s/INBOX", (char *)ast_config_AST_SPOOL_DIR, context, tmp);
  230. dir = opendir(fn);
  231. if (dir) {
  232. while ((de = readdir(dir))) {
  233. if ((strlen(de->d_name) > 3) && !strncasecmp(de->d_name, "msg", 3) &&
  234. !strcasecmp(de->d_name + strlen(de->d_name) - 3, "txt"))
  235. (*newmsgs)++;
  236. }
  237. closedir(dir);
  238. }
  239. }
  240. if (oldmsgs) {
  241. snprintf(fn, sizeof(fn), "%s/voicemail/%s/%s/Old", (char *)ast_config_AST_SPOOL_DIR, context, tmp);
  242. dir = opendir(fn);
  243. if (dir) {
  244. while ((de = readdir(dir))) {
  245. if ((strlen(de->d_name) > 3) && !strncasecmp(de->d_name, "msg", 3) &&
  246. !strcasecmp(de->d_name + strlen(de->d_name) - 3, "txt"))
  247. (*oldmsgs)++;
  248. }
  249. closedir(dir);
  250. }
  251. }
  252. return 0;
  253. }
  254. int ast_dtmf_stream(struct ast_channel *chan,struct ast_channel *peer,char *digits,int between)
  255. {
  256. char *ptr=NULL;
  257. int res=0;
  258. struct ast_frame f;
  259. if (!between)
  260. between = 100;
  261. if (peer)
  262. res = ast_autoservice_start(peer);
  263. if (!res) {
  264. res = ast_waitfor(chan,100);
  265. if (res > -1) {
  266. for (ptr=digits; *ptr; ptr++) {
  267. if (*ptr == 'w') {
  268. res = ast_safe_sleep(chan, 500);
  269. if (res)
  270. break;
  271. continue;
  272. }
  273. memset(&f, 0, sizeof(f));
  274. f.frametype = AST_FRAME_DTMF;
  275. f.subclass = *ptr;
  276. f.src = "ast_dtmf_stream";
  277. if (strchr("0123456789*#abcdABCD",*ptr)==NULL) {
  278. ast_log(LOG_WARNING, "Illegal DTMF character '%c' in string. (0-9*#aAbBcCdD allowed)\n",*ptr);
  279. } else {
  280. res = ast_write(chan, &f);
  281. if (res)
  282. break;
  283. /* pause between digits */
  284. res = ast_safe_sleep(chan,between);
  285. if (res)
  286. break;
  287. }
  288. }
  289. }
  290. if (peer)
  291. res = ast_autoservice_stop(peer);
  292. }
  293. return res;
  294. }
  295. struct linear_state {
  296. int fd;
  297. int autoclose;
  298. int allowoverride;
  299. int origwfmt;
  300. };
  301. static void linear_release(struct ast_channel *chan, void *params)
  302. {
  303. struct linear_state *ls = params;
  304. if (ls->origwfmt && ast_set_write_format(chan, ls->origwfmt)) {
  305. ast_log(LOG_WARNING, "Unable to restore channel '%s' to format '%d'\n", chan->name, ls->origwfmt);
  306. }
  307. if (ls->autoclose)
  308. close(ls->fd);
  309. free(params);
  310. }
  311. static int linear_generator(struct ast_channel *chan, void *data, int len, int samples)
  312. {
  313. struct ast_frame f;
  314. short buf[2048 + AST_FRIENDLY_OFFSET / 2];
  315. struct linear_state *ls = data;
  316. int res;
  317. len = samples * 2;
  318. if (len > sizeof(buf) - AST_FRIENDLY_OFFSET) {
  319. ast_log(LOG_WARNING, "Can't generate %d bytes of data!\n" ,len);
  320. len = sizeof(buf) - AST_FRIENDLY_OFFSET;
  321. }
  322. memset(&f, 0, sizeof(f));
  323. res = read(ls->fd, buf + AST_FRIENDLY_OFFSET/2, len);
  324. if (res > 0) {
  325. f.frametype = AST_FRAME_VOICE;
  326. f.subclass = AST_FORMAT_SLINEAR;
  327. f.data = buf + AST_FRIENDLY_OFFSET/2;
  328. f.datalen = res;
  329. f.samples = res / 2;
  330. f.offset = AST_FRIENDLY_OFFSET;
  331. ast_write(chan, &f);
  332. if (res == len)
  333. return 0;
  334. }
  335. return -1;
  336. }
  337. static void *linear_alloc(struct ast_channel *chan, void *params)
  338. {
  339. struct linear_state *ls;
  340. /* In this case, params is already malloc'd */
  341. if (params) {
  342. ls = params;
  343. if (ls->allowoverride)
  344. chan->writeinterrupt = 1;
  345. else
  346. chan->writeinterrupt = 0;
  347. ls->origwfmt = chan->writeformat;
  348. if (ast_set_write_format(chan, AST_FORMAT_SLINEAR)) {
  349. ast_log(LOG_WARNING, "Unable to set '%s' to linear format (write)\n", chan->name);
  350. free(ls);
  351. ls = params = NULL;
  352. }
  353. }
  354. return params;
  355. }
  356. static struct ast_generator linearstream =
  357. {
  358. alloc: linear_alloc,
  359. release: linear_release,
  360. generate: linear_generator,
  361. };
  362. int ast_linear_stream(struct ast_channel *chan, const char *filename, int fd, int allowoverride)
  363. {
  364. struct linear_state *lin;
  365. char tmpf[256] = "";
  366. int res = -1;
  367. int autoclose = 0;
  368. if (fd < 0) {
  369. if (!filename || ast_strlen_zero(filename))
  370. return -1;
  371. autoclose = 1;
  372. if (filename[0] == '/')
  373. strncpy(tmpf, filename, sizeof(tmpf) - 1);
  374. else
  375. snprintf(tmpf, sizeof(tmpf), "%s/%s/%s", (char *)ast_config_AST_VAR_DIR, "sounds", filename);
  376. fd = open(tmpf, O_RDONLY);
  377. if (fd < 0){
  378. ast_log(LOG_WARNING, "Unable to open file '%s': %s\n", tmpf, strerror(errno));
  379. return -1;
  380. }
  381. }
  382. lin = malloc(sizeof(struct linear_state));
  383. if (lin) {
  384. memset(lin, 0, sizeof(lin));
  385. lin->fd = fd;
  386. lin->allowoverride = allowoverride;
  387. lin->autoclose = autoclose;
  388. res = ast_activate_generator(chan, &linearstream, lin);
  389. }
  390. return res;
  391. }
  392. int ast_control_streamfile(struct ast_channel *chan, char *file, char *fwd, char *rev, char *stop, char *pause, int skipms)
  393. {
  394. struct timeval started, ended;
  395. long elapsed = 0,last_elapsed =0;
  396. char *breaks=NULL;
  397. char *end=NULL;
  398. int blen=2;
  399. int res=0;
  400. if (stop)
  401. blen += strlen(stop);
  402. if (pause)
  403. blen += strlen(pause);
  404. if (blen > 2) {
  405. breaks = alloca(blen + 1);
  406. breaks[0] = '\0';
  407. strcat(breaks, stop);
  408. strcat(breaks, pause);
  409. }
  410. if (chan->_state != AST_STATE_UP)
  411. res = ast_answer(chan);
  412. if (chan)
  413. ast_stopstream(chan);
  414. if (file) {
  415. if ((end = strchr(file,':'))) {
  416. if (!strcasecmp(end, ":end")) {
  417. *end = '\0';
  418. end++;
  419. }
  420. }
  421. }
  422. for (;;) {
  423. gettimeofday(&started,NULL);
  424. if (chan)
  425. ast_stopstream(chan);
  426. res = ast_streamfile(chan, file, chan->language);
  427. if (!res) {
  428. if (end) {
  429. ast_seekstream(chan->stream, 0, SEEK_END);
  430. end=NULL;
  431. }
  432. res = 1;
  433. if (elapsed) {
  434. ast_stream_fastforward(chan->stream, elapsed);
  435. last_elapsed = elapsed - 200;
  436. }
  437. if (res)
  438. res = ast_waitstream_fr(chan, breaks, fwd, rev, skipms);
  439. else
  440. break;
  441. }
  442. if (res < 1)
  443. break;
  444. if (pause != NULL && strchr(pause, res)) {
  445. gettimeofday(&ended, NULL);
  446. elapsed = (((ended.tv_sec * 1000) + ended.tv_usec / 1000) - ((started.tv_sec * 1000) + started.tv_usec / 1000) + last_elapsed);
  447. for(;;) {
  448. if (chan)
  449. ast_stopstream(chan);
  450. res = ast_waitfordigit(chan, 1000);
  451. if (res == 0)
  452. continue;
  453. else if (res == -1 || strchr(pause, res) || (stop && strchr(stop, res)))
  454. break;
  455. }
  456. if (res == *pause) {
  457. res = 0;
  458. continue;
  459. }
  460. }
  461. if (res == -1)
  462. break;
  463. /* if we get one of our stop chars, return it to the calling function */
  464. if (stop && strchr(stop, res)) {
  465. /* res = 0; */
  466. break;
  467. }
  468. }
  469. if (chan)
  470. ast_stopstream(chan);
  471. return res;
  472. }
  473. int ast_play_and_wait(struct ast_channel *chan, char *fn)
  474. {
  475. int d;
  476. d = ast_streamfile(chan, fn, chan->language);
  477. if (d)
  478. return d;
  479. d = ast_waitstream(chan, AST_DIGIT_ANY);
  480. ast_stopstream(chan);
  481. return d;
  482. }
  483. static int global_silence_threshold = 128;
  484. static int global_maxsilence = 0;
  485. int ast_play_and_record(struct ast_channel *chan, char *playfile, char *recordfile, int maxtime, char *fmt, int *duration, int silencethreshold, int maxsilence, const char *path)
  486. {
  487. int d;
  488. char *fmts;
  489. char comment[256];
  490. int x, fmtcnt=1, res=-1,outmsg=0;
  491. struct ast_frame *f;
  492. struct ast_filestream *others[MAX_OTHER_FORMATS];
  493. char *sfmt[MAX_OTHER_FORMATS];
  494. char *stringp=NULL;
  495. time_t start, end;
  496. struct ast_dsp *sildet=NULL; /* silence detector dsp */
  497. int totalsilence = 0;
  498. int dspsilence = 0;
  499. int gotsilence = 0; /* did we timeout for silence? */
  500. int rfmt=0;
  501. if (silencethreshold < 0)
  502. silencethreshold = global_silence_threshold;
  503. if (maxsilence < 0)
  504. maxsilence = global_maxsilence;
  505. /* barf if no pointer passed to store duration in */
  506. if (duration == NULL) {
  507. ast_log(LOG_WARNING, "Error play_and_record called without duration pointer\n");
  508. return -1;
  509. }
  510. ast_log(LOG_DEBUG,"play_and_record: %s, %s, '%s'\n", playfile ? playfile : "<None>", recordfile, fmt);
  511. snprintf(comment,sizeof(comment),"Playing %s, Recording to: %s on %s\n", playfile ? playfile : "<None>", recordfile, chan->name);
  512. if (playfile) {
  513. d = ast_play_and_wait(chan, playfile);
  514. if (d > -1)
  515. d = ast_streamfile(chan, "beep",chan->language);
  516. if (!d)
  517. d = ast_waitstream(chan,"");
  518. if (d < 0)
  519. return -1;
  520. }
  521. fmts = ast_strdupa(fmt);
  522. stringp=fmts;
  523. strsep(&stringp, "|");
  524. ast_log(LOG_DEBUG,"Recording Formats: sfmts=%s\n", fmts);
  525. sfmt[0] = ast_strdupa(fmts);
  526. while((fmt = strsep(&stringp, "|"))) {
  527. if (fmtcnt > MAX_OTHER_FORMATS - 1) {
  528. ast_log(LOG_WARNING, "Please increase MAX_OTHER_FORMATS in app_voicemail.c\n");
  529. break;
  530. }
  531. sfmt[fmtcnt++] = ast_strdupa(fmt);
  532. }
  533. time(&start);
  534. end=start; /* pre-initialize end to be same as start in case we never get into loop */
  535. for (x=0;x<fmtcnt;x++) {
  536. others[x] = ast_writefile(recordfile, sfmt[x], comment, O_TRUNC, 0, 0700);
  537. ast_verbose( VERBOSE_PREFIX_3 "x=%i, open writing: %s format: %s, %p\n", x, recordfile, sfmt[x], others[x]);
  538. if (!others[x]) {
  539. break;
  540. }
  541. }
  542. if (path)
  543. ast_unlock_path(path);
  544. if (maxsilence > 0) {
  545. sildet = ast_dsp_new(); /* Create the silence detector */
  546. if (!sildet) {
  547. ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
  548. return -1;
  549. }
  550. ast_dsp_set_threshold(sildet, silencethreshold);
  551. rfmt = chan->readformat;
  552. res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
  553. if (res < 0) {
  554. ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
  555. ast_dsp_free(sildet);
  556. return -1;
  557. }
  558. }
  559. if (x == fmtcnt) {
  560. /* Loop forever, writing the packets we read to the writer(s), until
  561. we read a # or get a hangup */
  562. f = NULL;
  563. for(;;) {
  564. res = ast_waitfor(chan, 2000);
  565. if (!res) {
  566. ast_log(LOG_DEBUG, "One waitfor failed, trying another\n");
  567. /* Try one more time in case of masq */
  568. res = ast_waitfor(chan, 2000);
  569. if (!res) {
  570. ast_log(LOG_WARNING, "No audio available on %s??\n", chan->name);
  571. res = -1;
  572. }
  573. }
  574. if (res < 0) {
  575. f = NULL;
  576. break;
  577. }
  578. f = ast_read(chan);
  579. if (!f)
  580. break;
  581. if (f->frametype == AST_FRAME_VOICE) {
  582. /* write each format */
  583. for (x=0;x<fmtcnt;x++) {
  584. res = ast_writestream(others[x], f);
  585. }
  586. /* Silence Detection */
  587. if (maxsilence > 0) {
  588. dspsilence = 0;
  589. ast_dsp_silence(sildet, f, &dspsilence);
  590. if (dspsilence)
  591. totalsilence = dspsilence;
  592. else
  593. totalsilence = 0;
  594. if (totalsilence > maxsilence) {
  595. /* Ended happily with silence */
  596. if (option_verbose > 2)
  597. ast_verbose( VERBOSE_PREFIX_3 "Recording automatically stopped after a silence of %d seconds\n", totalsilence/1000);
  598. ast_frfree(f);
  599. gotsilence = 1;
  600. outmsg=2;
  601. break;
  602. }
  603. }
  604. /* Exit on any error */
  605. if (res) {
  606. ast_log(LOG_WARNING, "Error writing frame\n");
  607. ast_frfree(f);
  608. break;
  609. }
  610. } else if (f->frametype == AST_FRAME_VIDEO) {
  611. /* Write only once */
  612. ast_writestream(others[0], f);
  613. } else if (f->frametype == AST_FRAME_DTMF) {
  614. if (f->subclass == '#') {
  615. if (option_verbose > 2)
  616. ast_verbose( VERBOSE_PREFIX_3 "User ended message by pressing %c\n", f->subclass);
  617. res = '#';
  618. outmsg = 2;
  619. ast_frfree(f);
  620. break;
  621. }
  622. }
  623. if (f->subclass == '0') {
  624. /* Check for a '0' during message recording also, in case caller wants operator */
  625. if (option_verbose > 2)
  626. ast_verbose(VERBOSE_PREFIX_3 "User cancelled by pressing %c\n", f->subclass);
  627. res = '0';
  628. outmsg = 0;
  629. ast_frfree(f);
  630. break;
  631. }
  632. if (maxtime) {
  633. time(&end);
  634. if (maxtime < (end - start)) {
  635. if (option_verbose > 2)
  636. ast_verbose( VERBOSE_PREFIX_3 "Took too long, cutting it short...\n");
  637. outmsg = 2;
  638. res = 't';
  639. ast_frfree(f);
  640. break;
  641. }
  642. }
  643. ast_frfree(f);
  644. }
  645. if (end == start) time(&end);
  646. if (!f) {
  647. if (option_verbose > 2)
  648. ast_verbose( VERBOSE_PREFIX_3 "User hung up\n");
  649. res = -1;
  650. outmsg=1;
  651. }
  652. } else {
  653. ast_log(LOG_WARNING, "Error creating writestream '%s', format '%s'\n", recordfile, sfmt[x]);
  654. }
  655. *duration = end - start;
  656. for (x=0;x<fmtcnt;x++) {
  657. if (!others[x])
  658. break;
  659. if (res > 0) {
  660. if (totalsilence)
  661. ast_stream_rewind(others[x], totalsilence-200);
  662. else
  663. ast_stream_rewind(others[x], 200);
  664. }
  665. ast_truncstream(others[x]);
  666. ast_closestream(others[x]);
  667. }
  668. if (rfmt) {
  669. if (ast_set_read_format(chan, rfmt)) {
  670. ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_getformatname(rfmt), chan->name);
  671. }
  672. }
  673. if (outmsg > 1) {
  674. /* Let them know recording is stopped */
  675. if(!ast_streamfile(chan, "auth-thankyou", chan->language))
  676. ast_waitstream(chan, "");
  677. }
  678. if (sildet)
  679. ast_dsp_free(sildet);
  680. return res;
  681. }
  682. int ast_play_and_prepend(struct ast_channel *chan, char *playfile, char *recordfile, int maxtime, char *fmt, int *duration, int beep, int silencethreshold, int maxsilence)
  683. {
  684. int d = 0;
  685. char *fmts;
  686. char comment[256];
  687. int x, fmtcnt=1, res=-1,outmsg=0;
  688. struct ast_frame *f;
  689. struct ast_filestream *others[MAX_OTHER_FORMATS];
  690. struct ast_filestream *realfiles[MAX_OTHER_FORMATS];
  691. char *sfmt[MAX_OTHER_FORMATS];
  692. char *stringp=NULL;
  693. time_t start, end;
  694. struct ast_dsp *sildet; /* silence detector dsp */
  695. int totalsilence = 0;
  696. int dspsilence = 0;
  697. int gotsilence = 0; /* did we timeout for silence? */
  698. int rfmt=0;
  699. char prependfile[80];
  700. if (silencethreshold < 0)
  701. silencethreshold = global_silence_threshold;
  702. if (maxsilence < 0)
  703. maxsilence = global_maxsilence;
  704. /* barf if no pointer passed to store duration in */
  705. if (duration == NULL) {
  706. ast_log(LOG_WARNING, "Error play_and_prepend called without duration pointer\n");
  707. return -1;
  708. }
  709. ast_log(LOG_DEBUG,"play_and_prepend: %s, %s, '%s'\n", playfile ? playfile : "<None>", recordfile, fmt);
  710. snprintf(comment,sizeof(comment),"Playing %s, Recording to: %s on %s\n", playfile ? playfile : "<None>", recordfile, chan->name);
  711. if (playfile || beep) {
  712. if (!beep)
  713. d = ast_play_and_wait(chan, playfile);
  714. if (d > -1)
  715. d = ast_streamfile(chan, "beep",chan->language);
  716. if (!d)
  717. d = ast_waitstream(chan,"");
  718. if (d < 0)
  719. return -1;
  720. }
  721. strncpy(prependfile, recordfile, sizeof(prependfile) -1);
  722. strncat(prependfile, "-prepend", sizeof(prependfile) - strlen(prependfile) - 1);
  723. fmts = ast_strdupa(fmt);
  724. stringp=fmts;
  725. strsep(&stringp, "|");
  726. ast_log(LOG_DEBUG,"Recording Formats: sfmts=%s\n", fmts);
  727. sfmt[0] = ast_strdupa(fmts);
  728. while((fmt = strsep(&stringp, "|"))) {
  729. if (fmtcnt > MAX_OTHER_FORMATS - 1) {
  730. ast_log(LOG_WARNING, "Please increase MAX_OTHER_FORMATS in app_voicemail.c\n");
  731. break;
  732. }
  733. sfmt[fmtcnt++] = ast_strdupa(fmt);
  734. }
  735. time(&start);
  736. end=start; /* pre-initialize end to be same as start in case we never get into loop */
  737. for (x=0;x<fmtcnt;x++) {
  738. others[x] = ast_writefile(prependfile, sfmt[x], comment, O_TRUNC, 0, 0700);
  739. ast_verbose( VERBOSE_PREFIX_3 "x=%i, open writing: %s format: %s, %p\n", x, prependfile, sfmt[x], others[x]);
  740. if (!others[x]) {
  741. break;
  742. }
  743. }
  744. sildet = ast_dsp_new(); /* Create the silence detector */
  745. if (!sildet) {
  746. ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
  747. return -1;
  748. }
  749. ast_dsp_set_threshold(sildet, silencethreshold);
  750. if (maxsilence > 0) {
  751. rfmt = chan->readformat;
  752. res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
  753. if (res < 0) {
  754. ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
  755. return -1;
  756. }
  757. }
  758. if (x == fmtcnt) {
  759. /* Loop forever, writing the packets we read to the writer(s), until
  760. we read a # or get a hangup */
  761. f = NULL;
  762. for(;;) {
  763. res = ast_waitfor(chan, 2000);
  764. if (!res) {
  765. ast_log(LOG_DEBUG, "One waitfor failed, trying another\n");
  766. /* Try one more time in case of masq */
  767. res = ast_waitfor(chan, 2000);
  768. if (!res) {
  769. ast_log(LOG_WARNING, "No audio available on %s??\n", chan->name);
  770. res = -1;
  771. }
  772. }
  773. if (res < 0) {
  774. f = NULL;
  775. break;
  776. }
  777. f = ast_read(chan);
  778. if (!f)
  779. break;
  780. if (f->frametype == AST_FRAME_VOICE) {
  781. /* write each format */
  782. for (x=0;x<fmtcnt;x++) {
  783. if (!others[x])
  784. break;
  785. res = ast_writestream(others[x], f);
  786. }
  787. /* Silence Detection */
  788. if (maxsilence > 0) {
  789. dspsilence = 0;
  790. ast_dsp_silence(sildet, f, &dspsilence);
  791. if (dspsilence)
  792. totalsilence = dspsilence;
  793. else
  794. totalsilence = 0;
  795. if (totalsilence > maxsilence) {
  796. /* Ended happily with silence */
  797. if (option_verbose > 2)
  798. ast_verbose( VERBOSE_PREFIX_3 "Recording automatically stopped after a silence of %d seconds\n", totalsilence/1000);
  799. ast_frfree(f);
  800. gotsilence = 1;
  801. outmsg=2;
  802. break;
  803. }
  804. }
  805. /* Exit on any error */
  806. if (res) {
  807. ast_log(LOG_WARNING, "Error writing frame\n");
  808. ast_frfree(f);
  809. break;
  810. }
  811. } else if (f->frametype == AST_FRAME_VIDEO) {
  812. /* Write only once */
  813. ast_writestream(others[0], f);
  814. } else if (f->frametype == AST_FRAME_DTMF) {
  815. /* stop recording with any digit */
  816. if (option_verbose > 2)
  817. ast_verbose( VERBOSE_PREFIX_3 "User ended message by pressing %c\n", f->subclass);
  818. res = 't';
  819. outmsg = 2;
  820. ast_frfree(f);
  821. break;
  822. }
  823. if (maxtime) {
  824. time(&end);
  825. if (maxtime < (end - start)) {
  826. if (option_verbose > 2)
  827. ast_verbose( VERBOSE_PREFIX_3 "Took too long, cutting it short...\n");
  828. res = 't';
  829. outmsg=2;
  830. ast_frfree(f);
  831. break;
  832. }
  833. }
  834. ast_frfree(f);
  835. }
  836. if (end == start) time(&end);
  837. if (!f) {
  838. if (option_verbose > 2)
  839. ast_verbose( VERBOSE_PREFIX_3 "User hung up\n");
  840. res = -1;
  841. outmsg=1;
  842. #if 0
  843. /* delete all the prepend files */
  844. for (x=0;x<fmtcnt;x++) {
  845. if (!others[x])
  846. break;
  847. ast_closestream(others[x]);
  848. ast_filedelete(prependfile, sfmt[x]);
  849. }
  850. #endif
  851. }
  852. } else {
  853. ast_log(LOG_WARNING, "Error creating writestream '%s', format '%s'\n", prependfile, sfmt[x]);
  854. }
  855. *duration = end - start;
  856. #if 0
  857. if (outmsg > 1) {
  858. #else
  859. if (outmsg) {
  860. #endif
  861. struct ast_frame *fr;
  862. for (x=0;x<fmtcnt;x++) {
  863. snprintf(comment, sizeof(comment), "Opening the real file %s.%s\n", recordfile, sfmt[x]);
  864. realfiles[x] = ast_readfile(recordfile, sfmt[x], comment, O_RDONLY, 0, 0);
  865. if (!others[x] || !realfiles[x])
  866. break;
  867. if (totalsilence)
  868. ast_stream_rewind(others[x], totalsilence-200);
  869. else
  870. ast_stream_rewind(others[x], 200);
  871. ast_truncstream(others[x]);
  872. /* add the original file too */
  873. while ((fr = ast_readframe(realfiles[x]))) {
  874. ast_writestream(others[x],fr);
  875. }
  876. ast_closestream(others[x]);
  877. ast_closestream(realfiles[x]);
  878. ast_filerename(prependfile, recordfile, sfmt[x]);
  879. #if 0
  880. ast_verbose("Recording Format: sfmts=%s, prependfile %s, recordfile %s\n", sfmt[x],prependfile,recordfile);
  881. #endif
  882. ast_filedelete(prependfile, sfmt[x]);
  883. }
  884. }
  885. if (rfmt) {
  886. if (ast_set_read_format(chan, rfmt)) {
  887. ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_getformatname(rfmt), chan->name);
  888. }
  889. }
  890. if (outmsg) {
  891. if (outmsg > 1) {
  892. /* Let them know it worked */
  893. ast_streamfile(chan, "auth-thankyou", chan->language);
  894. ast_waitstream(chan, "");
  895. }
  896. }
  897. return res;
  898. }
  899. int ast_lock_path(const char *path)
  900. {
  901. char *s;
  902. char *fs;
  903. int res;
  904. int fd;
  905. time_t start;
  906. s = alloca(strlen(path) + 10);
  907. fs = alloca(strlen(path) + 20);
  908. if (!fs || !s) {
  909. ast_log(LOG_WARNING, "Out of memory!\n");
  910. return -1;
  911. }
  912. snprintf(fs, strlen(path) + 19, "%s/%s-%08x", path, ".lock", rand());
  913. fd = open(fs, O_WRONLY | O_CREAT | O_EXCL, 0600);
  914. if (fd < 0) {
  915. fprintf(stderr, "Unable to create lock file: %s\n", strerror(errno));
  916. return -1;
  917. }
  918. close(fd);
  919. snprintf(s, strlen(path) + 9, "%s/%s", path, ".lock");
  920. time(&start);
  921. while (((res = link(fs, s)) < 0) && (errno == EEXIST) && (time(NULL) - start < 5))
  922. usleep(1);
  923. if (res < 0) {
  924. ast_log(LOG_WARNING, "Failed to lock path '%s': %s\n", path, strerror(errno));
  925. }
  926. unlink(fs);
  927. ast_log(LOG_DEBUG, "Locked path '%s'\n", path);
  928. return res;
  929. }
  930. int ast_unlock_path(const char *path)
  931. {
  932. char *s;
  933. s = alloca(strlen(path) + 10);
  934. if (!s)
  935. return -1;
  936. snprintf(s, strlen(path) + 9, "%s/%s", path, ".lock");
  937. ast_log(LOG_DEBUG, "Unlocked path '%s'\n", path);
  938. return unlink(s);
  939. }