OSDN Git Service

Removed snd_config_string_replace function.
authorJaroslav Kysela <perex@perex.cz>
Mon, 18 Jun 2001 14:14:49 +0000 (14:14 +0000)
committerJaroslav Kysela <perex@perex.cz>
Mon, 18 Jun 2001 14:14:49 +0000 (14:14 +0000)
Added back modified snd_config_refer_load function.
Added snd_func_private_pcm_subdevice function.
Removed the callback from the snd_sctl_build function (no more required).
Modified alsa.conf to use refer {} blocks again.
Modified card specific conf files to use new snd_func_private_pcm_subdevice function.

include/conf.h
include/control.h
src/alsa.conf
src/cards/EMU10K1.conf
src/cards/SI_7018.conf
src/cards/TRID4DWAVENX.conf
src/confmisc.c
src/control/setup.c
src/pcm/pcm.c
src/pcm/pcm_hooks.c

index 27f0d69..198e42c 100644 (file)
@@ -95,10 +95,8 @@ int snd_config_get_ctl_iface(snd_config_t *conf);
 
 typedef int (snd_config_string_replace_callback_t)(const char *what, char **dst, void *private_data);
 
-int snd_config_string_replace(const char *src, char idchr,
-                             snd_config_string_replace_callback_t *callback,
-                             void *private_data,
-                             char **dst);
+int snd_config_refer_load(snd_config_t **dst, char **name,
+                         snd_config_t *root, snd_config_t *config);
 
 #ifdef __cplusplus
 }
index b760415..8967f13 100644 (file)
@@ -266,7 +266,6 @@ int snd_card_type_string_to_enum(const char *strid, snd_card_type_t *enumid);
 int snd_card_type_enum_to_string(snd_card_type_t enumid, char **strid);
 
 int snd_sctl_build(snd_sctl_t **ctl, snd_ctl_t *handle, snd_config_t *config,
-                  snd_config_string_replace_callback_t *callback,
                   void *private_data, int mode);
 int snd_sctl_free(snd_sctl_t *handle);
 int snd_sctl_install(snd_sctl_t *handle);
index 4170d12..14bbc97 100644 (file)
@@ -190,26 +190,27 @@ pcm.front {
                        default 0
                }
        }
-       @func refer
-       file {
-               @func concat
-               strings [
-                       {
-                               @func datadir
-                       }
-                       "/cards/"
-                       {
-                               @func card_strtype
-                               card $CARD
-                       }
-                       ".conf"
-               ]
-       }
-       name {
-               @func concat
-               strings [
-                       "pcm.front_" $DEV ":CARD=" $CARD
-               ]
+       refer {
+               file {
+                       @func concat
+                       strings [
+                               {
+                                       @func datadir
+                               }
+                               "/cards/"
+                               {
+                                       @func card_strtype
+                                       card $CARD
+                               }
+                               ".conf"
+                       ]
+               }
+               name {
+                       @func concat
+                       strings [
+                               "pcm.front_" $DEV ":CARD=" $CARD
+                       ]
+               }
        }
 }
        
@@ -237,26 +238,27 @@ pcm.rear {
                        default 0
                }
        }
-       @func refer
-       file {
-               @func concat
-               strings [
-                       {
-                               @func datadir
-                       }
-                       "/cards/"
-                       {
-                               @func card_strtype
-                               card $CARD
-                       }
-                       ".conf"
-               ]
-       }
-       name {
-               @func concat
-               strings [
-                       "pcm.rear_" $DEV ":CARD=" $CARD
-               ]
+       refer {
+               file {
+                       @func concat
+                       strings [
+                               {
+                                       @func datadir
+                               }
+                               "/cards/"
+                               {
+                                       @func card_strtype
+                                       card $CARD
+                               }
+                               ".conf"
+                       ]
+               }
+               name {
+                       @func concat
+                       strings [
+                               "pcm.rear_" $DEV ":CARD=" $CARD
+                       ]
+               }
        }
 }
        
@@ -284,26 +286,27 @@ pcm.center_lfe {
                        default 0
                }
        }
