mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2025-11-02 09:01:48 -05:00
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:
parent
fe8bb13400
commit
3d0dae9099
2 changed files with 51 additions and 4 deletions
|
|
@ -95,6 +95,8 @@ defaults.pcm.iec958.card defaults.pcm.card
|
||||||
defaults.pcm.iec958.device defaults.pcm.device
|
defaults.pcm.iec958.device defaults.pcm.device
|
||||||
defaults.pcm.modem.card defaults.pcm.card
|
defaults.pcm.modem.card defaults.pcm.card
|
||||||
defaults.pcm.modem.device defaults.pcm.device
|
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.card 0
|
||||||
defaults.rawmidi.device 0
|
defaults.rawmidi.device 0
|
||||||
defaults.rawmidi.subdevice -1
|
defaults.rawmidi.subdevice -1
|
||||||
|
|
@ -270,6 +272,10 @@ pcm.tee {
|
||||||
slave.pcm $SLAVE
|
slave.pcm $SLAVE
|
||||||
file $FILE
|
file $FILE
|
||||||
format $FORMAT
|
format $FORMAT
|
||||||
|
truncate {
|
||||||
|
@func refer
|
||||||
|
name defaults.pcm.file_truncate
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pcm.file {
|
pcm.file {
|
||||||
|
|
@ -285,6 +291,10 @@ pcm.file {
|
||||||
slave.pcm null
|
slave.pcm null
|
||||||
file $FILE
|
file $FILE
|
||||||
format $FORMAT
|
format $FORMAT
|
||||||
|
truncate {
|
||||||
|
@func refer
|
||||||
|
name defaults.pcm.file_truncate
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pcm.null {
|
pcm.null {
|
||||||
|
|
|
||||||
|
|
@ -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 ifname Input filename (or NULL if file descriptor ifd is available)
|
||||||
* \param ifd Input file descriptor (if (ifd < 0) && (ifname == NULL), no input
|
* \param ifd Input file descriptor (if (ifd < 0) && (ifname == NULL), no input
|
||||||
* redirection will be performed)
|
* redirection will be performed)
|
||||||
|
* \param trunc Truncate the file if it already exists
|
||||||
* \param fmt File format ("raw" is supported only)
|
* \param fmt File format ("raw" is supported only)
|
||||||
* \param perm File permission
|
* \param perm File permission
|
||||||
* \param slave Slave PCM handle
|
* \param slave Slave PCM handle
|
||||||
|
|
@ -406,13 +407,15 @@ static snd_pcm_fast_ops_t snd_pcm_file_fast_ops = {
|
||||||
* changed in future.
|
* changed in future.
|
||||||
*/
|
*/
|
||||||
int snd_pcm_file_open(snd_pcm_t **pcmp, const char *name,
|
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)
|
const char *fmt, int perm, snd_pcm_t *slave, int close_slave)
|
||||||
{
|
{
|
||||||
snd_pcm_t *pcm;
|
snd_pcm_t *pcm;
|
||||||
snd_pcm_file_t *file;
|
snd_pcm_file_t *file;
|
||||||
snd_pcm_file_format_t format;
|
snd_pcm_file_format_t format;
|
||||||
struct timespec timespec;
|
struct timespec timespec;
|
||||||
|
char *tmpname = NULL;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
assert(pcmp);
|
assert(pcmp);
|
||||||
|
|
@ -424,9 +427,30 @@ int snd_pcm_file_open(snd_pcm_t **pcmp, const char *name,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if (fname) {
|
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) {
|
if (fd < 0) {
|
||||||
SYSERR("open %s for writing failed", fname);
|
SYSERR("open %s for writing failed", fname);
|
||||||
|
free(tmpname);
|
||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -434,6 +458,7 @@ int snd_pcm_file_open(snd_pcm_t **pcmp, const char *name,
|
||||||
if (!file) {
|
if (!file) {
|
||||||
if (fname)
|
if (fname)
|
||||||
close(fd);
|
close(fd);
|
||||||
|
free(tmpname);
|
||||||
return -ENOMEM;
|
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);
|
SYSERR("open %s for reading failed", ifname);
|
||||||
if (fname)
|
if (fname)
|
||||||
close(fd);
|
close(fd);
|
||||||
|
free(file);
|
||||||
|
free(tmpname);
|
||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -461,6 +488,7 @@ int snd_pcm_file_open(snd_pcm_t **pcmp, const char *name,
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
free(file->fname);
|
free(file->fname);
|
||||||
free(file);
|
free(file);
|
||||||
|
free(tmpname);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
pcm->ops = &snd_pcm_file_ops;
|
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);
|
snd_pcm_link_appl_ptr(pcm, slave);
|
||||||
*pcmp = pcm;
|
*pcmp = pcm;
|
||||||
|
|
||||||
|
free(tmpname);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -541,7 +570,7 @@ int _snd_pcm_file_open(snd_pcm_t **pcmp, const char *name,
|
||||||
snd_config_t *slave = NULL, *sconf;
|
snd_config_t *slave = NULL, *sconf;
|
||||||
const char *fname = NULL, *ifname = NULL;
|
const char *fname = NULL, *ifname = NULL;
|
||||||
const char *format = NULL;
|
const char *format = NULL;
|
||||||
long fd = -1, ifd = -1;
|
long fd = -1, ifd = -1, trunc = 1;
|
||||||
long perm = 0600;
|
long perm = 0600;
|
||||||
snd_config_for_each(i, next, conf) {
|
snd_config_for_each(i, next, conf) {
|
||||||
snd_config_t *n = snd_config_iterator_entry(i);
|
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;
|
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);
|
SNDERR("Unknown field %s", id);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
@ -615,7 +651,8 @@ int _snd_pcm_file_open(snd_pcm_t **pcmp, const char *name,
|
||||||
snd_config_delete(sconf);
|
snd_config_delete(sconf);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
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)
|
if (err < 0)
|
||||||
snd_pcm_close(spcm);
|
snd_pcm_close(spcm);
|
||||||
return err;
|
return err;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue