mirror of
https://github.com/alsa-project/alsa-utils
synced 2024-11-10 03:55:41 +01:00
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:
parent
7af6e01ace
commit
56190f977b
1 changed files with 81 additions and 83 deletions
148
aplay/aplay.c
148
aplay/aplay.c
|
@ -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)
|
||||||
|
|
Loading…
Reference in a new issue