mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2025-10-31 22:25:35 -04:00
String array for default rate plugin list
Change the rate converter type to allow string arrays in addition to a string. When a string array is given, the rate plugin probes each string and try to load the converter plugin in the order of the list. For example, you can set defaults.pcm.rate_converter [ "samplerate" "linear" ] so that samplerate plugin is preferred to linear plugin if it's installed.
This commit is contained in:
parent
70e4ec9d08
commit
36987b02c0
4 changed files with 88 additions and 64 deletions
|
|
@ -156,7 +156,8 @@ int _snd_pcm_route_open(snd_pcm_t **pcmp, const char *name,
|
||||||
* Rate plugin for linear formats
|
* Rate plugin for linear formats
|
||||||
*/
|
*/
|
||||||
int snd_pcm_rate_open(snd_pcm_t **pcmp, const char *name,
|
int snd_pcm_rate_open(snd_pcm_t **pcmp, const char *name,
|
||||||
snd_pcm_format_t sformat, unsigned int srate, const char *converter,
|
snd_pcm_format_t sformat, unsigned int srate,
|
||||||
|
const snd_config_t *converter,
|
||||||
snd_pcm_t *slave, int close_slave);
|
snd_pcm_t *slave, int close_slave);
|
||||||
int _snd_pcm_rate_open(snd_pcm_t **pcmp, const char *name,
|
int _snd_pcm_rate_open(snd_pcm_t **pcmp, const char *name,
|
||||||
snd_config_t *root, snd_config_t *conf,
|
snd_config_t *root, snd_config_t *conf,
|
||||||
|
|
|
||||||
|
|
@ -756,7 +756,7 @@ int snd_pcm_hw_open_fd(snd_pcm_t **pcmp, const char *name, int fd, int mmap_emul
|
||||||
|
|
||||||
int snd_pcm_wait_nocheck(snd_pcm_t *pcm, int timeout);
|
int snd_pcm_wait_nocheck(snd_pcm_t *pcm, int timeout);
|
||||||
|
|
||||||
const char *snd_pcm_rate_get_default_converter(snd_config_t *root);
|
const snd_config_t *snd_pcm_rate_get_default_converter(snd_config_t *root);
|
||||||
|
|
||||||
#define SND_PCM_HW_PARBIT_ACCESS (1U << SND_PCM_HW_PARAM_ACCESS)
|
#define SND_PCM_HW_PARBIT_ACCESS (1U << SND_PCM_HW_PARAM_ACCESS)
|
||||||
#define SND_PCM_HW_PARBIT_FORMAT (1U << SND_PCM_HW_PARAM_FORMAT)
|
#define SND_PCM_HW_PARBIT_FORMAT (1U << SND_PCM_HW_PARAM_FORMAT)
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ typedef struct {
|
||||||
snd_pcm_format_t sformat;
|
snd_pcm_format_t sformat;
|
||||||
int schannels;
|
int schannels;
|
||||||
int srate;
|
int srate;
|
||||||
const char *rate_converter;
|
const snd_config_t *rate_converter;
|
||||||
enum snd_pcm_plug_route_policy route_policy;
|
enum snd_pcm_plug_route_policy route_policy;
|
||||||
snd_pcm_route_ttable_entry_t *ttable;
|
snd_pcm_route_ttable_entry_t *ttable;
|
||||||
int ttable_ok, ttable_last;
|
int ttable_ok, ttable_last;
|
||||||
|
|
@ -1015,7 +1015,7 @@ static snd_pcm_ops_t snd_pcm_plug_ops = {
|
||||||
int snd_pcm_plug_open(snd_pcm_t **pcmp,
|
int snd_pcm_plug_open(snd_pcm_t **pcmp,
|
||||||
const char *name,
|
const char *name,
|
||||||
snd_pcm_format_t sformat, int schannels, int srate,
|
snd_pcm_format_t sformat, int schannels, int srate,
|
||||||
const char *rate_converter,
|
const snd_config_t *rate_converter,
|
||||||
enum snd_pcm_plug_route_policy route_policy,
|
enum snd_pcm_plug_route_policy route_policy,
|
||||||
snd_pcm_route_ttable_entry_t *ttable,
|
snd_pcm_route_ttable_entry_t *ttable,
|
||||||
unsigned int tt_ssize,
|
unsigned int tt_ssize,
|
||||||
|
|
@ -1092,6 +1092,9 @@ pcm.name {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rate_converter STR # type of rate converter
|
rate_converter STR # type of rate converter
|
||||||
|
# or
|
||||||
|
rate_converter [ STR1 STR2 ... ]
|
||||||
|
# type of rate converter
|
||||||
# default value is taken from defaults.pcm.rate_converter
|
# default value is taken from defaults.pcm.rate_converter
|
||||||
}
|
}
|
||||||
\endcode
|
\endcode
|
||||||
|
|
@ -1133,7 +1136,7 @@ int _snd_pcm_plug_open(snd_pcm_t **pcmp, const char *name,
|
||||||
unsigned int cused, sused;
|
unsigned int cused, sused;
|
||||||
snd_pcm_format_t sformat = SND_PCM_FORMAT_UNKNOWN;
|
snd_pcm_format_t sformat = SND_PCM_FORMAT_UNKNOWN;
|
||||||
int schannels = -1, srate = -1;
|
int schannels = -1, srate = -1;
|
||||||
const char *rate_converter = NULL;
|
const snd_config_t *rate_converter = NULL;
|
||||||
|
|
||||||
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);
|
||||||
|
|
@ -1177,12 +1180,7 @@ int _snd_pcm_plug_open(snd_pcm_t **pcmp, const char *name,
|
||||||
#endif
|
#endif
|
||||||
#ifdef BUILD_PCM_PLUGIN_RATE
|
#ifdef BUILD_PCM_PLUGIN_RATE
|
||||||
if (strcmp(id, "rate_converter") == 0) {
|
if (strcmp(id, "rate_converter") == 0) {
|
||||||
const char *str;
|
rate_converter = n;
|
||||||
if ((err = snd_config_get_string(n, &str)) < 0) {
|
|
||||||
SNDERR("Invalid type for %s", id);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
rate_converter = str;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -1251,20 +1251,47 @@ static snd_pcm_ops_t snd_pcm_rate_ops = {
|
||||||
/**
|
/**
|
||||||
* \brief Get a default converter string
|
* \brief Get a default converter string
|
||||||
* \param root Root configuration node
|
* \param root Root configuration node
|
||||||
* \retval A const string if found, or NULL
|
* \retval A const config item if found, or NULL
|
||||||
*/
|
*/
|
||||||
const char *snd_pcm_rate_get_default_converter(snd_config_t *root)
|
const snd_config_t *snd_pcm_rate_get_default_converter(snd_config_t *root)
|
||||||
{
|
{
|
||||||
snd_config_t *n;
|
snd_config_t *n;
|
||||||
/* look for default definition */
|
/* look for default definition */
|
||||||
if (snd_config_search(root, "defaults.pcm.rate_converter", &n) >= 0) {
|
if (snd_config_search(root, "defaults.pcm.rate_converter", &n) >= 0)
|
||||||
const char *str;
|
return n;
|
||||||
if (snd_config_get_string(n, &str) >= 0)
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef PIC
|
||||||
|
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;
|
||||||
|
|
||||||
|
snprintf(open_name, sizeof(open_name), "_snd_pcm_rate_%s_open", type);
|
||||||
|
open_func = snd_dlobj_cache_lookup(open_name);
|
||||||
|
if (!open_func) {
|
||||||
|
void *h;
|
||||||
|
char lib_name[128], *lib = NULL;
|
||||||
|
if (strcmp(type, "linear")) {
|
||||||
|
snprintf(lib_name, sizeof(lib_name),
|
||||||
|
"%s/libasound_module_rate_%s.so", PKGLIBDIR, type);
|
||||||
|
lib = lib_name;
|
||||||
|
}
|
||||||
|
h = snd_dlopen(lib, RTLD_NOW);
|
||||||
|
if (!h)
|
||||||
|
return -ENOENT;
|
||||||
|
open_func = snd_dlsym(h, open_name, NULL);
|
||||||
|
if (!open_func) {
|
||||||
|
snd_dlclose(h);
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
snd_dlobj_cache_add(open_name, h, open_func);
|
||||||
|
}
|
||||||
|
return open_func(SND_PCM_RATE_PLUGIN_VERSION, &rate->obj, &rate->ops);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Creates a new rate PCM
|
* \brief Creates a new rate PCM
|
||||||
* \param pcmp Returns created PCM handle
|
* \param pcmp Returns created PCM handle
|
||||||
|
|
@ -1279,15 +1306,17 @@ const char *snd_pcm_rate_get_default_converter(snd_config_t *root)
|
||||||
* of compatibility reasons. The prototype might be freely
|
* of compatibility reasons. The prototype might be freely
|
||||||
* changed in future.
|
* changed in future.
|
||||||
*/
|
*/
|
||||||
int snd_pcm_rate_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sformat,
|
int snd_pcm_rate_open(snd_pcm_t **pcmp, const char *name,
|
||||||
unsigned int srate, const char *type, snd_pcm_t *slave, int close_slave)
|
snd_pcm_format_t sformat, unsigned int srate,
|
||||||
|
const snd_config_t *converter,
|
||||||
|
snd_pcm_t *slave, int close_slave)
|
||||||
{
|
{
|
||||||
snd_pcm_t *pcm;
|
snd_pcm_t *pcm;
|
||||||
snd_pcm_rate_t *rate;
|
snd_pcm_rate_t *rate;
|
||||||
snd_pcm_rate_open_func_t open_func;
|
const char *type;
|
||||||
char open_name[64];
|
|
||||||
int err;
|
int err;
|
||||||
#ifndef PIC
|
#ifndef PIC
|
||||||
|
snd_pcm_rate_open_func_t open_func;
|
||||||
extern int SND_PCM_RATE_PLUGIN_ENTRY(linear) (unsigned int version, void **objp, snd_pcm_rate_ops_t *ops);
|
extern int SND_PCM_RATE_PLUGIN_ENTRY(linear) (unsigned int version, void **objp, snd_pcm_rate_ops_t *ops);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -1305,49 +1334,47 @@ int snd_pcm_rate_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sform
|
||||||
rate->sformat = sformat;
|
rate->sformat = sformat;
|
||||||
snd_atomic_write_init(&rate->watom);
|
snd_atomic_write_init(&rate->watom);
|
||||||
|
|
||||||
if (! type || ! *type)
|
|
||||||
type = "linear";
|
|
||||||
|
|
||||||
#ifdef PIC
|
|
||||||
snprintf(open_name, sizeof(open_name), "_snd_pcm_rate_%s_open", type);
|
|
||||||
open_func = snd_dlobj_cache_lookup(open_name);
|
|
||||||
if (! open_func) {
|
|
||||||
void *h;
|
|
||||||
char lib_name[128], *lib = NULL;
|
|
||||||
if (strcmp(type, "linear")) {
|
|
||||||
snprintf(lib_name, sizeof(lib_name),
|
|
||||||
"%s/libasound_module_rate_%s.so", PKGLIBDIR, type);
|
|
||||||
lib = lib_name;
|
|
||||||
}
|
|
||||||
h = snd_dlopen(lib, RTLD_NOW);
|
|
||||||
if (! h) {
|
|
||||||
SNDERR("Cannot open library for type %s", type);
|
|
||||||
free(rate);
|
|
||||||
return -ENOENT;
|
|
||||||
}
|
|
||||||
open_func = snd_dlsym(h, open_name, NULL);
|
|
||||||
if (! open_func) {
|
|
||||||
SNDERR("Cannot find function %s", open_name);
|
|
||||||
snd_dlclose(h);
|
|
||||||
free(rate);
|
|
||||||
return -ENOENT;
|
|
||||||
}
|
|
||||||
snd_dlobj_cache_add(open_name, h, open_func);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
open_func = SND_PCM_RATE_PLUGIN_ENTRY(linear);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
err = snd_pcm_new(&pcm, SND_PCM_TYPE_RATE, name, slave->stream, slave->mode);
|
err = snd_pcm_new(&pcm, SND_PCM_TYPE_RATE, name, slave->stream, slave->mode);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
free(rate);
|
free(rate);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef PIC
|
||||||
|
err = -ENOENT;
|
||||||
|
if (!converter)
|
||||||
|
err = rate_open_func(rate, "linear");
|
||||||
|
else if (!snd_config_get_string(converter, &type))
|
||||||
|
err = rate_open_func(rate, type);
|
||||||
|
else if (snd_config_get_type(converter) == SND_CONFIG_TYPE_COMPOUND) {
|
||||||
|
snd_config_iterator_t i, next;
|
||||||
|
snd_config_for_each(i, next, converter) {
|
||||||
|
snd_config_t *n = snd_config_iterator_entry(i);
|
||||||
|
if (snd_config_get_string(n, &type) < 0)
|
||||||
|
break;
|
||||||
|
err = rate_open_func(rate, type);
|
||||||
|
if (!err)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
SNDERR("Invalid type for rate converter");
|
||||||
|
snd_pcm_close(pcm);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
if (err < 0) {
|
||||||
|
SNDERR("Cannot find rate converter");
|
||||||
|
snd_pcm_close(pcm);
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
open_func = SND_PCM_RATE_PLUGIN_ENTRY(linear);
|
||||||
err = open_func(SND_PCM_RATE_PLUGIN_VERSION, &rate->obj, &rate->ops);
|
err = open_func(SND_PCM_RATE_PLUGIN_VERSION, &rate->obj, &rate->ops);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
snd_pcm_close(pcm);
|
snd_pcm_close(pcm);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (! rate->ops.init || ! (rate->ops.convert || rate->ops.convert_s16) ||
|
if (! rate->ops.init || ! (rate->ops.convert || rate->ops.convert_s16) ||
|
||||||
! rate->ops.input_frames || ! rate->ops.output_frames) {
|
! rate->ops.input_frames || ! rate->ops.output_frames) {
|
||||||
SNDERR("Inproper rate plugin %s initialization", type);
|
SNDERR("Inproper rate plugin %s initialization", type);
|
||||||
|
|
@ -1386,7 +1413,10 @@ pcm.name {
|
||||||
rate INT # Slave rate
|
rate INT # Slave rate
|
||||||
[format STR] # Slave format
|
[format STR] # Slave format
|
||||||
}
|
}
|
||||||
[converter STR] # Converter type, default is taken from
|
converter STR # optional
|
||||||
|
# or
|
||||||
|
converter [ STR1 STR2 ... ] # optional
|
||||||
|
# Converter type, default is taken from
|
||||||
# defaults.pcm.rate_converter
|
# defaults.pcm.rate_converter
|
||||||
}
|
}
|
||||||
\endcode
|
\endcode
|
||||||
|
|
@ -1423,7 +1453,7 @@ int _snd_pcm_rate_open(snd_pcm_t **pcmp, const char *name,
|
||||||
snd_config_t *slave = NULL, *sconf;
|
snd_config_t *slave = NULL, *sconf;
|
||||||
snd_pcm_format_t sformat = SND_PCM_FORMAT_UNKNOWN;
|
snd_pcm_format_t sformat = SND_PCM_FORMAT_UNKNOWN;
|
||||||
int srate = -1;
|
int srate = -1;
|
||||||
const char *type = NULL;
|
const snd_config_t *converter = NULL;
|
||||||
|
|
||||||
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);
|
||||||
|
|
@ -1437,12 +1467,7 @@ int _snd_pcm_rate_open(snd_pcm_t **pcmp, const char *name,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (strcmp(id, "converter") == 0) {
|
if (strcmp(id, "converter") == 0) {
|
||||||
const char *str;
|
converter = n;
|
||||||
if ((err = snd_config_get_string(n, &str)) < 0) {
|
|
||||||
SNDERR("invalid converter string");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
type = str;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
SNDERR("Unknown field %s", id);
|
SNDERR("Unknown field %s", id);
|
||||||
|
|
@ -1469,7 +1494,7 @@ int _snd_pcm_rate_open(snd_pcm_t **pcmp, const char *name,
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
err = snd_pcm_rate_open(pcmp, name, sformat, (unsigned int) srate,
|
err = snd_pcm_rate_open(pcmp, name, sformat, (unsigned int) srate,
|
||||||
type, spcm, 1);
|
converter, 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