Add truncate option to PCM file plugin

Addeed a new option "truncate" to indicate the behavior of creating
the output file.  When it's true (the default), the file is overwritten
and truncated at creation.  When false, the plugin tries to open a
unique file with a number suffix.

The global behavior of "file" and "tee" PCMs is defined via
defaults.pcm.file_truncate option.  You can overwrite it in ~/.asoundrc.
This commit is contained in:
Takashi Iwai 2008-03-12 16:30:26 +01:00
parent fe8bb13400
commit 3d0dae9099
2 changed files with 51 additions and 4 deletions

View file

@ -95,6 +95,8 @@ defaults.pcm.iec958.card defaults.pcm.card
defaults.pcm.iec958.device defaults.pcm.device
defaults.pcm.modem.card defaults.pcm.card
defaults.pcm.modem.device defaults.pcm.device
# truncate files via file or tee PCM
defaults.pcm.file_truncate true
defaults.rawmidi.card 0
defaults.rawmidi.device 0
defaults.rawmidi.subdevice -1
@ -270,6 +272,10 @@ pcm.tee {
slave.pcm $SLAVE
file $FILE
format $FORMAT
truncate {
@func refer
name defaults.pcm.file_truncate
}
}
pcm.file {
@ -285,6 +291,10 @@ pcm.file {
slave.pcm null
file $FILE
format $FORMAT
truncate {
@func refer
name defaults.pcm.file_truncate
}
}
pcm.null {

View file

@ -396,6 +396,7 @@ static snd_pcm_fast_ops_t snd_pcm_file_fast_ops = {
* \param ifname Input filename (or NULL if file descriptor ifd is available)
* \param ifd Input file descriptor (if (ifd < 0) && (ifname == NULL), no input
* redirection will be performed)
* \param trunc Truncate the file if it already exists
* \param fmt File format ("raw" is supported only)
* \param perm File permission
* \param slave Slave PCM handle
@ -406,13 +407,15 @@ static snd_pcm_fast_ops_t snd_pcm_file_fast_ops = {
* changed in future.
*/
int snd_pcm_file_open(snd_pcm_t **pcmp, const char *name,
const char *fname, int fd, const char *ifname, int ifd,
const char *fname, int fd, const char *ifname, int ifd,
int trunc,
const char *fmt, int perm, snd_pcm_t *slave, int close_slave)
{
snd_pcm_t *pcm;
snd_pcm_file_t *file;
snd_pcm_file_format_t format;
struct timespec timespec;
char *tmpname = NULL;
int err;
assert(pcmp);
@ -424,9 +427,30 @@ int snd_pcm_file_open(snd_pcm_t **pcmp, const char *name,
return -EINVAL;
}
if (fname) {
fd = open(fname, O_WRONLY|O_CREAT, perm);
if (trunc)
fd = open(fname, O_WRONLY|O_CREAT|O_TRUNC, perm);
else {
fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, perm);
if (fd < 0) {
int idx, len;
len = strlen(fname) + 6;
tmpname = malloc(len);
if (!tmpname)
return -ENOMEM;
for (idx = 1; idx < 10000; idx++) {
snprintf(tmpname, len,
"%s.%04d", fname, idx);
fd = open(tmpname, O_WRONLY|O_CREAT|O_EXCL, perm);
if (fd >= 0) {
fname = tmpname;
break;
}
}
}
}
if (fd < 0) {
SYSERR("open %s for writing failed", fname);
free(tmpname);
return -errno;
}
}
@ -434,6 +458,7 @@ int snd_pcm_file_open(snd_pcm_t **pcmp, const char *name,
if (!file) {
if (fname)
close(fd);
free(tmpname);
return -ENOMEM;
}
@ -443,6 +468,8 @@ int snd_pcm_file_open(snd_pcm_t **pcmp, const char *name,
SYSERR("open %s for reading failed", ifname);
if (fname)
close(fd);
free(file);
free(tmpname);
return -errno;
}
}
@ -461,6 +488,7 @@ int snd_pcm_file_open(snd_pcm_t **pcmp, const char *name,
if (err < 0) {
free(file->fname);
free(file);
free(tmpname);
return err;
}
pcm->ops = &snd_pcm_file_ops;
@ -478,6 +506,7 @@ int snd_pcm_file_open(snd_pcm_t **pcmp, const char *name,
snd_pcm_link_appl_ptr(pcm, slave);
*pcmp = pcm;
free(tmpname);
return 0;
}
@ -541,7 +570,7 @@ int _snd_pcm_file_open(snd_pcm_t **pcmp, const char *name,
snd_config_t *slave = NULL, *sconf;
const char *fname = NULL, *ifname = NULL;
const char *format = NULL;
long fd = -1, ifd = -1;
long fd = -1, ifd = -1, trunc = 1;
long perm = 0600;
snd_config_for_each(i, next, conf) {
snd_config_t *n = snd_config_iterator_entry(i);
@ -596,6 +625,13 @@ int _snd_pcm_file_open(snd_pcm_t **pcmp, const char *name,
}
continue;
}
if (strcmp(id, "truncate") == 0) {
err = snd_config_get_bool(n);
if (err < 0)
return -EINVAL;
trunc = err;
continue;
}
SNDERR("Unknown field %s", id);
return -EINVAL;
}
@ -615,7 +651,8 @@ int _snd_pcm_file_open(snd_pcm_t **pcmp, const char *name,
snd_config_delete(sconf);
if (err < 0)
return err;
err = snd_pcm_file_open(pcmp, name, fname, fd, ifname, ifd, format, perm, spcm, 1);
err = snd_pcm_file_open(pcmp, name, fname, fd, ifname, ifd,
trunc, format, perm, spcm, 1);
if (err < 0)
snd_pcm_close(spcm);
return err;