Fix endless loop of recording in arecord

Fix and clean up arecord (capture) code:
- fix the ending condition check
- fix invalid file close in raw mode
- clean up the code
This commit is contained in:
Takashi Iwai 2006-05-17 14:59:29 +02:00
parent 7af6e01ace
commit 56190f977b

View file

@ -126,7 +126,7 @@ struct fmt_capture {
char *what; char *what;
long long max_filesize; long long max_filesize;
} fmt_rec_table[] = { } fmt_rec_table[] = {
{ NULL, end_raw, N_("raw data"), LLONG_MAX }, { NULL, NULL, N_("raw data"), LLONG_MAX },
{ begin_voc, end_voc, N_("VOC"), 16000000LL }, { begin_voc, end_voc, N_("VOC"), 16000000LL },
/* FIXME: can WAV handle exactly 2GB or less than it? */ /* FIXME: can WAV handle exactly 2GB or less than it? */
{ begin_wave, end_wave, N_("WAVE"), 2147483648LL }, { begin_wave, end_wave, N_("WAVE"), 2147483648LL },
@ -1883,12 +1883,6 @@ static void end_voc(int fd)
close(fd); close(fd);
} }
static void end_raw(int fd)
{ /* REALLY only close output */
if (fd != 1)
close(fd);
}
static void end_wave(int fd) static void end_wave(int fd)
{ /* only close output */ { /* only close output */
WaveChunkHeader cd; WaveChunkHeader cd;
@ -2054,26 +2048,62 @@ static void playback(char *name)
close(fd); close(fd);
} }
static void capture(char *name_) static int new_capture_file(char *name, char *namebuf, size_t namelen,
int filecount)
{
/* get a copy of the original filename */
char *s;
char buf[PATH_MAX+1];
strncpy(buf, name, sizeof(buf));
/* separate extension from filename */
s = buf + strlen(buf);
while (s > buf && *s != '.' && *s != '/')
--s;
if (*s == '.')
*s++ = 0;
else if (*s == '/')
s = buf + strlen(buf);
/* upon first jump to this if block rename the first file */
if (filecount == 1) {
if (*s)
snprintf(namebuf, namelen, "%s-01.%s", buf, s);
else
snprintf(namebuf, namelen, "%s-01", buf);
remove(namebuf);
rename(name, namebuf);
filecount = 2;
}
/* name of the current file */
if (*s)
snprintf(namebuf, namelen, "%s-%02i.%s", buf, filecount, s);
else
snprintf(namebuf, namelen, "%s-%02i", buf, filecount);
return filecount;
}
static void capture(char *orig_name)
{ {
int tostdout=0; /* boolean which describes output stream */ int tostdout=0; /* boolean which describes output stream */
int filecount=0; /* number of files written */ int filecount=0; /* number of files written */
char *name=name_; /* current filename */ char *name = orig_name; /* current filename */
char namebuf[PATH_MAX+1]; char namebuf[PATH_MAX+1];
off64_t cur; /* number of bytes to capture */ off64_t count, rest; /* number of bytes to capture */
/* get number of bytes to capture */ /* get number of bytes to capture */
pbrec_count = calc_count(); count = calc_count();
if (count == 0)
count = LLONG_MAX;
/* WAVE-file should be even (I'm not sure), but wasting one byte /* WAVE-file should be even (I'm not sure), but wasting one byte
isn't a problem (this can only be in 8 bit mono) */ isn't a problem (this can only be in 8 bit mono) */
if (pbrec_count < LLONG_MAX) if (count < LLONG_MAX)
pbrec_count += pbrec_count % 2; count += count % 2;
else else
pbrec_count -= pbrec_count % 2; count -= count % 2;
if (pbrec_count == 0)
pbrec_count -= 2;
cur = pbrec_count;
/* display verbose output to console */ /* display verbose output to console */
header(file_type, name); header(file_type, name);
@ -2086,48 +2116,17 @@ static void capture(char *name_)
fd = fileno(stdout); fd = fileno(stdout);
name = "stdout"; name = "stdout";
tostdout=1; tostdout=1;
fdcount = 0;
} }
do { do {
/* open a file to write */ /* open a file to write */
if(!tostdout) { if(!tostdout) {
/* upon the second file we start the numbering scheme */ /* upon the second file we start the numbering scheme */
if(filecount) if (filecount) {
{ filecount = new_capture_file(orig_name, namebuf,
/* get a copy of the original filename */ sizeof(namebuf),
char *s; filecount);
char buf[PATH_MAX+1]; name = namebuf;
strncpy(buf, name_, sizeof(buf));
/* separate extension from filename */
s=buf+strlen(buf);
while(s>buf && *s!='.' && *s!='/')
--s;
if(*s=='.')
*s++=0;
else if(*s=='/')
s=buf+strlen(buf);
/* upon first jump to this if block rename the first file */
if(filecount==1) {
if(*s)
snprintf(namebuf, sizeof(namebuf), "%s-01.%s", buf, s);
else
snprintf(namebuf, sizeof(namebuf), "%s-01", buf);
remove(namebuf);
rename(name, namebuf);
filecount=2;
}
/* name of the current file */
if(*s)
snprintf(namebuf, sizeof(namebuf), "%s-%02i.%s", buf, filecount, s);
else
snprintf(namebuf, sizeof(namebuf), "%s-%02i", buf, filecount);
name=namebuf;
} }
/* open a new file */ /* open a new file */
@ -2136,45 +2135,44 @@ static void capture(char *name_)
perror(name); perror(name);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
fdcount = 0;
filecount++; filecount++;
} }
rest = count;
if (rest > fmt_rec_table[file_type].max_filesize)
rest = fmt_rec_table[file_type].max_filesize;
/* setup sample header */ /* setup sample header */
if (fmt_rec_table[file_type].start) if (fmt_rec_table[file_type].start)
fmt_rec_table[file_type].start(fd, pbrec_count); fmt_rec_table[file_type].start(fd, rest);
/* capture */ /* capture */
do { while (rest > 0) {
ssize_t r=0;
for (; cur > 0 && fdcount<fmt_rec_table[file_type].max_filesize; cur -= r) {
ssize_t err; ssize_t err;
size_t c = (cur <= chunk_bytes) ? cur : chunk_bytes; size_t c = (rest <= (off_t)chunk_bytes) ?
(size_t)rest : chunk_bytes;
c = c * 8 / bits_per_frame; c = c * 8 / bits_per_frame;
if ((size_t)(r = pcm_read(audiobuf, c)) != c) if ((size_t)(err = pcm_read(audiobuf, c)) != c)
break; break;
r = r * bits_per_frame / 8; c = err * bits_per_frame / 8;
if ((err = write(fd, audiobuf, r)) != r) { if ((err = write(fd, audiobuf, c)) != c) {
perror(name); perror(name);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (err > 0) if (err > 0) {
fdcount += err; count -= err;
rest -= err;
}
} }
/* exit conditions:
1) format_raw and a timelimit
2) all requested samples/bytes have been captured (cur>0)
3) filesize threshold was reached (fdcount<wrthreshold)
*/
} while (file_type == FORMAT_RAW && !timelimit && cur>0 &&
fdcount<fmt_rec_table[file_type].max_filesize);
/* finish sample container */ /* finish sample container */
if (fmt_rec_table[file_type].end)
fmt_rec_table[file_type].end(fd); fmt_rec_table[file_type].end(fd);
/* repeat the loop when format is raw without timelimit or filesize threshold was reached */ /* repeat the loop when format is raw without timelimit or
} while((file_type == FORMAT_RAW && !timelimit) || * requested counts of data are recorded
fdcount < fmt_rec_table[file_type].max_filesize); */
} while ((file_type == FORMAT_RAW && !timelimit) || count > 0);
} }
void playbackv_go(int* fds, unsigned int channels, size_t loaded, off64_t count, int rtype, char **names) void playbackv_go(int* fds, unsigned int channels, size_t loaded, off64_t count, int rtype, char **names)