Go to the source code of this file.
Functions | |
| int | ast_app_getdata (struct ast_channel *c, char *prompt, char *s, int maxlen, int timeout) |
| Plays a stream and gets DTMF data from a channel. | |
| int | ast_app_getdata_full (struct ast_channel *c, char *prompt, char *s, int maxlen, int timeout, int audiofd, int ctrlfd) |
| int | ast_app_getvoice (struct ast_channel *c, char *dest, char *dstfmt, char *prompt, int silence, int maxsec) |
| Record voice (after playing prompt if specified), waiting for silence (in ms) up to a given timeout (in s) or '#'. | |
| int | ast_app_has_voicemail (const char *mailbox) |
| Determine if a given mailbox has any voicemail. | |
| int | ast_app_messagecount (const char *mailbox, int *newmsgs, int *oldmsgs) |
| Determine number of new/old messages in a mailbox. | |
| int | ast_safe_system (const char *s) |
| Safely spawn an external program while closingn file descriptors. | |
| int | ast_dtmf_stream (struct ast_channel *chan, struct ast_channel *peer, char *digits, int between) |
| Send DTMF to chan (optionally entertain peer). | |
| int | ast_linear_stream (struct ast_channel *chan, const char *filename, int fd, int allowoverride) |
| Stream a filename (or file descriptor) as a generator. | |
| int | ast_control_streamfile (struct ast_channel *chan, char *file, char *fwd, char *rev, char *stop, char *pause, int skipms) |
| Stream a file with fast forward, pause, reverse. | |
| int | ast_play_and_wait (struct ast_channel *chan, char *fn) |
| Play a stream and wait for a digit, returning the digit that was pressed. | |
| int | ast_play_and_record (struct ast_channel *chan, char *playfile, char *recordfile, int maxtime_sec, char *fmt, int *duration, int silencethreshold, int maxsilence_ms, const char *path) |
| Record a file for a max amount of time (in seconds), in a given list of formats separated by '|', outputting the duration of the recording, and with a maximum. | |
| int | ast_play_and_prepend (struct ast_channel *chan, char *playfile, char *recordfile, int maxtime_sec, char *fmt, int *duration, int beep, int silencethreshold, int maxsilence_ms) |
| Record a message and prepend the message to the given record file after playing the optional playfile (or a beep), storing the duration in 'duration' and with a maximum. | |
| int | ast_lock_path (const char *path) |
| int | ast_unlock_path (const char *path) |
|
||||||||||||||||||||||||
|
Plays a stream and gets DTMF data from a channel.
Definition at line 38 of file app.c. References ast_readstring(), ast_streamfile(), ast_pbx::dtimeout, ast_channel::language, ast_channel::pbx, and ast_pbx::rtimeout. 00039 {
00040 int res,to,fto;
00041 /* XXX Merge with full version? XXX */
00042 if (maxlen)
00043 s[0] = '\0';
00044 if (prompt) {
00045 res = ast_streamfile(c, prompt, c->language);
00046 if (res < 0)
00047 return res;
00048 }
00049 fto = c->pbx ? c->pbx->rtimeout * 1000 : 6000;
00050 to = c->pbx ? c->pbx->dtimeout * 1000 : 2000;
00051
00052 if (timeout > 0) fto = to = timeout;
00053 if (timeout < 0) fto = to = 1000000000;
00054 res = ast_readstring(c, s, maxlen, to, fto, "#");
00055 return res;
00056 }
|
|
||||||||||||||||||||||||||||||||
|
Definition at line 59 of file app.c. References ast_readstring_full(), ast_streamfile(), and ast_channel::language. 00060 {
00061 int res,to,fto;
00062 if (prompt) {
00063 res = ast_streamfile(c, prompt, c->language);
00064 if (res < 0)
00065 return res;
00066 }
00067 fto = 6000;
00068 to = 2000;
00069 if (timeout > 0) fto = to = timeout;
00070 if (timeout < 0) fto = to = 1000000000;
00071 res = ast_readstring_full(c, s, maxlen, to, fto, "#", audiofd, ctrlfd);
00072 return res;
00073 }
|
|
||||||||||||||||||||||||||||
|
Record voice (after playing prompt if specified), waiting for silence (in ms) up to a given timeout (in s) or '#'.
Definition at line 75 of file app.c. References ast_closestream(), ast_dsp_free(), ast_dsp_new(), ast_dsp_silence(), AST_FORMAT_SLINEAR, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_frfree(), ast_log(), ast_read(), ast_set_read_format(), ast_streamfile(), ast_waitfor(), ast_waitstream(), ast_writefile(), ast_frame::frametype, ast_channel::language, LOG_NOTICE, LOG_WARNING, ast_channel::name, ast_channel::readformat, ast_frame::samples, and ast_frame::subclass. 00076 {
00077 int res;
00078 struct ast_filestream *writer;
00079 int rfmt;
00080 int totalms=0, total;
00081
00082 struct ast_frame *f;
00083 struct ast_dsp *sildet;
00084 /* Play prompt if requested */
00085 if (prompt) {
00086 res = ast_streamfile(c, prompt, c->language);
00087 if (res < 0)
00088 return res;
00089 res = ast_waitstream(c,"");
00090 if (res < 0)
00091 return res;
00092 }
00093 rfmt = c->readformat;
00094 res = ast_set_read_format(c, AST_FORMAT_SLINEAR);
00095 if (res < 0) {
00096 ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
00097 return -1;
00098 }
00099 sildet = ast_dsp_new();
00100 if (!sildet) {
00101 ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
00102 return -1;
00103 }
00104 writer = ast_writefile(dest, dstfmt, "Voice file", 0, 0, 0666);
00105 if (!writer) {
00106 ast_log(LOG_WARNING, "Unable to open file '%s' in format '%s' for writing\n", dest, dstfmt);
00107 ast_dsp_free(sildet);
00108 return -1;
00109 }
00110 for(;;) {
00111 if ((res = ast_waitfor(c, 2000)) < 0) {
00112 ast_log(LOG_NOTICE, "Waitfor failed while recording file '%s' format '%s'\n", dest, dstfmt);
00113 break;
00114 }
00115 if (res) {
00116 f = ast_read(c);
00117 if (!f) {
00118 ast_log(LOG_NOTICE, "Hungup while recording file '%s' format '%s'\n", dest, dstfmt);
00119 break;
00120 }
00121 if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '#')) {
00122 /* Ended happily with DTMF */
00123 ast_frfree(f);
00124 break;
00125 } else if (f->frametype == AST_FRAME_VOICE) {
00126 ast_dsp_silence(sildet, f, &total);
00127 if (total > silence) {
00128 /* Ended happily with silence */
00129 ast_frfree(f);
00130 break;
00131 }
00132 totalms += f->samples / 8;
00133 if (totalms > maxsec * 1000) {
00134 /* Ended happily with too much stuff */
00135 ast_log(LOG_NOTICE, "Constraining voice on '%s' to %d seconds\n", c->name, maxsec);
00136 ast_frfree(f);
00137 break;
00138 }
00139 }
00140 ast_frfree(f);
00141 }
00142 }
00143 res = ast_set_read_format(c, rfmt);
00144 if (res)
00145 ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", c->name);
00146 ast_dsp_free(sildet);
00147 ast_closestream(writer);
00148 return 0;
00149 }
|
|
|
Determine if a given mailbox has any voicemail.
Definition at line 151 of file app.c. References ast_app_has_voicemail(), and ast_config_AST_SPOOL_DIR. Referenced by ast_app_has_voicemail(). 00152 {
00153 DIR *dir;
00154 struct dirent *de;
00155 char fn[256];
00156 char tmp[256]="";
00157 char *mb, *cur;
00158 char *context;
00159 int ret;
00160 /* If no mailbox, return immediately */
00161 if (ast_strlen_zero(mailbox))
00162 return 0;
00163 if (strchr(mailbox, ',')) {
00164 strncpy(tmp, mailbox, sizeof(tmp) - 1);
00165 mb = tmp;
00166 ret = 0;
00167 while((cur = strsep(&mb, ","))) {
00168 if (!ast_strlen_zero(cur)) {
00169 if (ast_app_has_voicemail(cur))
00170 return 1;
00171 }
00172 }
00173 return 0;
00174 }
00175 strncpy(tmp, mailbox, sizeof(tmp) - 1);
00176 context = strchr(tmp, '@');
00177 if (context) {
00178 *context = '\0';
00179 context++;
00180 } else
00181 context = "default";
00182 snprintf(fn, sizeof(fn), "%s/voicemail/%s/%s/INBOX", (char *)ast_config_AST_SPOOL_DIR, context, tmp);
00183 dir = opendir(fn);
00184 if (!dir)
00185 return 0;
00186 while ((de = readdir(dir))) {
00187 if (!strncasecmp(de->d_name, "msg", 3))
00188 break;
00189 }
00190 closedir(dir);
00191 if (de)
00192 return 1;
00193 return 0;
00194 }
|
|
||||||||||||||||
|
Determine number of new/old messages in a mailbox.
Definition at line 196 of file app.c. References ast_app_messagecount(), and ast_config_AST_SPOOL_DIR. Referenced by ast_app_messagecount(). 00197 {
00198 DIR *dir;
00199 struct dirent *de;
00200 char fn[256];
00201 char tmp[256]="";
00202 char *mb, *cur;
00203 char *context;
00204 int ret;
00205 if (newmsgs)
00206 *newmsgs = 0;
00207 if (oldmsgs)
00208 *oldmsgs = 0;
00209 /* If no mailbox, return immediately */
00210 if (ast_strlen_zero(mailbox))
00211 return 0;
00212 if (strchr(mailbox, ',')) {
00213 int tmpnew, tmpold;
00214 strncpy(tmp, mailbox, sizeof(tmp) - 1);
00215 mb = tmp;
00216 ret = 0;
00217 while((cur = strsep(&mb, ", "))) {
00218 if (!ast_strlen_zero(cur)) {
00219 if (ast_app_messagecount(cur, newmsgs ? &tmpnew : NULL, oldmsgs ? &tmpold : NULL))
00220 return -1;
00221 else {
00222 if (newmsgs)
00223 *newmsgs += tmpnew;
00224 if (oldmsgs)
00225 *oldmsgs += tmpold;
00226 }
00227 }
00228 }
00229 return 0;
00230 }
00231 strncpy(tmp, mailbox, sizeof(tmp) - 1);
00232 context = strchr(tmp, '@');
00233 if (context) {
00234 *context = '\0';
00235 context++;
00236 } else
00237 context = "default";
00238 if (newmsgs) {
00239 snprintf(fn, sizeof(fn), "%s/voicemail/%s/%s/INBOX", (char *)ast_config_AST_SPOOL_DIR, context, tmp);
00240 dir = opendir(fn);
00241 if (dir) {
00242 while ((de = readdir(dir))) {
00243 if ((strlen(de->d_name) > 3) && !strncasecmp(de->d_name, "msg", 3) &&
00244 !strcasecmp(de->d_name + strlen(de->d_name) - 3, "txt"))
00245 (*newmsgs)++;
00246
00247 }
00248 closedir(dir);
00249 }
00250 }
00251 if (oldmsgs) {
00252 snprintf(fn, sizeof(fn), "%s/voicemail/%s/%s/Old", (char *)ast_config_AST_SPOOL_DIR, context, tmp);
00253 dir = opendir(fn);
00254 if (dir) {
00255 while ((de = readdir(dir))) {
00256 if ((strlen(de->d_name) > 3) && !strncasecmp(de->d_name, "msg", 3) &&
00257 !strcasecmp(de->d_name + strlen(de->d_name) - 3, "txt"))
00258 (*oldmsgs)++;
00259
00260 }
00261 closedir(dir);
00262 }
00263 }
00264 return 0;
00265 }
|
|
||||||||||||||||||||||||||||||||
|
Stream a file with fast forward, pause, reverse.
Definition at line 414 of file app.c. References ast_channel::_state, ast_answer(), ast_seekstream(), AST_STATE_UP, ast_stopstream(), ast_stream_fastforward(), ast_streamfile(), ast_waitfordigit(), and ast_waitstream_fr(). 00415 {
00416 struct timeval started, ended;
00417 long elapsed = 0,last_elapsed =0;
00418 char *breaks=NULL;
00419 char *end=NULL;
00420 int blen=2;
00421 int res=0;
00422
00423 if (stop)
00424 blen += strlen(stop);
00425 if (pause)
00426 blen += strlen(pause);
00427
00428 if (blen > 2) {
00429 breaks = alloca(blen + 1);
00430 breaks[0] = '\0';
00431 strcat(breaks, stop);
00432 strcat(breaks, pause);
00433 }
00434 if (chan->_state != AST_STATE_UP)
00435 res = ast_answer(chan);
00436
00437 if (chan)
00438 ast_stopstream(chan);
00439
00440
00441 if (file) {
00442 if ((end = strchr(file,':'))) {
00443 if (!strcasecmp(end, ":end")) {
00444 *end = '\0';
00445 end++;
00446 }
00447 }
00448 }
00449
00450 for (;;) {
00451 gettimeofday(&started,NULL);
00452
00453 if (chan)
00454 ast_stopstream(chan);
00455 res = ast_streamfile(chan, file, chan->language);
00456 if (!res) {
00457 if (end) {
00458 ast_seekstream(chan->stream, 0, SEEK_END);
00459 end=NULL;
00460 }
00461 res = 1;
00462 if (elapsed) {
00463 ast_stream_fastforward(chan->stream, elapsed);
00464 last_elapsed = elapsed - 200;
00465 }
00466 if (res)
00467 res = ast_waitstream_fr(chan, breaks, fwd, rev, skipms);
00468 else
00469 break;
00470 }
00471
00472 if (res < 1)
00473 break;
00474
00475 if (pause != NULL && strchr(pause, res)) {
00476 gettimeofday(&ended, NULL);
00477 elapsed = (((ended.tv_sec * 1000) + ended.tv_usec / 1000) - ((started.tv_sec * 1000) + started.tv_usec / 1000) + last_elapsed);
00478 for(;;) {
00479 if (chan)
00480 ast_stopstream(chan);
00481 res = ast_waitfordigit(chan, 1000);
00482 if (res == 0)
00483 continue;
00484 else if (res == -1 || strchr(pause, res) || (stop && strchr(stop, res)))
00485 break;
00486 }
00487 if (res == *pause) {
00488 res = 0;
00489 continue;
00490 }
00491 }
00492 if (res == -1)
00493 break;
00494
00495 /* if we get one of our stop chars, return it to the calling function */
00496 if (stop && strchr(stop, res)) {
00497 /* res = 0; */
00498 break;
00499 }
00500 }
00501 if (chan)
00502 ast_stopstream(chan);
00503
00504 return res;
00505 }
|
|
||||||||||||||||||||
|
Send DTMF to chan (optionally entertain peer).
Definition at line 267 of file app.c. References ast_autoservice_start(), ast_autoservice_stop(), AST_FRAME_DTMF, ast_log(), ast_safe_sleep(), ast_waitfor(), ast_write(), and LOG_WARNING. 00268 {
00269 char *ptr=NULL;
00270 int res=0;
00271 struct ast_frame f;
00272 if (!between)
00273 between = 100;
00274
00275 if (peer)
00276 res = ast_autoservice_start(peer);
00277
00278 if (!res) {
00279 res = ast_waitfor(chan,100);
00280 if (res > -1) {
00281 for (ptr=digits;*ptr;*ptr++) {
00282 if (*ptr == 'w') {
00283 res = ast_safe_sleep(chan, 500);
00284 if (res)
00285 break;
00286 continue;
00287 }
00288 memset(&f, 0, sizeof(f));
00289 f.frametype = AST_FRAME_DTMF;
00290 f.subclass = *ptr;
00291 f.src = "ast_dtmf_stream";
00292 if (strchr("0123456789*#abcdABCD",*ptr)==NULL) {
00293 ast_log(LOG_WARNING, "Illegal DTMF character '%c' in string. (0-9*#aAbBcCdD allowed)\n",*ptr);
00294 } else {
00295 res = ast_write(chan, &f);
00296 if (res)
00297 break;
00298 /* pause between digits */
00299 res = ast_safe_sleep(chan,between);
00300 if (res)
00301 break;
00302 }
00303 }
00304 }
00305 if (peer)
00306 res = ast_autoservice_stop(peer);
00307 }
00308 return res;
00309 }
|
|
||||||||||||||||||||
|
Stream a filename (or file descriptor) as a generator.
Definition at line 383 of file app.c. References ast_activate_generator(), ast_config_AST_VAR_DIR, ast_log(), linear_state::autoclose, LOG_WARNING, and malloc. 00384 {
00385 struct linear_state *lin;
00386 char tmpf[256] = "";
00387 int res = -1;
00388 int autoclose = 0;
00389 if (fd < 0) {
00390 if (!filename || ast_strlen_zero(filename))
00391 return -1;
00392 autoclose = 1;
00393 if (filename[0] == '/')
00394 strncpy(tmpf, filename, sizeof(tmpf) - 1);
00395 else
00396 snprintf(tmpf, sizeof(tmpf), "%s/%s/%s", (char *)ast_config_AST_VAR_DIR, "sounds", filename);
00397 fd = open(tmpf, O_RDONLY);
00398 if (fd < 0){
00399 ast_log(LOG_WARNING, "Unable to open file '%s': %s\n", tmpf, strerror(errno));
00400 return -1;
00401 }
00402 }
00403 lin = malloc(sizeof(struct linear_state));
00404 if (lin) {
00405 memset(lin, 0, sizeof(lin));
00406 lin->fd = fd;
00407 lin->allowoverride = allowoverride;
00408 lin->autoclose = autoclose;
00409 res = ast_activate_generator(chan, &linearstream, lin);
00410 }
00411 return res;
00412 }
|
|
|
Definition at line 969 of file app.c. References ast_log(), LOG_DEBUG, LOG_WARNING, and s. 00970 {
00971 char *s;
00972 char *fs;
00973 int res;
00974 int fd;
00975 time_t start;
00976 s = alloca(strlen(path) + 10);
00977 fs = alloca(strlen(path) + 20);
00978 if (!fs || !s) {
00979 ast_log(LOG_WARNING, "Out of memory!\n");
00980 return -1;
00981 }
00982 snprintf(fs, strlen(path) + 19, "%s/%s-%08x", path, ".lock", rand());
00983 fd = open(fs, O_WRONLY | O_CREAT | O_EXCL, 0600);
00984 if (fd < 0) {
00985 fprintf(stderr, "Unable to create lock file: %s\n", strerror(errno));
00986 return -1;
00987 }
00988 close(fd);
00989 snprintf(s, strlen(path) + 9, "%s/%s", path, ".lock");
00990 time(&start);
00991 while (((res = link(fs, s)) < 0) && (errno == EEXIST) && (time(NULL) - start < 5))
00992 usleep(1);
00993 if (res < 0) {
00994 ast_log(LOG_WARNING, "Failed to lock path '%s': %s\n", path, strerror(errno));
00995 }
00996 unlink(fs);
00997 ast_log(LOG_DEBUG, "Locked path '%s'\n", path);
00998 return res;
00999 }
|
|
||||||||||||||||||||||||||||||||||||||||
|
Record a message and prepend the message to the given record file after playing the optional playfile (or a beep), storing the duration in 'duration' and with a maximum.
Definition at line 737 of file app.c. References ast_closestream(), ast_dsp_new(), ast_dsp_set_threshold(), ast_dsp_silence(), ast_filedelete(), ast_filerename(), AST_FORMAT_SLINEAR, AST_FRAME_DTMF, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frfree(), ast_getformatname(), ast_log(), ast_play_and_wait(), ast_read(), ast_readfile(), ast_readframe(), ast_set_read_format(), ast_stream_rewind(), ast_streamfile(), ast_truncstream(), ast_verbose(), ast_waitfor(), ast_waitstream(), ast_writefile(), ast_writestream(), ast_frame::frametype, ast_channel::language, LOG_DEBUG, LOG_WARNING, MAX_OTHER_FORMATS, ast_channel::name, option_verbose, ast_channel::readformat, ast_frame::subclass, ast_dsp::totalsilence, and VERBOSE_PREFIX_3. 00738 {
00739 char d = 0, *fmts;
00740 char comment[256];
00741 int x, fmtcnt=1, res=-1,outmsg=0;
00742 struct ast_frame *f;
00743 struct ast_filestream *others[MAX_OTHER_FORMATS];
00744 struct ast_filestream *realfiles[MAX_OTHER_FORMATS];
00745 char *sfmt[MAX_OTHER_FORMATS];
00746 char *stringp=NULL;
00747 time_t start, end;
00748 struct ast_dsp *sildet; /* silence detector dsp */
00749 int totalsilence = 0;
00750 int dspsilence = 0;
00751 int gotsilence = 0; /* did we timeout for silence? */
00752 int rfmt=0;
00753 char prependfile[80];
00754
00755 if (silencethreshold < 0)
00756 silencethreshold = global_silence_threshold;
00757
00758 if (maxsilence < 0)
00759 maxsilence = global_maxsilence;
00760
00761 /* barf if no pointer passed to store duration in */
00762 if (duration == NULL) {
00763 ast_log(LOG_WARNING, "Error play_and_prepend called without duration pointer\n");
00764 return -1;
00765 }
00766
00767 ast_log(LOG_DEBUG,"play_and_prepend: %s, %s, '%s'\n", playfile ? playfile : "<None>", recordfile, fmt);
00768 snprintf(comment,sizeof(comment),"Playing %s, Recording to: %s on %s\n", playfile ? playfile : "<None>", recordfile, chan->name);
00769
00770 if (playfile || beep) {
00771 if (!beep)
00772 d = ast_play_and_wait(chan, playfile);
00773 if (d > -1)
00774 d = ast_streamfile(chan, "beep",chan->language);
00775 if (!d)
00776 d = ast_waitstream(chan,"");
00777 if (d < 0)
00778 return -1;
00779 }
00780 strncpy(prependfile, recordfile, sizeof(prependfile) -1);
00781 strncat(prependfile, "-prepend", sizeof(prependfile) - strlen(prependfile) - 1);
00782
00783 fmts = ast_strdupa(fmt);
00784
00785 stringp=fmts;
00786 strsep(&stringp, "|");
00787 ast_log(LOG_DEBUG,"Recording Formats: sfmts=%s\n", fmts);
00788 sfmt[0] = ast_strdupa(fmts);
00789
00790 while((fmt = strsep(&stringp, "|"))) {
00791 if (fmtcnt > MAX_OTHER_FORMATS - 1) {
00792 ast_log(LOG_WARNING, "Please increase MAX_OTHER_FORMATS in app_voicemail.c\n");
00793 break;
00794 }
00795 sfmt[fmtcnt++] = ast_strdupa(fmt);
00796 }
00797
00798 time(&start);
00799 end=start; /* pre-initialize end to be same as start in case we never get into loop */
00800 for (x=0;x<fmtcnt;x++) {
00801 others[x] = ast_writefile(prependfile, sfmt[x], comment, O_TRUNC, 0, 0700);
00802 ast_verbose( VERBOSE_PREFIX_3 "x=%i, open writing: %s format: %s, %p\n", x, prependfile, sfmt[x], others[x]);
00803 if (!others[x]) {
00804 break;
00805 }
00806 }
00807
00808 sildet = ast_dsp_new(); /* Create the silence detector */
00809 if (!sildet) {
00810 ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
00811 return -1;
00812 }
00813 ast_dsp_set_threshold(sildet, silencethreshold);
00814
00815 if (maxsilence > 0) {
00816 rfmt = chan->readformat;
00817 res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
00818 if (res < 0) {
00819 ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
00820 return -1;
00821 }
00822 }
00823
00824 if (x == fmtcnt) {
00825 /* Loop forever, writing the packets we read to the writer(s), until
00826 we read a # or get a hangup */
00827 f = NULL;
00828 for(;;) {
00829 res = ast_waitfor(chan, 2000);
00830 if (!res) {
00831 ast_log(LOG_DEBUG, "One waitfor failed, trying another\n");
00832 /* Try one more time in case of masq */
00833 res = ast_waitfor(chan, 2000);
00834 if (!res) {
00835 ast_log(LOG_WARNING, "No audio available on %s??\n", chan->name);
00836 res = -1;
00837 }
00838 }
00839
00840 if (res < 0) {
00841 f = NULL;
00842 break;
00843 }
00844 f = ast_read(chan);
00845 if (!f)
00846 break;
00847 if (f->frametype == AST_FRAME_VOICE) {
00848 /* write each format */
00849 for (x=0;x<fmtcnt;x++) {
00850 if (!others[x])
00851 break;
00852 res = ast_writestream(others[x], f);
00853 }
00854
00855 /* Silence Detection */
00856 if (maxsilence > 0) {
00857 dspsilence = 0;
00858 ast_dsp_silence(sildet, f, &dspsilence);
00859 if (dspsilence)
00860 totalsilence = dspsilence;
00861 else
00862 totalsilence = 0;
00863
00864 if (totalsilence > maxsilence) {
00865 /* Ended happily with silence */
00866 if (option_verbose > 2)
00867 ast_verbose( VERBOSE_PREFIX_3 "Recording automatically stopped after a silence of %d seconds\n", totalsilence/1000);
00868 ast_frfree(f);
00869 gotsilence = 1;
00870 outmsg=2;
00871 break;
00872 }
00873 }
00874 /* Exit on any error */
00875 if (res) {
00876 ast_log(LOG_WARNING, "Error writing frame\n");
00877 ast_frfree(f);
00878 break;
00879 }
00880 } else if (f->frametype == AST_FRAME_VIDEO) {
00881 /* Write only once */
00882 ast_writestream(others[0], f);
00883 } else if (f->frametype == AST_FRAME_DTMF) {
00884 /* stop recording with any digit */
00885 if (option_verbose > 2)
00886 ast_verbose( VERBOSE_PREFIX_3 "User ended message by pressing %c\n", f->subclass);
00887 res = 't';
00888 outmsg = 2;
00889 ast_frfree(f);
00890 break;
00891 }
00892 if (maxtime) {
00893 time(&end);
00894 if (maxtime < (end - start)) {
00895 if (option_verbose > 2)
00896 ast_verbose( VERBOSE_PREFIX_3 "Took too long, cutting it short...\n");
00897 res = 't';
00898 outmsg=2;
00899 ast_frfree(f);
00900 break;
00901 }
00902 }
00903 ast_frfree(f);
00904 }
00905 if (end == start) time(&end);
00906 if (!f) {
00907 if (option_verbose > 2)
00908 ast_verbose( VERBOSE_PREFIX_3 "User hung up\n");
00909 res = -1;
00910 outmsg=1;
00911 #if 0
00912 /* delete all the prepend files */
00913 for (x=0;x<fmtcnt;x++) {
00914 if (!others[x])
00915 break;
00916 ast_closestream(others[x]);
00917 ast_filedelete(prependfile, sfmt[x]);
00918 }
00919 #endif
00920 }
00921 } else {
00922 ast_log(LOG_WARNING, "Error creating writestream '%s', format '%s'\n", prependfile, sfmt[x]);
00923 }
00924 *duration = end - start;
00925 #if 0
00926 if (outmsg > 1) {
00927 #else
00928 if (outmsg) {
00929 #endif
00930 struct ast_frame *fr;
00931 for (x=0;x<fmtcnt;x++) {
00932 snprintf(comment, sizeof(comment), "Opening the real file %s.%s\n", recordfile, sfmt[x]);
00933 realfiles[x] = ast_readfile(recordfile, sfmt[x], comment, O_RDONLY, 0, 0);
00934 if (!others[x] || !realfiles[x])
00935 break;
00936 if (totalsilence)
00937 ast_stream_rewind(others[x], totalsilence-200);
00938 else
00939 ast_stream_rewind(others[x], 200);
00940 ast_truncstream(others[x]);
00941 /* add the original file too */
00942 while ((fr = ast_readframe(realfiles[x]))) {
00943 ast_writestream(others[x],fr);
00944 }
00945 ast_closestream(others[x]);
00946 ast_closestream(realfiles[x]);
00947 ast_filerename(prependfile, recordfile, sfmt[x]);
00948 #if 0
00949 ast_verbose("Recording Format: sfmts=%s, prependfile %s, recordfile %s\n", sfmt[x],prependfile,recordfile);
00950 #endif
00951 ast_filedelete(prependfile, sfmt[x]);
00952 }
00953 }
00954 if (rfmt) {
00955 if (ast_set_read_format(chan, rfmt)) {
00956 ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_getformatname(rfmt), chan->name);
00957 }
00958 }
00959 if (outmsg) {
00960 if (outmsg > 1) {
00961 /* Let them know it worked */
00962 ast_streamfile(chan, "auth-thankyou", chan->language);
00963 ast_waitstream(chan, "");
00964 }
00965 }
00966 return res;
00967 }
|
|
||||||||||||||||||||||||||||||||||||||||
|
Record a file for a max amount of time (in seconds), in a given list of formats separated by '|', outputting the duration of the recording, and with a maximum.
Definition at line 521 of file app.c. References ast_closestream(), ast_dsp_free(), ast_dsp_new(), ast_dsp_set_threshold(), ast_dsp_silence(), AST_FORMAT_SLINEAR, AST_FRAME_DTMF, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frfree(), ast_getformatname(), ast_log(), ast_play_and_wait(), ast_read(), ast_set_read_format(), ast_stream_rewind(), ast_streamfile(), ast_truncstream(), ast_unlock_path(), ast_verbose(), ast_waitfor(), ast_waitstream(), ast_writefile(), ast_writestream(), ast_frame::frametype, ast_channel::language, LOG_DEBUG, LOG_WARNING, MAX_OTHER_FORMATS, ast_channel::name, option_verbose, ast_channel::readformat, ast_frame::subclass, ast_dsp::totalsilence, and VERBOSE_PREFIX_3. 00522 {
00523 char d, *fmts;
00524 char comment[256];
00525 int x, fmtcnt=1, res=-1,outmsg=0;
00526 struct ast_frame *f;
00527 struct ast_filestream *others[MAX_OTHER_FORMATS];
00528 char *sfmt[MAX_OTHER_FORMATS];
00529 char *stringp=NULL;
00530 time_t start, end;
00531 struct ast_dsp *sildet=NULL; /* silence detector dsp */
00532 int totalsilence = 0;
00533 int dspsilence = 0;
00534 int gotsilence = 0; /* did we timeout for silence? */
00535 int rfmt=0;
00536
00537 if (silencethreshold < 0)
00538 silencethreshold = global_silence_threshold;
00539
00540 if (maxsilence < 0)
00541 maxsilence = global_maxsilence;
00542
00543 /* barf if no pointer passed to store duration in */
00544 if (duration == NULL) {
00545 ast_log(LOG_WARNING, "Error play_and_record called without duration pointer\n");
00546 return -1;
00547 }
00548
00549 ast_log(LOG_DEBUG,"play_and_record: %s, %s, '%s'\n", playfile ? playfile : "<None>", recordfile, fmt);
00550 snprintf(comment,sizeof(comment),"Playing %s, Recording to: %s on %s\n", playfile ? playfile : "<None>", recordfile, chan->name);
00551
00552 if (playfile) {
00553 d = ast_play_and_wait(chan, playfile);
00554 if (d > -1)
00555 d = ast_streamfile(chan, "beep",chan->language);
00556 if (!d)
00557 d = ast_waitstream(chan,"");
00558 if (d < 0)
00559 return -1;
00560 }
00561
00562 fmts = ast_strdupa(fmt);
00563
00564 stringp=fmts;
00565 strsep(&stringp, "|");
00566 ast_log(LOG_DEBUG,"Recording Formats: sfmts=%s\n", fmts);
00567 sfmt[0] = ast_strdupa(fmts);
00568
00569 while((fmt = strsep(&stringp, "|"))) {
00570 if (fmtcnt > MAX_OTHER_FORMATS - 1) {
00571 ast_log(LOG_WARNING, "Please increase MAX_OTHER_FORMATS in app_voicemail.c\n");
00572 break;
00573 }
00574 sfmt[fmtcnt++] = ast_strdupa(fmt);
00575 }
00576
00577 time(&start);
00578 end=start; /* pre-initialize end to be same as start in case we never get into loop */
00579 for (x=0;x<fmtcnt;x++) {
00580 others[x] = ast_writefile(recordfile, sfmt[x], comment, O_TRUNC, 0, 0700);
00581 ast_verbose( VERBOSE_PREFIX_3 "x=%i, open writing: %s format: %s, %p\n", x, recordfile, sfmt[x], others[x]);
00582
00583 if (!others[x]) {
00584 break;
00585 }
00586 }
00587
00588 if (path)
00589 ast_unlock_path(path);
00590
00591
00592 if (maxsilence > 0) {
00593 sildet = ast_dsp_new(); /* Create the silence detector */
00594 if (!sildet) {
00595 ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
00596 return -1;
00597 }
00598 ast_dsp_set_threshold(sildet, silencethreshold);
00599 rfmt = chan->readformat;
00600 res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
00601 if (res < 0) {
00602 ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
00603 ast_dsp_free(sildet);
00604 return -1;
00605 }
00606 }
00607
00608 if (x == fmtcnt) {
00609 /* Loop forever, writing the packets we read to the writer(s), until
00610 we read a # or get a hangup */
00611 f = NULL;
00612 for(;;) {
00613 res = ast_waitfor(chan, 2000);
00614 if (!res) {
00615 ast_log(LOG_DEBUG, "One waitfor failed, trying another\n");
00616 /* Try one more time in case of masq */
00617 res = ast_waitfor(chan, 2000);
00618 if (!res) {
00619 ast_log(LOG_WARNING, "No audio available on %s??\n", chan->name);
00620 res = -1;
00621 }
00622 }
00623
00624 if (res < 0) {
00625 f = NULL;
00626 break;
00627 }
00628 f = ast_read(chan);
00629 if (!f)
00630 break;
00631 if (f->frametype == AST_FRAME_VOICE) {
00632 /* write each format */
00633 for (x=0;x<fmtcnt;x++) {
00634 res = ast_writestream(others[x], f);
00635 }
00636
00637 /* Silence Detection */
00638 if (maxsilence > 0) {
00639 dspsilence = 0;
00640 ast_dsp_silence(sildet, f, &dspsilence);
00641 if (dspsilence)
00642 totalsilence = dspsilence;
00643 else
00644 totalsilence = 0;
00645
00646 if (totalsilence > maxsilence) {
00647 /* Ended happily with silence */
00648 if (option_verbose > 2)
00649 ast_verbose( VERBOSE_PREFIX_3 "Recording automatically stopped after a silence of %d seconds\n", totalsilence/1000);
00650 ast_frfree(f);
00651 gotsilence = 1;
00652 outmsg=2;
00653 break;
00654 }
00655 }
00656 /* Exit on any error */
00657 if (res) {
00658 ast_log(LOG_WARNING, "Error writing frame\n");
00659 ast_frfree(f);
00660 break;
00661 }
00662 } else if (f->frametype == AST_FRAME_VIDEO) {
00663 /* Write only once */
00664 ast_writestream(others[0], f);
00665 } else if (f->frametype == AST_FRAME_DTMF) {
00666 if (f->subclass == '#') {
00667 if (option_verbose > 2)
00668 ast_verbose( VERBOSE_PREFIX_3 "User ended message by pressing %c\n", f->subclass);
00669 res = '#';
00670 outmsg = 2;
00671 ast_frfree(f);
00672 break;
00673 }
00674 }
00675 if (f->subclass == '0') {
00676 /* Check for a '0' during message recording also, in case caller wants operator */
00677 if (option_verbose > 2)
00678 ast_verbose(VERBOSE_PREFIX_3 "User cancelled by pressing %c\n", f->subclass);
00679 res = '0';
00680 outmsg = 0;
00681 ast_frfree(f);
00682 break;
00683 }
00684 if (maxtime) {
00685 time(&end);
00686 if (maxtime < (end - start)) {
00687 if (option_verbose > 2)
00688 ast_verbose( VERBOSE_PREFIX_3 "Took too long, cutting it short...\n");
00689 outmsg = 2;
00690 res = 't';
00691 ast_frfree(f);
00692 break;
00693 }
00694 }
00695 ast_frfree(f);
00696 }
00697 if (end == start) time(&end);
00698 if (!f) {
00699 if (option_verbose > 2)
00700 ast_verbose( VERBOSE_PREFIX_3 "User hung up\n");
00701 res = -1;
00702 outmsg=1;
00703 }
00704 } else {
00705 ast_log(LOG_WARNING, "Error creating writestream '%s', format '%s'\n", recordfile, sfmt[x]);
00706 }
00707
00708 *duration = end - start;
00709
00710 for (x=0;x<fmtcnt;x++) {
00711 if (!others[x])
00712 break;
00713 if (res > 0) {
00714 if (totalsilence)
00715 ast_stream_rewind(others[x], totalsilence-200);
00716 else
00717 ast_stream_rewind(others[x], 200);
00718 }
00719 ast_truncstream(others[x]);
00720 ast_closestream(others[x]);
00721 }
00722 if (rfmt) {
00723 if (ast_set_read_format(chan, rfmt)) {
00724 ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_getformatname(rfmt), chan->name);
00725 }
00726 }
00727 if (outmsg > 1) {
00728 /* Let them know recording is stopped */
00729 if(!ast_streamfile(chan, "auth-thankyou", chan->language))
00730 ast_waitstream(chan, "");
00731 }
00732 if (sildet)
00733 ast_dsp_free(sildet);
00734 return res;
00735 }
|
|
||||||||||||
|
Play a stream and wait for a digit, returning the digit that was pressed.
Definition at line 507 of file app.c. References AST_DIGIT_ANY, ast_stopstream(), ast_streamfile(), ast_waitstream(), and ast_channel::language. Referenced by ast_play_and_prepend(), and ast_play_and_record(). 00508 {
00509 int d;
00510 d = ast_streamfile(chan, fn, chan->language);
00511 if (d)
00512 return d;
00513 d = ast_waitstream(chan, AST_DIGIT_ANY);
00514 ast_stopstream(chan);
00515 return d;
00516 }
|
|
|
Safely spawn an external program while closingn file descriptors.
Definition at line 183 of file asterisk.c. References ast_log(), and LOG_WARNING. Referenced by ast_closestream(). 00184 {
00185 /* XXX This function needs some optimization work XXX */
00186 pid_t pid;
00187 int x;
00188 int res;
00189 struct rusage rusage;
00190 int status;
00191 void (*prev_handler) = signal(SIGCHLD, null_sig_handler);
00192 pid = fork();
00193 if (pid == 0) {
00194 /* Close file descriptors and launch system command */
00195 for (x=STDERR_FILENO + 1; x<4096;x++) {
00196 close(x);
00197 }
00198 res = execl("/bin/sh", "/bin/sh", "-c", s, NULL);
00199 exit(1);
00200 } else if (pid > 0) {
00201 for(;;) {
00202 res = wait4(pid, &status, 0, &rusage);
00203 if (res > -1) {
00204 if (WIFEXITED(status))
00205 res = WEXITSTATUS(status);
00206 else
00207 res = -1;
00208 break;
00209 } else {
00210 if (errno != EINTR)
00211 break;
00212 }
00213 }
00214 } else {
00215 ast_log(LOG_WARNING, "Fork failed: %s\n", strerror(errno));
00216 res = -1;
00217 }
00218 signal(SIGCHLD, prev_handler);
00219 return res;
00220 }
|
|
|
Definition at line 1001 of file app.c. References ast_log(), LOG_DEBUG, and s. Referenced by ast_play_and_record(). 01002 {
01003 char *s;
01004 s = alloca(strlen(path) + 10);
01005 if (!s)
01006 return -1;
01007 snprintf(s, strlen(path) + 9, "%s/%s", path, ".lock");
01008 ast_log(LOG_DEBUG, "Unlocked path '%s'\n", path);
01009 return unlink(s);
01010 }
|
1.4.2