]> git.alsa-project.org Git - alsa-lib.git/commitdiff
Query the supported rate ranges from rate plugins
authorTakashi Iwai <tiwai@suse.de>
Tue, 2 Jun 2009 14:13:01 +0000 (16:13 +0200)
committerTakashi Iwai <tiwai@suse.de>
Tue, 2 Jun 2009 14:26:03 +0000 (16:26 +0200)
Extend the PCM-rate plugin protocol to allow the host to query the
supported sample rates.  The protocol version is bumped to 0x010002,
and the version number negotiaion is slightly changed.
Now the plugin is supposed to fill the version it supports in return.

The old versioned plugins are still supported, but they may spew
version-mismatch warning prints.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
include/pcm_rate.h
src/pcm/pcm_rate.c
src/pcm/pcm_rate_linear.c

index d211e09702bc9370577bc32483235610452b7051..4d70df269351934b2cb7bfd5baed7bd0373a16a8 100644 (file)
@@ -38,7 +38,7 @@ extern "C" {
 /**
  * Protocol version
  */
-#define SND_PCM_RATE_PLUGIN_VERSION    0x010001
+#define SND_PCM_RATE_PLUGIN_VERSION    0x010002
 
 /** hw_params information for a single side */
 typedef struct snd_pcm_rate_side_info {
@@ -98,6 +98,22 @@ typedef struct snd_pcm_rate_ops {
         * compute the frame size for output
         */
        snd_pcm_uframes_t (*output_frames)(void *obj, snd_pcm_uframes_t frames);
+       /**
+        * the protocol version the plugin supports;
+        * new field since version 0x010002
+        */
+       unsigned int version;
+       /**
+        * return the supported min / max sample rates;
+        * new ops since version 0x010002
+        */
+       int (*get_supported_rates)(void *obj, unsigned int *rate_min,
+                                  unsigned int *rate_max);
+       /**
+        * show some status messages for verbose mode;
+        * new ops since version 0x010002
+        */
+       void (*dump)(void *obj, snd_output_t *out);
 } snd_pcm_rate_ops_t;
 
 /** open function type */
@@ -110,6 +126,26 @@ typedef int (*snd_pcm_rate_open_func_t)(unsigned int version, void **objp,
 #define SND_PCM_RATE_PLUGIN_ENTRY(name) _snd_pcm_rate_##name##_open
 
 
+#ifndef DOC_HIDDEN
+/* old rate_ops for protocol version 0x010001 */
+typedef struct snd_pcm_rate_old_ops {
+       void (*close)(void *obj);
+       int (*init)(void *obj, snd_pcm_rate_info_t *info);
+       void (*free)(void *obj);
+       void (*reset)(void *obj);
+       int (*adjust_pitch)(void *obj, snd_pcm_rate_info_t *info);
+       void (*convert)(void *obj,
+                       const snd_pcm_channel_area_t *dst_areas,
+                       snd_pcm_uframes_t dst_offset, unsigned int dst_frames,
+                       const snd_pcm_channel_area_t *src_areas,
+                       snd_pcm_uframes_t src_offset, unsigned int src_frames);
+       void (*convert_s16)(void *obj, int16_t *dst, unsigned int dst_frames,
+                           const int16_t *src, unsigned int src_frames);
+       snd_pcm_uframes_t (*input_frames)(void *obj, snd_pcm_uframes_t frames);
+       snd_pcm_uframes_t (*output_frames)(void *obj, snd_pcm_uframes_t frames);
+} snd_pcm_rate_old_ops_t;
+#endif
+
 #ifdef __cplusplus
 }
 #endif
index a97a5de53b8f6d510e845da4aefd7dbc117a7311..c28884bc08564be8af1cfb090747a263631a0e9c 100644 (file)
@@ -69,12 +69,17 @@ struct _snd_pcm_rate {
        int16_t *dst_buf;
        int start_pending; /* start is triggered but not commited to slave */
        snd_htimestamp_t trigger_tstamp;
+       unsigned int plugin_version;
+       unsigned int rate_min, rate_max;
 };
 
+#define SND_PCM_RATE_PLUGIN_VERSION_OLD        0x010001        /* old rate plugin */
+
 #endif /* DOC_HIDDEN */
 
 static int snd_pcm_rate_hw_refine_cprepare(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params)
 {
+       snd_pcm_rate_t *rate = pcm->private_data;
        int err;
        snd_pcm_access_mask_t access_mask = { SND_PCM_ACCBIT_SHM };
        snd_pcm_format_mask_t format_mask = { SND_PCM_FMTBIT_LINEAR };
@@ -89,14 +94,18 @@ static int snd_pcm_rate_hw_refine_cprepare(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_
        err = _snd_pcm_hw_params_set_subformat(params, SND_PCM_SUBFORMAT_STD);
        if (err < 0)
                return err;
-       err = _snd_pcm_hw_param_set_min(params,
-                                       SND_PCM_HW_PARAM_RATE, SND_PCM_PLUGIN_RATE_MIN, 0);
-       if (err < 0)
-               return err;
-       err = _snd_pcm_hw_param_set_max(params,
-                                       SND_PCM_HW_PARAM_RATE, SND_PCM_PLUGIN_RATE_MAX, 0);
-       if (err < 0)
-               return err;
+       if (rate->rate_min) {
+               err = _snd_pcm_hw_param_set_min(params, SND_PCM_HW_PARAM_RATE,
+                                               rate->rate_min, 0);
+               if (err < 0)
+                       return err;
+       }
+       if (rate->rate_max) {
+               err = _snd_pcm_hw_param_set_max(params, SND_PCM_HW_PARAM_RATE,
+                                               rate->rate_max, 0);
+               if (err < 0)
+                       return err;
+       }
        params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
        return 0;
 }
@@ -1178,6 +1187,9 @@ static void snd_pcm_rate_dump(snd_pcm_t *pcm, snd_output_t *out)
                snd_output_printf(out, "Rate conversion PCM (%d, sformat=%s)\n", 
                        rate->srate,
                        snd_pcm_format_name(rate->sformat));
+       if (rate->ops.dump)
+               rate->ops.dump(rate->obj, out);
+       snd_output_printf(out, "Protocol version: %x\n", rate->plugin_version);
        if (pcm->setup) {
                snd_output_printf(out, "Its setup is:\n");
                snd_pcm_dump_setup(pcm, out);
@@ -1264,6 +1276,7 @@ static int rate_open_func(snd_pcm_rate_t *rate, const char *type)
 {
        char open_name[64];
        snd_pcm_rate_open_func_t open_func;
+       int err;
 
        snprintf(open_name, sizeof(open_name), "_snd_pcm_rate_%s_open", type);
        open_func = snd_dlobj_cache_lookup(open_name);
@@ -1285,7 +1298,25 @@ static int rate_open_func(snd_pcm_rate_t *rate, const char *type)
                }
                snd_dlobj_cache_add(open_name, h, open_func);
        }
-       return open_func(SND_PCM_RATE_PLUGIN_VERSION, &rate->obj, &rate->ops);
+
+       rate->rate_min = SND_PCM_PLUGIN_RATE_MIN;
+       rate->rate_max = SND_PCM_PLUGIN_RATE_MAX;
+       rate->plugin_version = SND_PCM_RATE_PLUGIN_VERSION;
+
+       err = open_func(SND_PCM_RATE_PLUGIN_VERSION, &rate->obj, &rate->ops);
+       if (!err) {
+               rate->plugin_version = rate->ops.version;
+               if (rate->ops.get_supported_rates)
+                       rate->ops.get_supported_rates(rate->obj,
+                                                     &rate->rate_min,
+                                                     &rate->rate_max);
+               return 0;
+       }
+
+       /* try to open with the old protocol version */
+       rate->plugin_version = SND_PCM_RATE_PLUGIN_VERSION_OLD;
+       return open_func(SND_PCM_RATE_PLUGIN_VERSION_OLD,
+                        &rate->obj, &rate->ops);
 }
 #endif
 
index 20e119becc45a402bc8287d9305857e6600d93fc..8b2d2d02c5026724efc13b756a371830a12bd526 100644 (file)
@@ -405,6 +405,19 @@ static void linear_close(void *obj)
        free(obj);
 }
 
+static int get_supported_rates(void *rate, unsigned int *rate_min,
+                              unsigned int *rate_max)
+{
+       *rate_min = SND_PCM_PLUGIN_RATE_MIN;
+       *rate_max = SND_PCM_PLUGIN_RATE_MAX;
+       return 0;
+}
+
+static void linear_dump(void *rate, snd_output_t *out)
+{
+       snd_output_printf(out, "Converter: linear-interpolation\n");
+}
+
 static const snd_pcm_rate_ops_t linear_ops = {
        .close = linear_close,
        .init = linear_init,
@@ -414,17 +427,15 @@ static const snd_pcm_rate_ops_t linear_ops = {
        .convert = linear_convert,
        .input_frames = input_frames,
        .output_frames = output_frames,
+       .version = SND_PCM_RATE_PLUGIN_VERSION,
+       .get_supported_rates = get_supported_rates,
+       .dump = linear_dump,
 };
 
 int SND_PCM_RATE_PLUGIN_ENTRY(linear) (unsigned int version, void **objp, snd_pcm_rate_ops_t *ops)
 {
        struct rate_linear *rate;
 
-       if (version != SND_PCM_RATE_PLUGIN_VERSION) {
-               SNDERR("Invalid plugin version %x\n", version);
-               return -EINVAL;
-       }
-
        rate = calloc(1, sizeof(*rate));
        if (! rate)
                return -ENOMEM;