/* Beep and then record a file. filename and format are null-terminated strings which are the file name and format of the desired file. Timeout is the maximum length of the recording in milliseconds (specify 0 for infinite). flags are: NEWT_FLAG_COMMONINT to allow common section interrupt. Returns 0 if time-out, 1 if hang-up, 2 if common interrupt, or the received DTMF char if one received. */ int newt_dep_recordfile(void *newtch, char *filename, char *format, int timeout, int flags) { struct newt_channel *newt; /* pointer to our channel structure */ struct ast_filestream *fs; /* file stream for writing the file */ struct ast_frame *f; /* frames for reading (f) and writing (wf) */ struct timeval tv, start, lastout = { 0,0 } ; /* time vars */ int i,j,res,sil; /* scratch vars */ short samp; /* holder for linear-ized sample */ unsigned char *cp; /* pointer for mu-law data block */ /* point it to the channel structure passed by the user */ newt = (struct newt_channel *) newtch; /* beep at the user to prompt for recording */ i = 0; /* start at 0 index into tone generation */ /* i is now value for 3rd arg of make_tone_block call */ /* initialize last out time */ lastout.tv_sec = lastout.tv_usec = 0; /* output recording beep */ if (ast_streamfile(newt->chan,"beep",newt->chan->language) == -1) return -1; (void) newt_waitstream(newt->chan,"",newt,NEWT_FLAG_COMMONINT,0); /* for normal channel */ ast_stopstream(newt->chan); /* suck in 5 voice frames to make up for echo of beep, etc */ for(i = 0; i < 5; i++) { /* check for soft hangup flag */ if (ast_check_hangup(newt->chan)) return -1; /* if got a common section interrupt, return as such */ if ((flags & NEWT_FLAG_COMMONINT) && (newt_iscommonint(newt->channo))) return 2; /* wait for something on fd */ res = ast_waitfor(newt->chan,-1); if (res == -1) return -1; /* read a frame */ f = ast_read(newt->chan); if (!f) { /* if hangup */ return 1; /* return indicating hangup */ } switch(f->frametype) { case AST_FRAME_DTMF: /* if we got a DTMF frame */ res = f->subclass; /* get received char */ /* free frame */ ast_frfree(f); return res; /* return received char */ } /* free the alloc'ed frame */ ast_frfree(f); } /* now we actually record the voice stream into the file */ /* use the asterisk call to open a file stream */ /* start with normal flags */ i = O_CREAT | O_TRUNC | O_WRONLY; /* if they want to append, set flags this way */ if (flags & NEWT_FLAG_APPEND) i = O_CREAT | O_WRONLY | O_APPEND; fs = ast_writefile(filename, format, NULL, i, 0, 0644); if (!fs) { /* if unable to open */ /* log error */ ast_log(LOG_WARNING, "ast_writefile failed on %s for %s\n", newt->chan->name, filename); return -1; /* return indicating error */ } gettimeofday(&start, NULL); /* get recording start time */ gettimeofday(&tv, NULL); /* get current time */ sil = 0; /* initialize contiguous silence counter to zero */ /* loop while time left (or no time specified) */ while ((!timeout) || (((tv.tv_sec - start.tv_sec) * 1000 + (tv.tv_usec - start.tv_usec)/1000) < timeout)) { /* check for soft hangup flag */ if (ast_check_hangup(newt->chan)) return -1; /* if got a common section interrupt, return as such */ if ((flags & NEWT_FLAG_COMMONINT) && (newt_iscommonint(newt->channo))) return 2; /* wait for activity on channel */ res = ast_waitfor(newt->chan, 250); if (res < 0) { /* if timeout */ continue; /* do it again */ } /* read a frame */ f = ast_read(newt->chan); if (!f) { /* if hangup */ ast_closestream(fs); /* close stream */ return 1; } switch(f->frametype) { case AST_FRAME_DTMF: /* DTMF found */ res = f->subclass; /* get received char */ ast_closestream(fs); /* close stream */ /* free frame */ ast_frfree(f); if (newt_truncate_vfile(filename, format, NEWT_DTMF_TRUNCATE_SIZE) == -1) return -1; return res; case AST_FRAME_VOICE: /* voice frame */ /* if we are to check for silence */ if (flags & NEWT_FLAG_SILENCEINT) { /* go through the received block and count the contiguous samples that qualify as silence */ /* set pointer to data block in frame */ cp = (unsigned char *) f->data; /* loop through the block */ for(j = 0; j < f->datalen; j++) { /* get this sample in linear form */ samp = AST_MULAW(cp[j]); /* within silence parameters, add to count, otherwise clear count */ if ((samp <= SILENCE_LEVEL) && (samp >= -SILENCE_LEVEL)) { sil++; } else sil = 0; } /* if we have enough contiguous silence, exit as interrupted by it */ if (sil >= SILENCE_COUNT) { /* free frame */ ast_frfree(f); ast_closestream(fs); /* close stream */ if (newt_truncate_vfile(filename, format, SILENCE_COUNT) == -1) return -1; return 0; /* return same as timeout */ } } ast_writestream(fs, f); /* write to file */ break; } /* free frame */ ast_frfree(f); /* save current time */ gettimeofday(&tv, NULL); } ast_closestream(fs); /* close file stream */ return 0; /* return indicating timeout */ }