]> git.alsa-project.org Git - alsa-lib.git/commitdiff
Add truncate option to PCM file plugin
authorTakashi Iwai <tiwai@suse.de>
Wed, 12 Mar 2008 15:30:26 +0000 (16:30 +0100)
committerTakashi Iwai <tiwai@suse.de>
Wed, 12 Mar 2008 15:30:26 +0000 (16:30 +0100)
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.

src/conf/alsa.conf
src/pcm/pcm_file.c

index 5c881f1abe3de3ecfc9973430a7c7c09c931263e..53baedf16f809d55d050b8e0916f5113e077a938 100644 (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 {
index a006696c4e742a2f845012c6d0ea092311996344..4d632707afba2f51390753a67318f88261906166 100644 (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;