Added possibility to disable also channel and format conversions + softvol.
authorJaroslav Kysela <perex@perex.cz>
Fri, 11 Jan 2008 16:21:44 +0000 (17:21 +0100)
committerJaroslav Kysela <perex@perex.cz>
Fri, 11 Jan 2008 16:21:44 +0000 (17:21 +0100)
Unified disable option using mode bits in snd_pcm_open().

include/pcm.h
src/pcm/pcm_plug.c
src/pcm/pcm_softvol.c

index d217bb9..66082ce 100644 (file)
@@ -292,9 +292,17 @@ typedef unsigned long snd_pcm_uframes_t;
 typedef long snd_pcm_sframes_t;
 
 /** Non blocking mode (flag for open mode) \hideinitializer */
-#define SND_PCM_NONBLOCK               0x0001
+#define SND_PCM_NONBLOCK               0x00000001
 /** Async notification (flag for open mode) \hideinitializer */
-#define SND_PCM_ASYNC                  0x0002
+#define SND_PCM_ASYNC                  0x00000002
+/** Disable automatic (but not forced!) rate resamplinig */
+#define SND_PCM_NO_AUTO_RESAMPLE       0x00010000
+/** Disable automatic (but not forced!) channel conversion */
+#define SND_PCM_NO_AUTO_CHANNELS       0x00020000
+/** Disable automatic (but not forced!) format conversion */
+#define SND_PCM_NO_AUTO_FORMAT         0x00040000
+/** Disable soft volume control */
+#define SND_PCM_NO_SOFTVOL             0x00080000
 
 /** PCM handle */
 typedef struct _snd_pcm snd_pcm_t;
