[Asterisk-Dev] Asterisk crashes on voicemail timeout
Jim Gottlieb
jimmy-ml at nccom.com
Sun Apr 27 19:07:09 MST 2003
On 2003-04-27 at 12:34, Mark Spencer (markster at digium.com) wrote:
> The "right thing to do" (on my list) is to listen for silence, and when a
> certain amount of silence has occured, *rewind* the stream by that amount
> of silence, and truncate it, to remove the silence from the recording.
> This is totally doable, I just haven't had the time yet t o do it.
In case it helps, here is our routine for recording to a file,
including silence timeout (with rewind) and DTMF interrupt.
#define SILENCE_LEVEL 32
#define SILENCE_COUNT 40000 /* five seconds */
-------------- next part --------------
/* 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 */
}
More information about the asterisk-dev
mailing list