Main Page | Alphabetical List | Data Structures | File List | Data Fields | Globals

app.h File Reference

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)
 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.


Function Documentation

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.

Parameters:
c Which channel one is interacting with
prompt File to pass to ast_streamfile (the one that you wish to play)
s The location where the DTMF data will be stored
maxlen Max Length of the data
timeout Timeout length waiting for data(in milliseconds). Set to 0 for standard timeout(six seconds), or -1 for no time out.
This function was designed for application programmers for situations where they need to play a message and then get some DTMF data in response to the message. If a digit is pressed during playback, it will immediately break out of the message and continue execution of your code. Definition at line 38 of file app.c.

References ast_readstring(), ast_streamfile(), ast_pbx::dtimeout, ast_channel::language, ast_channel::pbx, ast_pbx::rtimeout, and s.

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 }

int ast_app_getdata_full struct ast_channel c,
char *  prompt,
char *  s,
int  maxlen,
int  timeout,
int  audiofd,
int  ctrlfd
 

Definition at line 59 of file app.c.

References ast_readstring_full(), ast_streamfile(), ast_channel::language, and s.

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 }

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 '#'.

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_channel::language, LOG_NOTICE, LOG_WARNING, ast_channel::name, and ast_channel::readformat.

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 }

int ast_app_has_voicemail const char *  mailbox  ) 
 

Determine if a given mailbox has any voicemail.

Definition at line 151 of file app.c.

References ast_config_AST_SPOOL_DIR.

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 }

int ast_app_messagecount const char *  mailbox,
int *  newmsgs,
int *  oldmsgs
 

Determine number of new/old messages in a mailbox.

Definition at line 196 of file app.c.

References ast_config_AST_SPOOL_DIR.

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 }

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.

Definition at line 414 of file app.c.

References ast_channel::_state, ast_answer(), AST_STATE_UP, ast_stopstream(), ast_stream_fastforward(), ast_streamfile(), ast_waitfordigit(), ast_waitstream_fr(), ast_channel::language, and ast_channel::stream.

00415 { 00416 struct timeval started, ended; 00417 long elapsed = 0,last_elapsed =0; 00418 char *breaks; 00419 int blen=2; 00420 int res=0; 00421 00422 if (stop) 00423 blen += strlen(stop); 00424 if (pause) 00425 blen += strlen(pause); 00426 00427 breaks = alloca(blen + 1); 00428 breaks[0] = '\0'; 00429 strcat(breaks, stop); 00430 strcat(breaks, pause); 00431 00432 if (chan->_state != AST_STATE_UP) 00433 res = ast_answer(chan); 00434 00435 if (chan) 00436 ast_stopstream(chan); 00437 00438 for (;;) { 00439 gettimeofday(&started,NULL); 00440 00441 if (chan) 00442 ast_stopstream(chan); 00443 res = ast_streamfile(chan, file, chan->language); 00444 if (!res) { 00445 res = 1; 00446 if (elapsed) { 00447 ast_stream_fastforward(chan->stream, elapsed); 00448 last_elapsed = elapsed - 200; 00449 } 00450 if (res) 00451 res = ast_waitstream_fr(chan, breaks, fwd, rev, skipms); 00452 else 00453 break; 00454 } 00455 00456 if (res < 1) 00457 break; 00458 00459 if (pause != NULL && strchr(pause, res)) { 00460 gettimeofday(&ended, NULL); 00461 elapsed = (((ended.tv_sec * 1000) + ended.tv_usec / 1000) - ((started.tv_sec * 1000) + started.tv_usec / 1000) + last_elapsed); 00462 for(;;) { 00463 if (chan) 00464 ast_stopstream(chan); 00465 res = ast_waitfordigit(chan, 1000); 00466 if(res == 0) 00467 continue; 00468 else if(res == -1 || strchr(pause, res) || (stop && strchr(stop, res))) 00469 break; 00470 } 00471 if (res == *pause) { 00472 res = 0; 00473 continue; 00474 } 00475 } 00476 if (res == -1) 00477 break; 00478 00479 /* if we get one of our stop chars, return it to the calling function */ 00480 if (stop && strchr(stop, res)) { 00481 /* res = 0; */ 00482 break; 00483 } 00484 } 00485 if (chan) 00486 ast_stopstream(chan); 00487 00488 return res; 00489 }