index 0c2ff6e..ee74f44 100644 (file)
@@ -707,7 +707,9 @@ static int snd_pcm_plug_hw_refine_schange(snd_pcm_t *pcm, snd_pcm_hw_params_t *p
        snd_interval_t t, buffer_size;
        const snd_interval_t *srate, *crate;
 
-       if (plug->srate == -2)
+       if (plug->srate == -2 ||
+           (pcm->mode & pcm->mode & SND_PCM_NO_AUTO_RESAMPLE) ||
+           (params->flags & SND_PCM_HW_PARAMS_NORESAMPLE))
                links |= SND_PCM_HW_PARBIT_RATE;
        else {
                err = snd_pcm_hw_param_refine_multiple(slave, sparams, SND_PCM_HW_PARAM_RATE, params);
@@ -715,14 +717,14 @@ static int snd_pcm_plug_hw_refine_schange(snd_pcm_t *pcm, snd_pcm_hw_params_t *p
                        return err;
        }
        
-       if (plug->schannels == -2)
+       if (plug->schannels == -2 || (pcm->mode & SND_PCM_NO_AUTO_CHANNELS))
                links |= SND_PCM_HW_PARBIT_CHANNELS;
        else {
                err = snd_pcm_hw_param_refine_near(slave, sparams, SND_PCM_HW_PARAM_CHANNELS, params);
                if (err < 0)
                        return err;
        }
-       if (plug->sformat == -2)
+       if (plug->sformat == -2 || (pcm->mode & SND_PCM_NO_AUTO_FORMAT))
                links |= SND_PCM_HW_PARBIT_FORMAT;
        else {
                format_mask = snd_pcm_hw_param_get_mask(params, SND_PCM_HW_PARAM_FORMAT);
@@ -791,8 +793,6 @@ static int snd_pcm_plug_hw_refine_schange(snd_pcm_t *pcm, snd_pcm_hw_params_t *p
        err = _snd_pcm_hw_params_refine(sparams, links, params);
        if (err < 0)
                return err;
-       if (params->flags & SND_PCM_HW_PARAMS_NORESAMPLE)
-               snd_interval_copy((snd_interval_t *)snd_pcm_hw_param_get_interval(params, SND_PCM_HW_PARAM_RATE), snd_pcm_hw_param_get_interval(sparams, SND_PCM_HW_PARAM_RATE));
        return 0;
 }
        
@@ -811,10 +811,10 @@ static int snd_pcm_plug_hw_refine_cchange(snd_pcm_t *pcm ATTRIBUTE_UNUSED,
        const snd_interval_t *sbuffer_size;
        const snd_interval_t *srate, *crate;
 
-       if (plug->schannels == -2)
+       if (plug->schannels == -2 || (pcm->mode & SND_PCM_NO_AUTO_CHANNELS))
                links |= SND_PCM_HW_PARBIT_CHANNELS;
 
-       if (plug->sformat == -2)
+       if (plug->sformat == -2 || (pcm->mode & SND_PCM_NO_AUTO_FORMAT))
                links |= SND_PCM_HW_PARBIT_FORMAT;
        else {
                format_mask = snd_pcm_hw_param_get_mask(params,
@@ -857,7 +857,9 @@ static int snd_pcm_plug_hw_refine_cchange(snd_pcm_t *pcm ATTRIBUTE_UNUSED,
                        return err;
        }
 
-       if (plug->srate == -2)
+       if (plug->srate == -2 ||
+           (pcm->mode & SND_PCM_NO_AUTO_RESAMPLE) ||
+           (params->flags & SND_PCM_HW_PARAMS_NORESAMPLE))
                links |= SND_PCM_HW_PARBIT_RATE;
        else {
                unsigned int rate_min, srate_min;
@@ -895,8 +897,6 @@ static int snd_pcm_plug_hw_refine_cchange(snd_pcm_t *pcm ATTRIBUTE_UNUSED,
        err = _snd_pcm_hw_params_refine(params, links, sparams);
        if (err < 0)
                return err;
-       if (params->flags & SND_PCM_HW_PARAMS_NORESAMPLE)
-               snd_interval_copy((snd_interval_t *)snd_pcm_hw_param_get_interval(params, SND_PCM_HW_PARAM_RATE), snd_pcm_hw_param_get_interval(sparams, SND_PCM_HW_PARAM_RATE));
        /* FIXME */
        params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
        return 0;
index 8f91204..7af7f40 100644 (file)
@@ -969,34 +969,43 @@ int _snd_pcm_softvol_open(snd_pcm_t **pcmp, const char *name,
                SNDERR("Invalid resolution value %d", resolution);
                return -EINVAL;
        }
-       err = snd_pcm_slave_conf(root, slave, &sconf, 1,
-                                SND_PCM_HW_PARAM_FORMAT, 0, &sformat);
-       if (err < 0)
-               return err;
-       if (sformat != SND_PCM_FORMAT_UNKNOWN &&
-           sformat != SND_PCM_FORMAT_S16_LE &&
-           sformat != SND_PCM_FORMAT_S16_BE &&
-           sformat != SND_PCM_FORMAT_S24_3LE && 
-           sformat != SND_PCM_FORMAT_S32_LE &&
-           sformat != SND_PCM_FORMAT_S32_BE) {
-               SNDERR("only S16_LE, S16_BE, S24_3LE, S32_LE or S32_BE format "
-                      "is supported");
+       if (mode & SND_PCM_NO_SOFTVOL) {
+               err = snd_pcm_slave_conf(root, slave, &sconf, 0);
+               if (err < 0)
+                       return err;
+               err = snd_pcm_open_named_slave(pcmp, name, root, sconf, stream,
+                                              mode, conf);
                snd_config_delete(sconf);
-               return -EINVAL;
-       }
-       err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode, conf);
-       snd_config_delete(sconf);
-       if (err < 0)
-               return err;
-       snd_ctl_elem_id_alloca(&ctl_id);
-       if ((err = snd_pcm_parse_control_id(control, ctl_id, &card, &cchannels, NULL)) < 0) {
-               snd_pcm_close(spcm);
-               return err;
+       } else {
+               snd_ctl_elem_id_alloca(&ctl_id);
+               err = snd_pcm_slave_conf(root, slave, &sconf, 1,
+                                        SND_PCM_HW_PARAM_FORMAT, 0, &sformat);
+               if (err < 0)
+                       return err;
+               if (sformat != SND_PCM_FORMAT_UNKNOWN &&
+                   sformat != SND_PCM_FORMAT_S16_LE &&
+                   sformat != SND_PCM_FORMAT_S16_BE &&
+                   sformat != SND_PCM_FORMAT_S24_3LE && 
+                   sformat != SND_PCM_FORMAT_S32_LE &&
+                   sformat != SND_PCM_FORMAT_S32_BE) {
+                       SNDERR("only S16_LE, S16_BE, S24_3LE, S32_LE or S32_BE format "
+                              "is supported");
+                       snd_config_delete(sconf);
+                       return -EINVAL;
+               }
+               err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode, conf);
+               snd_config_delete(sconf);
+               if (err < 0)
+                       return err;
+               if ((err = snd_pcm_parse_control_id(control, ctl_id, &card, &cchannels, NULL)) < 0) {
+                       snd_pcm_close(spcm);
+                       return err;
+               }
+               err = snd_pcm_softvol_open(pcmp, name, sformat, card, ctl_id, cchannels,
+                                          min_dB, max_dB, resolution, spcm, 1);
+               if (err < 0)
+                       snd_pcm_close(spcm);
        }
-       err = snd_pcm_softvol_open(pcmp, name, sformat, card, ctl_id, cchannels,
-                                  min_dB, max_dB, resolution, spcm, 1);
-       if (err < 0)
-               snd_pcm_close(spcm);
        return err;
 }
 #ifndef DOC_HIDDEN