From 3a993b4a3e467ee4081121bd81c521af2a1be98b Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 18 Jun 2001 14:14:49 +0000 Subject: [PATCH] Removed snd_config_string_replace function. 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 | 6 +- include/control.h | 1 - src/alsa.conf | 256 +++++++++++++++++++++++--------------------- src/cards/EMU10K1.conf | 6 +- src/cards/SI_7018.conf | 1 + src/cards/TRID4DWAVENX.conf | 6 +- src/confmisc.c | 166 ++++++++++++++++------------ src/control/setup.c | 129 ++++++++-------------- src/pcm/pcm.c | 15 ++- src/pcm/pcm_hooks.c | 28 +---- 10 files changed, 302 insertions(+), 312 deletions(-) diff --git a/include/conf.h b/include/conf.h index 27f0d69e..198e42cb 100644 --- a/include/conf.h +++ b/include/conf.h @@ -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 } diff --git a/include/control.h b/include/control.h index b760415d..8967f13b 100644 --- a/include/control.h +++ b/include/control.h @@ -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); diff --git a/src/alsa.conf b/src/alsa.conf index 4170d12b..14bbc978 100644 --- a/src/alsa.conf +++ b/src/alsa.conf @@ -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 + ] + } } } diff --git a/src/cards/EMU10K1.conf b/src/cards/EMU10K1.conf index a2824c07..df74bd51 100644 --- a/src/cards/EMU10K1.conf +++ b/src/cards/EMU10K1.conf @@ -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 ] } diff --git a/src/cards/SI_7018.conf b/src/cards/SI_7018.conf index 4782753f..68b9bb4c 100644 --- a/src/cards/SI_7018.conf +++ b/src/cards/SI_7018.conf @@ -58,6 +58,7 @@ pcm.si7018_rear { name "PCM Playback Volume" preserve true lock true + index { @func private_pcm_subdevice } value [ 24 24 ] } ] diff --git a/src/cards/TRID4DWAVENX.conf b/src/cards/TRID4DWAVENX.conf index 5bf7bb3c..20a4b42a 100644 --- a/src/cards/TRID4DWAVENX.conf +++ b/src/cards/TRID4DWAVENX.conf @@ -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 ] diff --git a/src/confmisc.c b/src/confmisc.c index c58496e0..63d44b01 100644 --- a/src/confmisc.c +++ b/src/confmisc.c @@ -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; diff --git a/src/control/setup.c b/src/control/setup.c index 73acb135..fac0828e 100644 --- a/src/control/setup.c +++ b/src/control/setup.c @@ -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; diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c index 1213aeb8..93a71018 100644 --- a/src/pcm/pcm.c +++ b/src/pcm/pcm.c @@ -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; diff --git a/src/pcm/pcm_hooks.c b/src/pcm/pcm_hooks.c index 74bf2873..8ab7fcdb 100644 --- a/src/pcm/pcm_hooks.c +++ b/src/pcm/pcm_hooks.c @@ -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, -- 2.11.0