]> git.alsa-project.org Git - alsa-lib.git/commitdiff
String array for default rate plugin list
authorTakashi Iwai <tiwai@suse.de>
Wed, 21 Mar 2007 23:58:42 +0000 (00:58 +0100)
committerTakashi Iwai <tiwai@suse.de>
Wed, 21 Mar 2007 23:58:42 +0000 (00:58 +0100)
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.

include/pcm_plugin.h
src/pcm/pcm_local.h
src/pcm/pcm_plug.c
src/pcm/pcm_rate.c

index 7d48527ec447771d7f18cb187383ef358f3324d5..f6e89651c13e482064a18d0b0b03aaf70094fe8e 100644 (file)
@@ -156,7 +156,8 @@ int _snd_pcm_route_open(snd_pcm_t **pcmp, const char *name,
  *  Rate plugin for linear formats
  */
 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);
 int _snd_pcm_rate_open(snd_pcm_t **pcmp, const char *name,
                       snd_config_t *root, snd_config_t *conf,
index ecf2e1d8809018f81f07114399e7f5827131a189..b3e319706455413ba38192e36795857cee7247ec 100644 (file)
@@ -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);
 
-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_FORMAT       (1U << SND_PCM_HW_PARAM_FORMAT)
index 58a165a9fae07b7a5852b0b43ae8637c2556dee2..87917c422a8338cb88ea5bc9a30096eaf9c667a7 100644 (file)
@@ -50,7 +50,7 @@ typedef struct {
        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;
        snd_pcm_route_ttable_entry_t *ttable;
        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,
                      const char *name,
                      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,
                      snd_pcm_route_ttable_entry_t *ttable,
                      unsigned int tt_ssize,
@@ -1092,6 +1092,9 @@ pcm.name {
                }
        }
        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
 }
 \endcode
@@ -1133,7 +1136,7 @@ int _snd_pcm_plug_open(snd_pcm_t **pcmp, const char *name,
        unsigned int cused, sused;
        snd_pcm_format_t sformat = SND_PCM_FORMAT_UNKNOWN;
        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_t *n = snd_config_iterator_entry(i);
@@ -1177,12 +1180,7 @@ int _snd_pcm_plug_open(snd_pcm_t **pcmp, const char *name,
 #endif
 #ifdef BUILD_PCM_PLUGIN_RATE
                if (strcmp(id, "rate_converter") == 0) {
-                       const char *str;
-                       if ((err = snd_config_get_string(n, &str)) < 0) {
-                               SNDERR("Invalid type for %s", id);
-                               return -EINVAL;
-                       }
-                       rate_converter = str;
+                       rate_converter = n;
                        continue;
                }
 #endif
index 0c594fd254694f65f93fa622842f0f729b669ca9..d0b934b620d6ec252d3c0fcfbde6cec722503548 100644 (file)
@@ -1251,20 +1251,47 @@ static snd_pcm_ops_t snd_pcm_rate_ops = {
 /**
  * \brief Get a default converter string
  * \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;
        /* look for default definition */
-       if (snd_config_search(root, "defaults.pcm.rate_converter", &n) >= 0) {
-               const char *str;
-               if (snd_config_get_string(n, &str) >= 0)
-                       return str;
-       }
+       if (snd_config_search(root, "defaults.pcm.rate_converter", &n) >= 0)
+               return n;
        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
  * \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
  *          changed in future.
  */
-int snd_pcm_rate_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sformat,
-                     unsigned int srate, const char *type, snd_pcm_t *slave, int close_slave)
+int snd_pcm_rate_open(snd_pcm_t **pcmp, const char *name,
+                     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_rate_t *rate;
-       snd_pcm_rate_open_func_t open_func;
-       char open_name[64];
+       const char *type;
        int err;
 #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);
 #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;
        snd_atomic_write_init(&rate->watom);
 
-       if (! type || ! *type)
-               type = "linear";
+       err = snd_pcm_new(&pcm, SND_PCM_TYPE_RATE, name, slave->stream, slave->mode);
+       if (err < 0) {
+               free(rate);
+               return err;
+       }
 
 #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;
+       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;
                }
-               snd_dlobj_cache_add(open_name, h, open_func);
+       } else {
+               SNDERR("Invalid type for rate converter");
+               snd_pcm_close(pcm);
+               return -EINVAL;
        }
-#else
-       open_func = SND_PCM_RATE_PLUGIN_ENTRY(linear);
-#endif
-
-       err = snd_pcm_new(&pcm, SND_PCM_TYPE_RATE, name, slave->stream, slave->mode);
        if (err < 0) {
-               free(rate);
-               return err;
+               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);
        if (err < 0) {
                snd_pcm_close(pcm);
                return err;
        }
+#endif
+
        if (! rate->ops.init || ! (rate->ops.convert || rate->ops.convert_s16) ||
            ! rate->ops.input_frames || ! rate->ops.output_frames) {
                SNDERR("Inproper rate plugin %s initialization", type);
@@ -1386,7 +1413,10 @@ pcm.name {
                 rate INT        # Slave rate
                 [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
 }
 \endcode
@@ -1423,7 +1453,7 @@ int _snd_pcm_rate_open(snd_pcm_t **pcmp, const char *name,
        snd_config_t *slave = NULL, *sconf;
        snd_pcm_format_t sformat = SND_PCM_FORMAT_UNKNOWN;
        int srate = -1;
-       const char *type = NULL;
+       const snd_config_t *converter = NULL;
 
        snd_config_for_each(i, next, conf) {
                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;
                }
                if (strcmp(id, "converter") == 0) {
-                       const char *str;
-                       if ((err = snd_config_get_string(n, &str)) < 0) {
-                               SNDERR("invalid converter string");
-                               return -EINVAL;
-                       }
-                       type = str;
+                       converter = n;
                        continue;
                }
                SNDERR("Unknown field %s", id);
@@ -1469,7 +1494,7 @@ int _snd_pcm_rate_open(snd_pcm_t **pcmp, const char *name,
        if (err < 0)
                return err;
        err = snd_pcm_rate_open(pcmp, name, sformat, (unsigned int) srate,
-                               type, spcm, 1);
+                               converter, spcm, 1);
        if (err < 0)
                snd_pcm_close(spcm);
        return err;