int ast_dtmf_stream struct ast_channel chan,
struct ast_channel peer,
char *  digits,
int  between
 

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 }

int ast_linear_stream struct ast_channel chan,
const char *  filename,
int  fd,
int  allowoverride
 

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(), 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 }

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.

Definition at line 716 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, and VERBOSE_PREFIX_3.

00717 { 00718 char d = 0, *fmts; 00719 char comment[256]; 00720 int x, fmtcnt=1, res=-1,outmsg=0; 00721 struct ast_frame *f; 00722 struct ast_filestream *others[MAX_OTHER_FORMATS]; 00723 struct ast_filestream *realfiles[MAX_OTHER_FORMATS]; 00724 char *sfmt[MAX_OTHER_FORMATS]; 00725 char *stringp=NULL; 00726 time_t start, end; 00727 struct ast_dsp *sildet; /* silence detector dsp */ 00728 int totalsilence = 0; 00729 int dspsilence = 0; 00730 int gotsilence = 0; /* did we timeout for silence? */ 00731 int rfmt=0; 00732 char prependfile[80]; 00733 00734 if (silencethreshold < 0) 00735 silencethreshold = global_silence_threshold; 00736 00737 if (maxsilence < 0) 00738 maxsilence = global_maxsilence; 00739 00740 /* barf if no pointer passed to store duration in */ 00741 if (duration == NULL) { 00742 ast_log(LOG_WARNING, "Error play_and_prepend called without duration pointer\n"); 00743 return -1; 00744 } 00745 00746 ast_log(LOG_DEBUG,"play_and_prepend: %s, %s, '%s'\n", playfile ? playfile : "<None>", recordfile, fmt); 00747 snprintf(comment,sizeof(comment),"Playing %s, Recording to: %s on %s\n", playfile ? playfile : "<None>", recordfile, chan->name); 00748 00749 if (playfile || beep) { 00750 if (!beep) 00751 d = ast_play_and_wait(chan, playfile); 00752 if (d > -1) 00753 d = ast_streamfile(chan, "beep",chan->language); 00754 if (!d) 00755 d = ast_waitstream(chan,""); 00756 if (d < 0) 00757 return -1; 00758 } 00759 strncpy(prependfile, recordfile, sizeof(prependfile) -1); 00760 strncat(prependfile, "-prepend", sizeof(prependfile) - strlen(prependfile) - 1); 00761 00762 fmts = ast_strdupa(fmt); 00763 00764 stringp=fmts; 00765 strsep(&stringp, "|"); 00766 ast_log(LOG_DEBUG,"Recording Formats: sfmts=%s\n", fmts); 00767 sfmt[0] = ast_strdupa(fmts); 00768 00769 while((fmt = strsep(&stringp, "|"))) { 00770 if (fmtcnt > MAX_OTHER_FORMATS - 1) { 00771 ast_log(LOG_WARNING, "Please increase MAX_OTHER_FORMATS in app_voicemail.c\n"); 00772 break; 00773 } 00774 sfmt[fmtcnt++] = ast_strdupa(fmt); 00775 } 00776 00777 time(&start); 00778 end=start; /* pre-initialize end to be same as start in case we never get into loop */ 00779 for (x=0;x<fmtcnt;x++) { 00780 others[x] = ast_writefile(prependfile, sfmt[x], comment, O_TRUNC, 0, 0700); 00781 ast_verbose( VERBOSE_PREFIX_3 "x=%i, open writing: %s format: %s, %p\n", x, prependfile, sfmt[x], others[x]); 00782 if (!others[x]) { 00783 break; 00784 } 00785 } 00786 00787 sildet = ast_dsp_new(); /* Create the silence detector */ 00788 if (!sildet) { 00789 ast_log(LOG_WARNING, "Unable to create silence detector :(\n"); 00790 return -1; 00791 } 00792 ast_dsp_set_threshold(sildet, silencethreshold); 00793 00794 if (maxsilence > 0) { 00795 rfmt = chan->readformat; 00796 res = ast_set_read_format(chan, AST_FORMAT_SLINEAR); 00797 if (res < 0) { 00798 ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n"); 00799 return -1; 00800 } 00801 } 00802 00803 if (x == fmtcnt) { 00804 /* Loop forever, writing the packets we read to the writer(s), until 00805 we read a # or get a hangup */ 00806 f = NULL; 00807 for(;;) { 00808 res = ast_waitfor(chan, 2000); 00809 if (!res) { 00810 ast_log(LOG_DEBUG, "One waitfor failed, trying another\n"); 00811 /* Try one more time in case of masq */ 00812 res = ast_waitfor(chan, 2000); 00813 if (!res) { 00814 ast_log(LOG_WARNING, "No audio available on %s??\n", chan->name); 00815 res = -1; 00816 } 00817 } 00818 00819 if (res < 0) { 00820 f = NULL; 00821 break; 00822 } 00823 f = ast_read(chan); 00824 if (!f) 00825 break; 00826 if (f->frametype == AST_FRAME_VOICE) { 00827 /* write each format */ 00828 for (x=0;x<fmtcnt;x++) { 00829 if (!others[x]) 00830 break; 00831 res = ast_writestream(others[x], f); 00832 } 00833 00834 /* Silence Detection */ 00835 if (maxsilence > 0) { 00836 dspsilence = 0; 00837 ast_dsp_silence(sildet, f, &dspsilence); 00838 if (dspsilence) 00839 totalsilence = dspsilence; 00840 else 00841 totalsilence = 0; 00842 00843 if (totalsilence > maxsilence) { 00844 /* Ended happily with silence */ 00845 if (option_verbose > 2) 00846 ast_verbose( VERBOSE_PREFIX_3 "Recording automatically stopped after a silence of %d seconds\n", totalsilence/1000); 00847 ast_frfree(f); 00848 gotsilence = 1; 00849 outmsg=2; 00850 break; 00851 } 00852 } 00853 /* Exit on any error */ 00854 if (res) { 00855 ast_log(LOG_WARNING, "Error writing frame\n"); 00856 ast_frfree(f); 00857 break; 00858 } 00859 } else if (f->frametype == AST_FRAME_VIDEO) { 00860 /* Write only once */ 00861 ast_writestream(others[0], f); 00862 } else if (f->frametype == AST_FRAME_DTMF) { 00863 /* stop recording with any digit */ 00864 if (option_verbose > 2) 00865 ast_verbose( VERBOSE_PREFIX_3 "User ended message by pressing %c\n", f->subclass); 00866 res = 't'; 00867 outmsg = 2; 00868 ast_frfree(f); 00869 break; 00870 } 00871 if (maxtime) { 00872 time(&end); 00873 if (maxtime < (end - start)) { 00874 if (option_verbose > 2) 00875 ast_verbose( VERBOSE_PREFIX_3 "Took too long, cutting it short...\n"); 00876 res = 't'; 00877 outmsg=2; 00878 ast_frfree(f); 00879 break; 00880 } 00881 } 00882 ast_frfree(f); 00883 } 00884 if (end == start) time(&end); 00885 if (!f) { 00886 if (option_verbose > 2) 00887 ast_verbose( VERBOSE_PREFIX_3 "User hung up\n"); 00888 res = -1; 00889 outmsg=1; 00890 #if 0 00891 /* delete all the prepend files */ 00892 for (x=0;x<fmtcnt;x++) { 00893 if (!others[x]) 00894 break; 00895 ast_closestream(others[x]); 00896 ast_filedelete(prependfile, sfmt[x]); 00897 } 00898 #endif 00899 } 00900 } else { 00901 ast_log(LOG_WARNING, "Error creating writestream '%s', format '%s'\n", prependfile, sfmt[x]); 00902 } 00903 *duration = end - start; 00904 #if 0 00905 if (outmsg > 1) { 00906 #else 00907 if (outmsg) { 00908 #endif 00909 struct ast_frame *fr; 00910 for (x=0;x<fmtcnt;x++) { 00911 snprintf(comment, sizeof(comment), "Opening the real file %s.%s\n", recordfile, sfmt[x]); 00912 realfiles[x] = ast_readfile(recordfile, sfmt[x], comment, O_RDONLY, 0, 0); 00913 if (!others[x] || !realfiles[x]) 00914 break; 00915 if (totalsilence) 00916 ast_stream_rewind(others[x], totalsilence-200); 00917 else 00918 ast_stream_rewind(others[x], 200); 00919 ast_truncstream(others[x]); 00920 /* add the original file too */ 00921 while ((fr = ast_readframe(realfiles[x]))) { 00922 ast_writestream(others[x],fr); 00923 } 00924 ast_closestream(others[x]); 00925 ast_closestream(realfiles[x]); 00926 ast_filerename(prependfile, recordfile, sfmt[x]); 00927 #if 0 00928 ast_verbose("Recording Format: sfmts=%s, prependfile %s, recordfile %s\n", sfmt[x],prependfile,recordfile); 00929 #endif 00930 ast_filedelete(prependfile, sfmt[x]); 00931 } 00932 } 00933 if (rfmt) { 00934 if (ast_set_read_format(chan, rfmt)) { 00935 ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_getformatname(rfmt), chan->name); 00936 } 00937 } 00938 if (outmsg) { 00939 if (outmsg > 1) { 00940 /* Let them know it worked */ 00941 ast_streamfile(chan, "auth-thankyou", chan->language); 00942 ast_waitstream(chan, ""); 00943 } 00944 } 00945 return res; 00946 }

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
 

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 505 of file app.c.

References ast_closestream(), 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_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, and VERBOSE_PREFIX_3.

00506 { 00507 char d, *fmts; 00508 char comment[256]; 00509 int x, fmtcnt=1, res=-1,outmsg=0; 00510 struct ast_frame *f; 00511 struct ast_filestream *others[MAX_OTHER_FORMATS]; 00512 char *sfmt[MAX_OTHER_FORMATS]; 00513 char *stringp=NULL; 00514 time_t start, end; 00515 struct ast_dsp *sildet; /* silence detector dsp */ 00516 int totalsilence = 0; 00517 int dspsilence = 0; 00518 int gotsilence = 0; /* did we timeout for silence? */ 00519 int rfmt=0; 00520 00521 if (silencethreshold < 0) 00522 silencethreshold = global_silence_threshold; 00523 00524 if (maxsilence < 0) 00525 maxsilence = global_maxsilence; 00526 00527 /* barf if no pointer passed to store duration in */ 00528 if (duration == NULL) { 00529 ast_log(LOG_WARNING, "Error play_and_record called without duration pointer\n"); 00530 return -1; 00531 } 00532 00533 ast_log(LOG_DEBUG,"play_and_record: %s, %s, '%s'\n", playfile ? playfile : "<None>", recordfile, fmt); 00534 snprintf(comment,sizeof(comment),"Playing %s, Recording to: %s on %s\n", playfile ? playfile : "<None>", recordfile, chan->name); 00535 00536 if (playfile) { 00537 d = ast_play_and_wait(chan, playfile); 00538 if (d > -1) 00539 d = ast_streamfile(chan, "beep",chan->language); 00540 if (!d) 00541 d = ast_waitstream(chan,""); 00542 if (d < 0) 00543 return -1; 00544 } 00545 00546 fmts = ast_strdupa(fmt); 00547 00548 stringp=fmts; 00549 strsep(&stringp, "|"); 00550 ast_log(LOG_DEBUG,"Recording Formats: sfmts=%s\n", fmts); 00551 sfmt[0] = ast_strdupa(fmts); 00552 00553 while((fmt = strsep(&stringp, "|"))) { 00554 if (fmtcnt > MAX_OTHER_FORMATS - 1) { 00555 ast_log(LOG_WARNING, "Please increase MAX_OTHER_FORMATS in app_voicemail.c\n"); 00556 break; 00557 } 00558 sfmt[fmtcnt++] = ast_strdupa(fmt); 00559 } 00560 00561 time(&start); 00562 end=start; /* pre-initialize end to be same as start in case we never get into loop */ 00563 for (x=0;x<fmtcnt;x++) { 00564 others[x] = ast_writefile(recordfile, sfmt[x], comment, O_TRUNC, 0, 0700); 00565 ast_verbose( VERBOSE_PREFIX_3 "x=%i, open writing: %s format: %s, %p\n", x, recordfile, sfmt[x], others[x]); 00566 00567 if (!others[x]) { 00568 break; 00569 } 00570 } 00571 00572 sildet = ast_dsp_new(); /* Create the silence detector */ 00573 if (!sildet) { 00574 ast_log(LOG_WARNING, "Unable to create silence detector :(\n"); 00575 return -1; 00576 } 00577 ast_dsp_set_threshold(sildet, silencethreshold); 00578 00579 if (maxsilence > 0) { 00580 rfmt = chan->readformat; 00581 res = ast_set_read_format(chan, AST_FORMAT_SLINEAR); 00582 if (res < 0) { 00583 ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n"); 00584 return -1; 00585 } 00586 } 00587 00588 if (x == fmtcnt) { 00589 /* Loop forever, writing the packets we read to the writer(s), until 00590 we read a # or get a hangup */ 00591 f = NULL; 00592 for(;;) { 00593 res = ast_waitfor(chan, 2000); 00594 if (!res) { 00595 ast_log(LOG_DEBUG, "One waitfor failed, trying another\n"); 00596 /* Try one more time in case of masq */ 00597 res = ast_waitfor(chan, 2000); 00598 if (!res) { 00599 ast_log(LOG_WARNING, "No audio available on %s??\n", chan->name); 00600 res = -1; 00601 } 00602 } 00603 00604 if (res < 0) { 00605 f = NULL; 00606 break; 00607 } 00608 f = ast_read(chan); 00609 if (!f) 00610 break; 00611 if (f->frametype == AST_FRAME_VOICE) { 00612 /* write each format */ 00613 for (x=0;x<fmtcnt;x++) { 00614 res = ast_writestream(others[x], f); 00615 } 00616 00617 /* Silence Detection */ 00618 if (maxsilence > 0) { 00619 dspsilence = 0; 00620 ast_dsp_silence(sildet, f, &dspsilence); 00621 if (dspsilence) 00622 totalsilence = dspsilence; 00623 else 00624 totalsilence = 0; 00625 00626 if (totalsilence > maxsilence) { 00627 /* Ended happily with silence */ 00628 if (option_verbose > 2) 00629 ast_verbose( VERBOSE_PREFIX_3 "Recording automatically stopped after a silence of %d seconds\n", totalsilence/1000); 00630 ast_frfree(f); 00631 gotsilence = 1; 00632 outmsg=2; 00633 break; 00634 } 00635 } 00636 /* Exit on any error */ 00637 if (res) { 00638 ast_log(LOG_WARNING, "Error writing frame\n"); 00639 ast_frfree(f); 00640 break; 00641 } 00642 } else if (f->frametype == AST_FRAME_VIDEO) { 00643 /* Write only once */ 00644 ast_writestream(others[0], f); 00645 } else if (f->frametype == AST_FRAME_DTMF) { 00646 if (f->subclass == '#') { 00647 if (option_verbose > 2) 00648 ast_verbose( VERBOSE_PREFIX_3 "User ended message by pressing %c\n", f->subclass); 00649 res = '#'; 00650 outmsg = 2; 00651 ast_frfree(f); 00652 break; 00653 } 00654 } 00655 if (f->subclass == '0') { 00656 /* Check for a '0' during message recording also, in case caller wants operator */ 00657 if (option_verbose > 2) 00658 ast_verbose(VERBOSE_PREFIX_3 "User cancelled by pressing %c\n", f->subclass); 00659 res = '0'; 00660 outmsg = 0; 00661 ast_frfree(f); 00662 break; 00663 } 00664 if (maxtime) { 00665 time(&end); 00666 if (maxtime < (end - start)) { 00667 if (option_verbose > 2) 00668 ast_verbose( VERBOSE_PREFIX_3 "Took too long, cutting it short...\n"); 00669 outmsg = 2; 00670 res = 't'; 00671 ast_frfree(f); 00672 break; 00673 } 00674 } 00675 ast_frfree(f); 00676 } 00677 if (end == start) time(&end); 00678 if (!f) { 00679 if (option_verbose > 2) 00680 ast_verbose( VERBOSE_PREFIX_3 "User hung up\n"); 00681 res = -1; 00682 outmsg=1; 00683 } 00684 } else { 00685 ast_log(LOG_WARNING, "Error creating writestream '%s', format '%s'\n", recordfile, sfmt[x]); 00686 } 00687 00688 *duration = end - start; 00689 00690 for (x=0;x<fmtcnt;x++) { 00691 if (!others[x]) 00692 break; 00693 if (totalsilence) 00694 ast_stream_rewind(others[x], totalsilence-200); 00695 else 00696 ast_stream_rewind(others[x], 200); 00697 ast_truncstream(others[x]); 00698 ast_closestream(others[x]); 00699 } 00700 if (rfmt) { 00701 if (ast_set_read_format(chan, rfmt)) { 00702 ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_getformatname(rfmt), chan->name); 00703 } 00704 } 00705 if (outmsg) { 00706 if (outmsg > 1) { 00707 /* Let them know recording is stopped */ 00708 ast_streamfile(chan, "auth-thankyou", chan->language); 00709 ast_waitstream(chan, ""); 00710 } 00711 } 00712 00713 return res; 00714 }

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.

Definition at line 491 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().

00492 { 00493 int d; 00494 d = ast_streamfile(chan, fn, chan->language); 00495 if (d) 00496 return d; 00497 d = ast_waitstream(chan, AST_DIGIT_ANY); 00498 ast_stopstream(chan); 00499 return d; 00500 }

int ast_safe_system const char *  s  ) 
 

Safely spawn an external program while closingn file descriptors.

Definition at line 182 of file asterisk.c.

References ast_log(), LOG_WARNING, and s.

Referenced by ast_closestream().

00183 { 00184 /* XXX This function needs some optimization work XXX */ 00185 pid_t pid; 00186 int x; 00187 int res; 00188 struct rusage rusage; 00189 int status; 00190 void (*prev_handler) = signal(SIGCHLD, null_sig_handler); 00191 pid = fork(); 00192 if (pid == 0) { 00193 /* Close file descriptors and launch system command */ 00194 for (x=STDERR_FILENO + 1; x<4096;x++) { 00195 close(x); 00196 } 00197 res = execl("/bin/sh", "/bin/sh", "-c", s, NULL); 00198 exit(1); 00199 } else if (pid > 0) { 00200 for(;;) { 00201 res = wait4(pid, &status, 0, &rusage); 00202 if (res > -1) { 00203 if (WIFEXITED(status)) 00204 res = WEXITSTATUS(status); 00205 else 00206 res = -1; 00207 break; 00208 } else { 00209 if (errno != EINTR) 00210 break; 00211 } 00212 } 00213 } else { 00214 ast_log(LOG_WARNING, "Fork failed: %s\n", strerror(errno)); 00215 res = -1; 00216 } 00217 signal(SIGCHLD, prev_handler); 00218 return res; 00219 }


Generated on Fri Sep 24 21:03:49 2004 for Asterisk by doxygen 1.3.8