/**
* 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 {
* 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 */
#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
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 };
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;
}
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);
{
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);
}
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
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,
.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;