-       @func refer
-       file {
-               @func concat
-               strings [
-                       {
-                               @func datadir
-                       }
-                       "/cards/"
-                       {
-                               @func card_strtype
-                               card $CARD
-                       }
-                       ".conf"
-               ]
-       }
-       name {
-               @func concat
-               strings [
-                       "pcm.center_lfe_" $DEV ":CARD=" $CARD
-               ]
+       refer {
+               file {
+                       @func concat
+                       strings [
+                               {
+                                       @func datadir
+                               }
+                               "/cards/"
+                               {
+                                       @func card_strtype
+                                       card $CARD
+                               }
+                               ".conf"
+                       ]
+               }
+               name {
+                       @func concat
+                       strings [
+                               "pcm.center_lfe_" $DEV ":CARD=" $CARD
+                       ]
+               }
        }
 }
        
@@ -331,26 +334,27 @@ pcm.surround40 {
                        default 0
                }
        }
-       @func refer
-       file {
-               @func concat
-               strings [
-                       {
-                               @func datadir
-                       }
-                       "/cards/"
-                       {
-                               @func card_strtype
-                               card $CARD
-                       }
-                       ".conf"
-               ]
-       }
-       name {
-               @func concat
-               strings [
-                       "pcm.surround40_" $DEV ":CARD=" $CARD
-               ]
+       refer {
+               file {
+                       @func concat
+                       strings [
+                               {
+                                       @func datadir
+                               }
+                               "/cards/"
+                               {
+                                       @func card_strtype
+                                       card $CARD
+                               }
+                               ".conf"
+                       ]
+               }
+               name {
+                       @func concat
+                       strings [
+                               "pcm.surround40_" $DEV ":CARD=" $CARD
+                       ]
+               }
        }
 }
        
@@ -378,26 +382,27 @@ pcm.surround51 {
                        default 0
                }
        }
-       @func refer
-       file {
-               @func concat
-               strings [
-                       {
-                               @func datadir
-                       }
-                       "/cards/"
-                       {
-                               @func card_strtype
-                               card $CARD
-                       }
-                       ".conf"
-               ]
-       }
-       name {
-               @func concat
-               strings [
-                       "pcm.surround51_" $DEV ":CARD=" $CARD
-               ]
+       refer {
+               file {
+                       @func concat
+                       strings [
+                               {
+                                       @func datadir
+                               }
+                               "/cards/"
+                               {
+                                       @func card_strtype
+                                       card $CARD
+                               }
+                               ".conf"
+                       ]
+               }
+               name {
+                       @func concat
+                       strings [
+                               "pcm.surround51_" $DEV ":CARD=" $CARD
+                       ]
+               }
        }
 }
        
@@ -445,31 +450,32 @@ pcm.iec958 {
                # fs=48000Hz, clock accuracy=1000ppm
                default 0x02
        }
-       @func refer
-       file {
-               @func concat
-               strings [
-                       {
-                               @func datadir
-                       }
-                       "/cards/"
-                       {
-                               @func card_strtype
-                               card $CARD
-                       }
-                       ".conf"
-               ]
-       }
-       name {
-               @func concat
-               strings [
-                       "pcm.iec958_" $DEV ":"
-                       "CARD=" $CARD ","
-                       "AES0=" $AES0 ","
-                       "AES1=" $AES1 ","
-                       "AES2=" $AES2 ","
-                       "AES3=" $AES3
-               ]
+       refer {
+               file {
+                       @func concat
+                       strings [
+                               {
+                                       @func datadir
+                               }
+                               "/cards/"
+                               {
+                                       @func card_strtype
+                                       card $CARD
+                               }
+                               ".conf"
+                       ]
+               }
+               name {
+                       @func concat
+                       strings [
+                               "pcm.iec958_" $DEV ":"
+                               "CARD=" $CARD ","
+                               "AES0=" $AES0 ","
+                               "AES1=" $AES1 ","
+                               "AES2=" $AES2 ","
+                               "AES3=" $AES3
+                       ]
+               }
        }
 }
 
index a2824c0..df74bd5 100644 (file)
@@ -62,7 +62,7 @@ pcm.emu10k1_rear {
                        }
                        {
                                name "EMU10K1 PCM Send Volume"
-                               index = &(subdevice)
+                               index { @func private_pcm_subdevice }
                                lock true
                                value [ 0 0 0 0 0 0 255 0 0 0 0 255 ]
                        }
@@ -118,13 +118,13 @@ pcm.emu10k1_center_lfe {
                        }
                        {
                                name "EMU10K1 PCM Send Volume"
-                               index = &(subdevice)
+                               index { @func private_pcm_subdevice }
                                lock true
                                value [ 0 0 0 0 255 0 0 0 0 255 0 0 ]
                        }
                        {
                                name "EMU10K1 PCM Send Routing"
-                               index = &(subdevice)
+                               index { @func private_pcm_subdevice }
                                lock true
                                value [ 0 1 2 3 6 7 0 1 6 7 0 1 ]
                        }
index 4782753..68b9bb4 100644 (file)
@@ -58,6 +58,7 @@ pcm.si7018_rear {
                                name "PCM Playback Volume"
                                preserve true
                                lock true
+                               index { @func private_pcm_subdevice }
                                value [ 24 24 ]
                        }
                ]
index 5bf7bb3..20a4b42 100644 (file)
@@ -56,21 +56,21 @@ pcm.trid4dwavenx_rear {
                hook_args [
                        {
                                name "Rear Path"
-                               index &(subdevice)
+                               index { @func private_pcm_subdevice }
                                lock true
                                preserve true
                                value true
                        }
                        {
                                name "PCM Front Playback Volume"
-                               index &(subdevice)
+                               index { @func private_pcm_subdevice }
                                lock true
                                preserve true
                                value [ 0 0 ]
                        }
                        {
                                name "PCM Reverb Playback Volume"
-                               index &(subdevice)
+                               index { @func private_pcm_subdevice }
                                lock true
                                preserve true
                                value [ 127 127 ]
index c58496e..63d44b0 100644 (file)
@@ -140,71 +140,89 @@ int snd_config_get_ctl_iface(snd_config_t *conf)
 }
 
 /**
- * \brief Expand the dynamic contents
- * \param src Source string
- * \param idchr Identification character
- * \param callback Callback function
- * \param private_data Private data for the given callback function
- * \param dst Destination string
+ * \brief Refer the configuration block to another
+ * \param dst new configuration block (if *dst != root -> dst needs to be deleted)
+ * \param name the identifier of new configuration block
+ * \param root the root of all configurations
+ * \param config redirect configuration
  */
-int snd_config_string_replace(const char *src, char idchr,
-                             snd_config_string_replace_callback_t *callback,
-                             void *private_data,
-                             char **dst)
+int snd_config_refer_load(snd_config_t **dst,
+                         char **name,
+                         snd_config_t *root,
+                         snd_config_t *config)
 {
-       int len = 0, len1, err;
-       const char *ptr, *end;
-       char *tmp, *what, *fptr, *rdst = NULL;
+       int err;
+       snd_config_t *result, *c;
+       char *rname;
 
-       assert(src && idchr && dst);
-       while (*src != '\0') {
-               ptr = strchr(src, idchr);
-               end = NULL;
-               if (ptr == src && *(ptr + 1) == '(' && (end = strchr(ptr + 2, ')')) != NULL) {
-                       src = end + 1;
-                       if (callback == NULL)
-                               continue;
-                       len1 = end - (ptr + 2);
-                       if (len1 == 0)          /* empty */
-                               continue;
-                       what = malloc(len1 + 1);
-                       memcpy(what, ptr + 2, len1);
-                       what[len1] = '\0';
-                       fptr = NULL;
-                       err = callback(what, &fptr, private_data);
-                       free(what);
-                       if (err < 0) {
-                               if (*dst != NULL)
-                                       free(*dst);
-                               return err;
-                       }
-                       if (fptr == NULL)       /* empty */
-                               continue;
-                       len1 = strlen(ptr = fptr);
+       assert(dst);
+       assert(name);
+       assert(root);
+       assert(config);
+       if (snd_config_get_type(config) == SND_CONFIG_TYPE_STRING) {
+               const char *str;
+               snd_config_get_string(config, &str);
+               *name = strdup(str);
+               if (*name == NULL)
+                       return -ENOMEM;
+               *dst = root;
+               return 0;
+       }
+       if (snd_config_get_type(config) != SND_CONFIG_TYPE_COMPOUND)
+               return -EINVAL;
+       result = root;
+       rname = NULL;
+       if (snd_config_search(config, "file", &c) >= 0) {
+               snd_config_t *rconfig;
+               const char *filename;
+               snd_input_t *input;
+               err = snd_config_copy(&rconfig, root);
+               if (err < 0)
+                       return err;
+               if (snd_config_get_type(c) == SND_CONFIG_TYPE_STRING) {
+                       snd_config_get_string(c, &filename);
                } else {
-                       if (ptr == NULL) {
-                               len1 = strlen(ptr = src);
-                       } else {
-                               len1 = ptr - src;
-                               ptr = src;
-                       }
-                       src += len1;
-                       fptr = NULL;
+                       err = -EINVAL;
+                     __filename_error:
+                       snd_config_delete(rconfig);
+                       return err;
                }
-               tmp = realloc(rdst, len + len1 + 1);
-               if (tmp == NULL) {
-                       if (*dst != NULL)
-                               free(*dst);
-                       return -ENOMEM;
+               err = snd_input_stdio_open(&input, filename, "r");
+               if (err < 0) {
+                       SNDERR("Unable to open filename %s: %s", filename, snd_strerror(err));
+                       goto __filename_error;
+               }
+               err = snd_config_load(rconfig, input);
+               if (err < 0) {
+                       snd_input_close(input);
+                       goto __filename_error;
                }
-               memcpy(tmp + len, ptr, len1);
-               tmp[len+=len1] = '\0';
-               if (fptr)
-                       free(fptr);
-               rdst = tmp;
+               snd_input_close(input);
+               result = rconfig;
        }
-       *dst = rdst;
+       if (snd_config_search(config, "name", &c) >= 0) {
+               const char *ptr;
+               if ((err = snd_config_get_string(c, &ptr)) < 0)
+                       goto __error;
+               rname = strdup(ptr);
+               if (rname == NULL) {
+                       err = -ENOMEM;
+                       goto __error;
+               }
+       }
+       if (rname == NULL) {
+               err = -EINVAL;
+               goto __error;
+       }
+       *dst = result;
+       *name = rname;
        return 0;
+      __error:
+       if (rname)
+               free(rname);
+       if (result != root)
+               snd_config_delete(result);
+       return err;
 }
 
 /*
@@ -315,7 +333,6 @@ int snd_func_igetenv(snd_config_t **dst, snd_config_t *root, snd_config_t *src,
 }
        
        
-
 int snd_func_concat(snd_config_t **dst, snd_config_t *root, snd_config_t *src, void *private_data)
 {
        snd_config_t *n;
@@ -514,7 +531,6 @@ int snd_func_card_id(snd_config_t **dst, snd_config_t *root, snd_config_t *src,
 int snd_func_pcm_id(snd_config_t **dst, snd_config_t *root, snd_config_t *src, void *private_data)
 {
        snd_config_t *n;
-       char *res = NULL;
        snd_ctl_t *ctl = NULL;
        snd_pcm_info_t *info;
        long card, device, subdevice = 0;
@@ -575,21 +591,39 @@ int snd_func_pcm_id(snd_config_t **dst, snd_config_t *root, snd_config_t *src, v
                SNDERR("snd_ctl_pcm_info error: %s", snd_strerror(err));
                goto __error;
        }
-       res = strdup(snd_pcm_info_get_id(info));
-       if (res == NULL) {
-               err = -ENOMEM;
-               goto __error;
-       }
        err = snd_config_make_string(dst, snd_config_get_id(src));
        if (err >= 0)
-               err = snd_config_set_string(*dst, res);
-       free(res);
+               err = snd_config_set_string(*dst, snd_pcm_info_get_id(info));
       __error:
        if (ctl)
                snd_ctl_close(ctl);
        return err;
 }
 
+int snd_func_private_pcm_subdevice(snd_config_t **dst, snd_config_t *root ATTRIBUTE_UNUSED, snd_config_t *src, void *private_data)
+{
+       char *res = NULL;
+       snd_pcm_info_t *info;
+       int err;
+
+       if (private_data == NULL)
+               return snd_config_copy(dst, src);
+       snd_pcm_info_alloca(&info);
+       err = snd_pcm_info((snd_pcm_t *)private_data, info);
+       if (err < 0) {
+               SNDERR("snd_ctl_pcm_info error: %s", snd_strerror(err));
+               return err;
+       }
+       res = strdup(snd_pcm_info_get_id(info));
+       if (res == NULL)
+               return -ENOMEM;
+       err = snd_config_make_integer(dst, snd_config_get_id(src));
+       if (err >= 0)
+               err = snd_config_set_integer(*dst, snd_pcm_info_get_subdevice(info));
+       free(res);
+       return err;
+}
+
 int snd_func_refer(snd_config_t **dst, snd_config_t *_root, snd_config_t *src, void *private_data)
 {
        snd_config_t *n;
index 73acb13..fac0828 100644 (file)
@@ -371,74 +371,13 @@ static int snd_config_get_ctl_elem_value(snd_config_t *conf,
        return 0;
 }
 
-static int config_replace(snd_config_t *conf,
-                         snd_config_string_replace_callback_t *callback,
-                         void *private_data, char **res)
-{
-       int err;
-       char *replace, *tmp;
-       
-       err = snd_config_get_ascii(conf, &tmp);
-       if (err < 0)
-               return err;
-       err = snd_config_string_replace(tmp, '&', callback, private_data, &replace);
-       free(tmp);
-       if (err < 0)
-               return err;
-       if (replace == NULL) {
-               SNDERR("Invalid value for '%s'", snd_config_get_id(conf));
-               return err;
-       }
-       *res = replace;
-       return 0;
-}
-
-static int config_replace_integer(snd_config_t *conf,
-                                 snd_config_string_replace_callback_t *callback,
-                                 void *private_data, long *res)
-{
-       char *tmp;
-       int err;
-       
-       err = config_replace(conf, callback, private_data, &tmp);
-       if (err < 0)
-               return err;
-       err = safe_strtol(tmp, res);
-       if (err < 0) {
-               SNDERR("Invalid value for '%s'", snd_config_get_id(conf));
-               return err;
-       }
-       return 0;
-}
-
-static int config_replace_bool(snd_config_t *conf,
-                              snd_config_string_replace_callback_t *callback,
-                              void *private_data, int *res)
-{
-       char *tmp;
-       int err;
-       
-       err = config_replace(conf, callback, private_data, &tmp);
-       if (err < 0)
-               return err;
-       err = snd_config_get_bool_ascii(tmp);
-       free(tmp);
-       if (err < 0) {
-               SNDERR("Invalid value for '%s'", snd_config_get_id(conf));
-               return err;
-       }
-       *res = err;
-       return 0;
-}
-
-static int add_elem(snd_sctl_t *h, snd_config_t *conf,
-                   snd_config_string_replace_callback_t *callback,
-                   void *private_data)
+static int add_elem(snd_sctl_t *h, snd_config_t *_conf, void *private_data)
 {
+       snd_config_t *conf;
        snd_config_iterator_t i, next;
        char *tmp;
        int iface = SND_CTL_ELEM_IFACE_MIXER;
-       char *name = NULL;
+       const char *name = NULL;
        long index = 0;
        long device = -1;
        long subdevice = -1;
@@ -447,50 +386,80 @@ static int add_elem(snd_sctl_t *h, snd_config_t *conf,
        snd_config_t *value = NULL, *mask = NULL;
        snd_sctl_elem_t *elem = NULL;
        int err;
+       err = snd_config_expand(_conf, _conf, NULL, private_data, &conf);
+       if (err < 0)
+               return err;
        snd_config_for_each(i, next, conf) {
                snd_config_t *n = snd_config_iterator_entry(i);
                const char *id = snd_config_get_id(n);
                if (strcmp(id, "comment") == 0)
                        continue;
                if (strcmp(id, "iface") == 0 || strcmp(id, "interface") == 0) {
-                       if ((err = config_replace(n, callback, private_data, &tmp)) < 0)
+                       const char *ptr;
+                       if ((err = snd_config_get_string(n, &ptr)) < 0) {
+                               SNDERR("field %s is not a string", id);
                                goto _err;
-                       if ((err = snd_config_get_ctl_iface_ascii(tmp)) < 0) {
+                       }
+                       if ((err = snd_config_get_ctl_iface_ascii(ptr)) < 0) {
                                SNDERR("Invalid value for '%s'", id);
                                free(tmp);
                                goto _err;
                        }
                        iface = err;
-                       free(tmp);
                        continue;
                }
                if (strcmp(id, "name") == 0) {
-                       if ((err = config_replace(n, callback, private_data, &name)) < 0)
+                       if ((err = snd_config_get_string(n, &name)) < 0) {
+                               SNDERR("field %s is not a string", id);
                                goto _err;
+                       }
                        continue;
                }
                if (strcmp(id, "index") == 0) {
-                       if ((err = config_replace_integer(n, callback, private_data, &index)) < 0)
+                       if ((err = snd_config_get_integer(n, &index)) < 0) {
+                               SNDERR("field %s is not an integer", id);
                                goto _err;
+                       }
                        continue;
                }
                if (strcmp(id, "device") == 0) {
-                       if ((err = config_replace_integer(n, callback, private_data, &device)) < 0)
+                       if ((err = snd_config_get_integer(n, &device)) < 0) {
+                               SNDERR("field %s is not an integer", id);
                                goto _err;
+                       }
                        continue;
                }
                if (strcmp(id, "subdevice") == 0) {
-                       if ((err = config_replace_integer(n, callback, private_data, &subdevice)) < 0)
+                       if ((err = snd_config_get_integer(n, &subdevice)) < 0) {
+                               SNDERR("field %s is not an integer", id);
                                goto _err;
+                       }
+                       continue;
                }
                if (strcmp(id, "lock") == 0) {
-                       if ((err = config_replace_bool(n, callback, private_data, &lock)) < 0)
+                       if ((err = snd_config_get_ascii(n, &tmp)) < 0) {
+                               SNDERR("field %s has an invalid type", id);
+                               goto _err;
+                       }
+                       err = snd_config_get_bool_ascii(tmp);
+                       if (err < 0) {
+                               SNDERR("field %s is not a boolean", id);
                                goto _err;
+                       }
+                       lock = err;
                        continue;
                }
                if (strcmp(id, "preserve") == 0) {
-                       if ((err = config_replace_bool(n, callback, private_data, &preserve)) < 0)
+                       if ((err = snd_config_get_ascii(n, &tmp)) < 0) {
+                               SNDERR("field %s has an invalid type", id);
+                               goto _err;
+                       }
+                       err = snd_config_get_bool_ascii(tmp);
+                       if (err < 0) {
+                               SNDERR("field %s is not a boolean", id);
                                goto _err;
+                       }
+                       preserve = err;
                        continue;
                }
                if (strcmp(id, "value") == 0) {
@@ -568,12 +537,9 @@ static int add_elem(snd_sctl_t *h, snd_config_t *conf,
        if (err < 0)
                goto _err;
        list_add_tail(&elem->list, &h->elems);
-       return 0;
 
  _err:
-       if (name)
-               free(name);
-       if (elem) {
+       if (err < 0 && elem) {
                if (elem->id)
                        snd_ctl_elem_id_free(elem->id);
                if (elem->info)
@@ -586,13 +552,12 @@ static int add_elem(snd_sctl_t *h, snd_config_t *conf,
                        snd_ctl_elem_value_free(elem->old);
                free(elem);
        }
+       if (conf)
+               snd_config_delete(conf);
        return err;
 }
 
-int snd_sctl_build(snd_sctl_t **sctl, snd_ctl_t *handle, snd_config_t *conf,
-                  snd_config_string_replace_callback_t *callback,
-                  void *private_data,
-                  int mode)
+int snd_sctl_build(snd_sctl_t **sctl, snd_ctl_t *handle, snd_config_t *conf, void *private_data, int mode)
 {
        snd_sctl_t *h;
        snd_config_iterator_t i, next;
@@ -615,7 +580,7 @@ int snd_sctl_build(snd_sctl_t **sctl, snd_ctl_t *handle, snd_config_t *conf,
        INIT_LIST_HEAD(&h->elems);
        snd_config_for_each(i, next, conf) {
                snd_config_t *n = snd_config_iterator_entry(i);
-               err = add_elem(h, n, callback, private_data);
+               err = add_elem(h, n, private_data);
                if (err < 0) {
                        free_elems(h);
                        return err;
index 1213aeb..93a7101 100644 (file)
@@ -1001,12 +1001,25 @@ static int snd_pcm_open_noupdate(snd_pcm_t **pcmp, snd_config_t *root,
                                 const char *name, snd_pcm_stream_t stream, int mode)
 {
        int err;
-       snd_config_t *pcm_conf;
+       snd_config_t *pcm_conf, *n;
        err = snd_config_search_definition(root, "pcm", name, &pcm_conf);
        if (err < 0) {
                SNDERR("Unknown PCM %s", name);
                return err;
        }
+       if (snd_config_search(pcm_conf, "refer", &n) >= 0) {
+               snd_config_t *refer;
+               char *new_name;
+               err = snd_config_refer_load(&refer, &new_name, root, n);
+               if (err < 0) {
+                       SNDERR("Unable to load refered block in PCM %s: %s", name, snd_strerror(err));
+                       return err;
+               }
+               err = snd_pcm_open_noupdate(pcmp, refer, new_name, stream, mode);
+               if (refer != root)
+                       snd_config_delete(refer);
+               return err;
+       }
        err = snd_pcm_open_conf(pcmp, name, root, pcm_conf, stream, mode);
        snd_config_delete(pcm_conf);
        return err;
index 74bf287..8ab7fcd 100644 (file)
@@ -606,32 +606,6 @@ static int snd_pcm_hook_ctl_elems_close(snd_pcm_hook_t *hook)
        return err;
 }
 
-static int snd_pcm_hook_ctl_elems_replace(const char *what, char **dst, void *private_data)
-{
-       snd_pcm_t *pcm = private_data;
-       snd_pcm_info_t *info;
-       char str[12];
-       long val;
-       int err;
-
-       snd_pcm_info_alloca(&info);
-       err = snd_pcm_info(pcm, info);
-       if (err < 0)
-               return err;
-       if (!strcmp(what, "card")) {
-               val = snd_pcm_info_get_card(info);
-       } else if (!strcmp(what, "device")) {
-               val = snd_pcm_info_get_device(info);
-       } else if (!strcmp(what, "subdevice")) {
-               val = snd_pcm_info_get_subdevice(info);
-       } else
-               return 0;       /* empty string */
-       snprintf(str, sizeof(str), "%li", val);
-       str[sizeof(str)-1] = '\0';
-       *dst = strdup(str);
-       return 0;
-}
-
 int _snd_pcm_hook_ctl_elems_install(snd_pcm_t *pcm, snd_config_t *conf)
 {
        int err;
@@ -658,7 +632,7 @@ int _snd_pcm_hook_ctl_elems_install(snd_pcm_t *pcm, snd_config_t *conf)
                SNDERR("Cannot open CTL %s", ctl_name);
                return err;
        }
-       err = snd_sctl_build(&sctl, ctl, conf, snd_pcm_hook_ctl_elems_replace, pcm, 0);
+       err = snd_sctl_build(&sctl, ctl, conf, pcm, 0);
        if (err < 0)
                return -ENOMEM;
        err = snd_pcm_hook_add(&h_hw_params, pcm, SND_PCM_HOOK_TYPE_HW_PARAMS,