From: Jaroslav Kysela Date: Sat, 16 Jun 2001 22:03:23 +0000 (+0000) Subject: Added context handling for snd_config_expand. X-Git-Tag: v1.0.3~800 X-Git-Url: https://git.alsa-project.org/?a=commitdiff_plain;h=1e0c53a11c47ca044ffdfd16cb3ccb97237769de;p=alsa-lib.git Added context handling for snd_config_expand. PCM slave configuration is now dynamic. --- diff --git a/include/conf.h b/include/conf.h index 415adf4b..27f0d69e 100644 --- a/include/conf.h +++ b/include/conf.h @@ -38,10 +38,11 @@ int snd_config_search_definition(snd_config_t *config, const char *base, const char *key, snd_config_t **result); -int snd_config_expand(snd_config_t *config, const char *args, - void *private_data, snd_config_t **result); -int snd_config_evaluate(snd_config_t *config, void *private_data, - snd_config_t **result); +int snd_config_expand(snd_config_t *config, snd_config_t *root, + const char *args, void *private_data, + snd_config_t **result); +int snd_config_evaluate(snd_config_t *config, snd_config_t *root, + void *private_data, snd_config_t **result); int snd_config_add(snd_config_t *config, snd_config_t *leaf); int snd_config_delete(snd_config_t *config); @@ -98,11 +99,6 @@ 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 *root, - snd_config_t *config, - char **name, - snd_config_t **dst_config, - int *dst_dynamic); #ifdef __cplusplus } diff --git a/src/cards/SI_7018.conf b/src/cards/SI_7018.conf index 5b29343a..6ce069eb 100644 --- a/src/cards/SI_7018.conf +++ b/src/cards/SI_7018.conf @@ -25,13 +25,14 @@ pcm.front_0 { @args.CARD { type integer } - redir { + @func refer + name { @func concat strings [ "pcm.si7018_front:" $(CARD) ",0,-1" ] } } -pcm.si7010_rear { +pcm.si7018_rear { @args [ CARD DEV SUBDEV ] @args.CARD { type integer @@ -54,7 +55,8 @@ pcm.rear_0 { @args.CARD { type integer } - redir { + @func refer + name { @func concat strings [ "pcm.si7018_rear:" $(CARD) ",0,-1" ] } diff --git a/src/conf.c b/src/conf.c index f37207dd..ac4d5af2 100644 --- a/src/conf.c +++ b/src/conf.c @@ -1667,11 +1667,13 @@ typedef enum _snd_config_walk_pass { /* Return 1 if node needs to be attached to father */ /* Return 2 if compound is replaced with standard node */ typedef int (*snd_config_walk_callback_t)(snd_config_t *src, + snd_config_t *root, snd_config_t **dst, snd_config_walk_pass_t pass, void *private_data); static int snd_config_walk(snd_config_t *src, + snd_config_t *root, snd_config_t **dst, snd_config_walk_callback_t callback, void *private_data) @@ -1680,14 +1682,14 @@ static int snd_config_walk(snd_config_t *src, snd_config_iterator_t i, next; switch (snd_config_get_type(src)) { case SND_CONFIG_TYPE_COMPOUND: - err = callback(src, dst, SND_CONFIG_WALK_PASS_PRE, private_data); + err = callback(src, root, dst, SND_CONFIG_WALK_PASS_PRE, private_data); if (err <= 0) return err; snd_config_for_each(i, next, src) { snd_config_t *s = snd_config_iterator_entry(i); snd_config_t *d = NULL; - err = snd_config_walk(s, (dst && *dst) ? &d : NULL, + err = snd_config_walk(s, root, (dst && *dst) ? &d : NULL, callback, private_data); if (err < 0) goto _error; @@ -1697,7 +1699,7 @@ static int snd_config_walk(snd_config_t *src, goto _error; } } - err = callback(src, dst, SND_CONFIG_WALK_PASS_POST, private_data); + err = callback(src, root, dst, SND_CONFIG_WALK_PASS_POST, private_data); if (err <= 0) { _error: if (dst && *dst) @@ -1705,13 +1707,14 @@ static int snd_config_walk(snd_config_t *src, } break; default: - err = callback(src, dst, SND_CONFIG_WALK_PASS_LEAF, private_data); + err = callback(src, root, dst, SND_CONFIG_WALK_PASS_LEAF, private_data); break; } return err; } static int _snd_config_copy(snd_config_t *src, + snd_config_t *root ATTRIBUTE_UNUSED, snd_config_t **dst, snd_config_walk_pass_t pass, void *private_data ATTRIBUTE_UNUSED) @@ -1774,10 +1777,11 @@ static int _snd_config_copy(snd_config_t *src, int snd_config_copy(snd_config_t **dst, snd_config_t *src) { - return snd_config_walk(src, dst, _snd_config_copy, NULL); + return snd_config_walk(src, NULL, dst, _snd_config_copy, NULL); } static int _snd_config_expand(snd_config_t *src, + snd_config_t *root ATTRIBUTE_UNUSED, snd_config_t **dst, snd_config_walk_pass_t pass, void *private_data) @@ -1880,19 +1884,20 @@ void snd_config_substitute(snd_config_t *dst, snd_config_t *src) } static int _snd_config_evaluate(snd_config_t *src, + snd_config_t *root, snd_config_t **dst ATTRIBUTE_UNUSED, snd_config_walk_pass_t pass, void *private_data) { int err; if (pass == SND_CONFIG_WALK_PASS_PRE) { - char buf[256]; + char *buf = NULL; const char *lib = NULL, *func_name = NULL; const char *str; - int (*func)(snd_config_t **dst, snd_config_t *src, - void *private_data); - void *h; - snd_config_t *c, *eval, *func_conf = NULL; + int (*func)(snd_config_t **dst, snd_config_t *root, + snd_config_t *src, void *private_data) = NULL; + void *h = NULL; + snd_config_t *c, *func_conf = NULL; err = snd_config_search(src, "@func", &c); if (err < 0) return 1; @@ -1901,7 +1906,7 @@ static int _snd_config_evaluate(snd_config_t *src, SNDERR("Invalid type for @func"); return err; } - err = snd_config_search_definition(snd_config, "func", str, &func_conf); + err = snd_config_search_definition(root, "func", str, &func_conf); if (err >= 0) { snd_config_iterator_t i, next; if (snd_config_get_type(func_conf) != SND_CONFIG_TYPE_COMPOUND) { @@ -1930,53 +1935,58 @@ static int _snd_config_evaluate(snd_config_t *src, continue; } SNDERR("Unknown field %s", id); - _err: - snd_config_delete(func_conf); - return -EINVAL; } } if (!func_name) { + int len = 9 + strlen(str) + 1; + buf = malloc(len); + snprintf(buf, len, "snd_func_%s", str); + buf[len-1] = '\0'; func_name = buf; - snprintf(buf, sizeof(buf), "snd_func_%s", str); } if (!lib) lib = ALSA_LIB; h = dlopen(lib, RTLD_NOW); - if (h) - func = dlsym(h, func_name); - if (func_conf) - snd_config_delete(func_conf); + func = h ? dlsym(h, func_name) : NULL; + err = 0; if (!h) { SNDERR("Cannot open shared library %s", lib); return -ENOENT; - } - if (!func) { + } else if (!func) { SNDERR("symbol %s is not defined inside %s", func_name, lib); dlclose(h); return -ENXIO; } - err = func(&eval, src, private_data); - dlclose(h); - if (err < 0) { - SNDERR("function %s returned error: %s", func_name, snd_strerror(err)); - return err; - } - if (eval) { - snd_config_substitute(src, eval); - free(eval); + _err: + if (func_conf) + snd_config_delete(func_conf); + if (err >= 0) { + snd_config_t *eval; + err = func(&eval, root, src, private_data); + if (err < 0) + SNDERR("function %s returned error: %s", func_name, snd_strerror(err)); + dlclose(h); + if (err >= 0 && eval) { + snd_config_substitute(src, eval); + free(eval); + } } + if (buf) + free(buf); + if (err < 0) + return err; return 0; } return 1; } -int snd_config_evaluate(snd_config_t *config, void *private_data, - snd_config_t **result) +int snd_config_evaluate(snd_config_t *config, snd_config_t *root, + void *private_data, snd_config_t **result) { /* FIXME: Only in place evaluation is currently implemented */ assert(result == NULL); - return snd_config_walk(config, result, _snd_config_evaluate, private_data); + return snd_config_walk(config, root, result, _snd_config_evaluate, private_data); } static int load_defaults(snd_config_t *subs, snd_config_t *defs) @@ -2351,12 +2361,13 @@ static int parse_args(snd_config_t *subs, const char *str, snd_config_t *defs) /** * \brief Expand a node applying arguments and functions * \param config Config node handle + * \param root Root config node handle * \param args Arguments string (optional) * \param private_data Private data for functions * \param result Pointer to found node * \return 0 on success otherwise a negative error code */ -int snd_config_expand(snd_config_t *config, const char *args, +int snd_config_expand(snd_config_t *config, snd_config_t *root, const char *args, void *private_data, snd_config_t **result) { int err; @@ -2380,18 +2391,18 @@ int snd_config_expand(snd_config_t *config, const char *args, SNDERR("Parse arguments error: %s", snd_strerror(err)); goto _end; } - err = snd_config_evaluate(subs, private_data, NULL); + err = snd_config_evaluate(subs, root, private_data, NULL); if (err < 0) { SNDERR("Args evaluate error: %s", snd_strerror(err)); goto _end; } - err = snd_config_walk(config, &res, _snd_config_expand, subs); + err = snd_config_walk(config, root, &res, _snd_config_expand, subs); if (err < 0) { SNDERR("Expand error (walk): %s", snd_strerror(err)); goto _end; } } - err = snd_config_evaluate(res, private_data, NULL); + err = snd_config_evaluate(res, root, private_data, NULL); if (err < 0) { SNDERR("Evaluate error: %s", snd_strerror(err)); snd_config_delete(res); @@ -2436,7 +2447,7 @@ int snd_config_search_definition(snd_config_t *config, err = snd_config_search_alias(config, base, key, &conf); if (err < 0) return err; - return snd_config_expand(conf, args, NULL, result); + return snd_config_expand(conf, config, args, NULL, result); } diff --git a/src/confmisc.c b/src/confmisc.c index 7c1128d7..b8d6d091 100644 --- a/src/confmisc.c +++ b/src/confmisc.c @@ -211,7 +211,7 @@ int snd_config_string_replace(const char *src, char idchr, * Helper functions for the configuration file */ -int snd_func_getenv(snd_config_t **dst, snd_config_t *src, void *private_data) +int snd_func_getenv(snd_config_t **dst, snd_config_t *root, snd_config_t *src, void *private_data) { snd_config_t *n, *d; snd_config_iterator_t i, next; @@ -223,7 +223,7 @@ int snd_func_getenv(snd_config_t **dst, snd_config_t *src, void *private_data) SNDERR("field envname not found"); goto __error; } - err = snd_config_evaluate(n, private_data, NULL); + err = snd_config_evaluate(n, root, private_data, NULL); if (err < 0) { SNDERR("error evaluating envname"); goto __error; @@ -233,7 +233,7 @@ int snd_func_getenv(snd_config_t **dst, snd_config_t *src, void *private_data) SNDERR("field default not found"); goto __error; } - err = snd_config_evaluate(d, private_data, NULL); + err = snd_config_evaluate(d, root, private_data, NULL); if (err < 0) { SNDERR("error evaluating default"); goto __error; @@ -287,13 +287,13 @@ int snd_func_getenv(snd_config_t **dst, snd_config_t *src, void *private_data) return err; } -int snd_func_igetenv(snd_config_t **dst, snd_config_t *src, void *private_data) +int snd_func_igetenv(snd_config_t **dst, snd_config_t *root, snd_config_t *src, void *private_data) { snd_config_t *d; const char *str; int err; long v; - err = snd_func_getenv(&d, src, private_data); + err = snd_func_getenv(&d, root, src, private_data); if (err < 0) return err; err = snd_config_get_string(d, &str); @@ -314,7 +314,7 @@ int snd_func_igetenv(snd_config_t **dst, snd_config_t *src, void *private_data) -int snd_func_concat(snd_config_t **dst, snd_config_t *src, void *private_data) +int snd_func_concat(snd_config_t **dst, snd_config_t *root, snd_config_t *src, void *private_data) { snd_config_t *n; snd_config_iterator_t i, next; @@ -326,7 +326,7 @@ int snd_func_concat(snd_config_t **dst, snd_config_t *src, void *private_data) SNDERR("field strings not found"); goto __error; } - err = snd_config_evaluate(n, private_data, NULL); + err = snd_config_evaluate(n, root, private_data, NULL); if (err < 0) { SNDERR("error evaluating strings"); goto __error; @@ -376,7 +376,8 @@ int snd_func_concat(snd_config_t **dst, snd_config_t *src, void *private_data) return err; } -int snd_func_datadir(snd_config_t **dst, snd_config_t *src, void *private_data ATTRIBUTE_UNUSED) +int snd_func_datadir(snd_config_t **dst, snd_config_t *root ATTRIBUTE_UNUSED, + snd_config_t *src, void *private_data ATTRIBUTE_UNUSED) { int err = snd_config_make_string(dst, snd_config_get_id(src)); if (err >= 0) @@ -406,7 +407,7 @@ static int string_from_integer(char **dst, long v) } #endif -int snd_func_card_strtype(snd_config_t **dst, snd_config_t *src, void *private_data) +int snd_func_card_strtype(snd_config_t **dst, snd_config_t *root, snd_config_t *src, void *private_data) { snd_config_t *n; char *res = NULL; @@ -420,7 +421,7 @@ int snd_func_card_strtype(snd_config_t **dst, snd_config_t *src, void *private_d SNDERR("field card not found"); goto __error; } - err = snd_config_evaluate(n, private_data, NULL); + err = snd_config_evaluate(n, root, private_data, NULL); if (err < 0) { SNDERR("error evaluating card"); goto __error; @@ -456,7 +457,7 @@ int snd_func_card_strtype(snd_config_t **dst, snd_config_t *src, void *private_d return err; } -int snd_func_card_id(snd_config_t **dst, snd_config_t *src, void *private_data) +int snd_func_card_id(snd_config_t **dst, snd_config_t *root, snd_config_t *src, void *private_data) { snd_config_t *n; char *res = NULL; @@ -470,7 +471,7 @@ int snd_func_card_id(snd_config_t **dst, snd_config_t *src, void *private_data) SNDERR("field card not found"); goto __error; } - err = snd_config_evaluate(n, private_data, NULL); + err = snd_config_evaluate(n, root, private_data, NULL); if (err < 0) { SNDERR("error evaluating card"); goto __error; @@ -506,7 +507,7 @@ int snd_func_card_id(snd_config_t **dst, snd_config_t *src, void *private_data) return err; } -int snd_func_pcm_id(snd_config_t **dst, snd_config_t *src, void *private_data) +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; @@ -520,7 +521,7 @@ int snd_func_pcm_id(snd_config_t **dst, snd_config_t *src, void *private_data) SNDERR("field card not found"); goto __error; } - err = snd_config_evaluate(n, private_data, NULL); + err = snd_config_evaluate(n, root, private_data, NULL); if (err < 0) { SNDERR("error evaluating card"); goto __error; @@ -535,7 +536,7 @@ int snd_func_pcm_id(snd_config_t **dst, snd_config_t *src, void *private_data) SNDERR("field device not found"); goto __error; } - err = snd_config_evaluate(n, private_data, NULL); + err = snd_config_evaluate(n, root, private_data, NULL); if (err < 0) { SNDERR("error evaluating device"); goto __error; @@ -546,7 +547,7 @@ int snd_func_pcm_id(snd_config_t **dst, snd_config_t *src, void *private_data) goto __error; } if (snd_config_search(src, "subdevice", &n) >= 0) { - err = snd_config_evaluate(n, private_data, NULL); + err = snd_config_evaluate(n, root, private_data, NULL); if (err < 0) { SNDERR("error evaluating subdevice"); goto __error; @@ -585,16 +586,16 @@ int snd_func_pcm_id(snd_config_t **dst, snd_config_t *src, void *private_data) return err; } -int snd_func_refer(snd_config_t **dst, snd_config_t *src, void *private_data) +int snd_func_refer(snd_config_t **dst, snd_config_t *_root, snd_config_t *src, void *private_data) { snd_config_t *n; - snd_config_t *root = NULL; + snd_config_t *root; const char *file = NULL, *name = NULL; int err; err = snd_config_search(src, "file", &n); if (err >= 0) { - err = snd_config_evaluate(n, private_data, NULL); + err = snd_config_evaluate(n, _root, private_data, NULL); if (err < 0) { SNDERR("error evaluating file"); goto _end; @@ -607,7 +608,7 @@ int snd_func_refer(snd_config_t **dst, snd_config_t *src, void *private_data) } err = snd_config_search(src, "name", &n); if (err >= 0) { - err = snd_config_evaluate(n, private_data, NULL); + err = snd_config_evaluate(n, _root, private_data, NULL); if (err < 0) { SNDERR("error evaluating name"); goto _end; @@ -624,7 +625,7 @@ int snd_func_refer(snd_config_t **dst, snd_config_t *src, void *private_data) goto _end; } if (!file) - root = snd_config; + root = _root; else { snd_input_t *input; err = snd_config_top(&root); @@ -642,17 +643,18 @@ int snd_func_refer(snd_config_t **dst, snd_config_t *src, void *private_data) } } if (!name) { - if (root == snd_config) - snd_config_copy(dst, root); - else + if (root == _root) + err = snd_config_copy(dst, root); + else { *dst = root; - err = 0; + err = 0; + } } else - err = snd_config_search_definition(root, 0, name, dst); + err = snd_config_search_definition(root, NULL, name, dst); if (err >= 0) err = snd_config_set_id(*dst, snd_config_get_id(src)); _end: - if (root && root != snd_config) + if (root && root != _root) snd_config_delete(root); return err; } diff --git a/src/control/control.c b/src/control/control.c index 75ce33dd..6c5eb7ce 100644 --- a/src/control/control.c +++ b/src/control/control.c @@ -381,7 +381,7 @@ int snd_ctl_wait(snd_ctl_t *ctl, int timeout) } int snd_ctl_open_conf(snd_ctl_t **ctlp, const char *name, - snd_config_t *ctl_conf, int mode) + snd_config_t *ctl_root, snd_config_t *ctl_conf, int mode) { const char *str; char buf[256]; @@ -389,7 +389,7 @@ int snd_ctl_open_conf(snd_ctl_t **ctlp, const char *name, snd_config_t *conf, *type_conf = NULL; snd_config_iterator_t i, next; const char *lib = NULL, *open_name = NULL; - int (*open_func)(snd_ctl_t **, const char *, snd_config_t *, int); + int (*open_func)(snd_ctl_t **, const char *, snd_config_t *, snd_config_t *, int) = NULL; void *h; if (snd_config_get_type(ctl_conf) != SND_CONFIG_TYPE_COMPOUND) { if (name) @@ -408,7 +408,7 @@ int snd_ctl_open_conf(snd_ctl_t **ctlp, const char *name, SNDERR("Invalid type for %s", snd_config_get_id(conf)); return err; } - err = snd_config_search_definition(snd_config, "ctl_type", str, &type_conf); + err = snd_config_search_definition(ctl_root, "ctl_type", str, &type_conf); if (err >= 0) { if (snd_config_get_type(type_conf) != SND_CONFIG_TYPE_COMPOUND) { SNDERR("Invalid type for CTL type %s definition", str); @@ -436,9 +436,8 @@ int snd_ctl_open_conf(snd_ctl_t **ctlp, const char *name, continue; } SNDERR("Unknown field %s", id); - _err: - snd_config_delete(type_conf); - return -EINVAL; + err = -EINVAL; + goto _err; } } if (!open_name) { @@ -448,20 +447,20 @@ int snd_ctl_open_conf(snd_ctl_t **ctlp, const char *name, if (!lib) lib = ALSA_LIB; h = dlopen(lib, RTLD_NOW); - if (h) - open_func = dlsym(h, open_name); - if (type_conf) - snd_config_delete(type_conf); + open_func = h ? dlsym(h, open_name) : NULL; + err = 0; if (!h) { SNDERR("Cannot open shared library %s", lib); - return -ENOENT; - } - if (!open_func) { + err = -ENOENT; + } if (!open_func) { SNDERR("symbol %s is not defined inside %s", open_name, lib); dlclose(h); - return -ENXIO; + err = -ENXIO; } - return open_func(ctlp, name, ctl_conf, mode); + _err: + if (type_conf) + snd_config_delete(type_conf); + return err >= 0 ? open_func(ctlp, name, ctl_root, ctl_conf, mode) : err; } int snd_ctl_open_noupdate(snd_ctl_t **ctlp, snd_config_t *root, const char *name, int mode) @@ -473,7 +472,7 @@ int snd_ctl_open_noupdate(snd_ctl_t **ctlp, snd_config_t *root, const char *name SNDERR("Invalid CTL %s", name); return err; } - err = snd_ctl_open_conf(ctlp, name, ctl_conf, mode); + err = snd_ctl_open_conf(ctlp, name, root, ctl_conf, mode); snd_config_delete(ctl_conf); return err; } diff --git a/src/control/control_hw.c b/src/control/control_hw.c index e99c2544..b287e35f 100644 --- a/src/control/control_hw.c +++ b/src/control/control_hw.c @@ -330,7 +330,7 @@ int snd_ctl_hw_open(snd_ctl_t **handle, const char *name, int card, int mode) return 0; } -int _snd_ctl_hw_open(snd_ctl_t **handlep, char *name, snd_config_t *conf) +int _snd_ctl_hw_open(snd_ctl_t **handlep, char *name, snd_config_t *root ATTRIBUTE_UNUSED, snd_config_t *conf) { snd_config_iterator_t i, next; long card = -1; diff --git a/src/control/control_shm.c b/src/control/control_shm.c index 04875b04..34262da4 100644 --- a/src/control/control_shm.c +++ b/src/control/control_shm.c @@ -524,7 +524,7 @@ int snd_ctl_shm_open(snd_ctl_t **handlep, const char *name, const char *sockname return result; } -int _snd_ctl_shm_open(snd_ctl_t **handlep, char *name, snd_config_t *conf, int mode) +int _snd_ctl_shm_open(snd_ctl_t **handlep, char *name, snd_config_t *root, snd_config_t *conf, int mode) { snd_config_iterator_t i, next; const char *server = NULL; @@ -570,13 +570,15 @@ int _snd_ctl_shm_open(snd_ctl_t **handlep, char *name, snd_config_t *conf, int m SNDERR("server is not defined"); return -EINVAL; } - err = snd_config_search_definition(snd_config, "server", server, &sconfig); + err = snd_config_search_definition(root, "server", server, &sconfig); if (err < 0) { SNDERR("Unknown server %s", server); - return -EINVAL; + err = -EINVAL; + goto _err; } if (snd_config_get_type(sconfig) != SND_CONFIG_TYPE_COMPOUND) { SNDERR("Invalid type for server %s definition", server); + err = -EINVAL; goto _err; } snd_config_for_each(i, next, conf) { @@ -609,9 +611,8 @@ int _snd_ctl_shm_open(snd_ctl_t **handlep, char *name, snd_config_t *conf, int m continue; } SNDERR("Unknown field %s", id); - _err: - snd_config_delete(sconfig); - return -EINVAL; + err = -EINVAL; + goto _err; } if (!host) { @@ -633,7 +634,7 @@ int _snd_ctl_shm_open(snd_ctl_t **handlep, char *name, snd_config_t *conf, int m goto _err; } err = snd_ctl_shm_open(handlep, name, sockname, ctl_name, mode); + _err: snd_config_delete(sconfig); return err; } - diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c index 11affad3..1213aeb8 100644 --- a/src/pcm/pcm.c +++ b/src/pcm/pcm.c @@ -912,7 +912,7 @@ ssize_t snd_pcm_samples_to_bytes(snd_pcm_t *pcm, int samples) } static int snd_pcm_open_conf(snd_pcm_t **pcmp, const char *name, - snd_config_t *root, snd_config_t *pcm_conf, + snd_config_t *pcm_root, snd_config_t *pcm_conf, snd_pcm_stream_t stream, int mode) { const char *str; @@ -923,7 +923,7 @@ static int snd_pcm_open_conf(snd_pcm_t **pcmp, const char *name, const char *lib = NULL, *open_name = NULL; int (*open_func)(snd_pcm_t **, const char *, snd_config_t *, snd_config_t *, - snd_pcm_stream_t, int); + snd_pcm_stream_t, int) = NULL; void *h; if (snd_config_get_type(pcm_conf) != SND_CONFIG_TYPE_COMPOUND) { if (name) @@ -942,7 +942,7 @@ static int snd_pcm_open_conf(snd_pcm_t **pcmp, const char *name, SNDERR("Invalid type for %s", snd_config_get_id(conf)); return err; } - err = snd_config_search_definition(snd_config, "pcm_type", str, &type_conf); + err = snd_config_search_definition(pcm_root, "pcm_type", str, &type_conf); if (err >= 0) { if (snd_config_get_type(type_conf) != SND_CONFIG_TYPE_COMPOUND) { SNDERR("Invalid type for PCM type %s definition", str); @@ -970,9 +970,8 @@ static int snd_pcm_open_conf(snd_pcm_t **pcmp, const char *name, continue; } SNDERR("Unknown field %s", id); - _err: - snd_config_delete(type_conf); - return -EINVAL; + err = -EINVAL; + goto _err; } } if (!open_name) { @@ -982,23 +981,20 @@ static int snd_pcm_open_conf(snd_pcm_t **pcmp, const char *name, if (!lib) lib = ALSA_LIB; h = dlopen(lib, RTLD_NOW); - if (h) - open_func = dlsym(h, open_name); - if (type_conf) - snd_config_delete(type_conf); + open_func = h ? dlsym(h, open_name) : NULL; + err = 0; if (!h) { SNDERR("Cannot open shared library %s", lib); - return -ENOENT; - } - if (!open_func) { + err = -ENOENT; + } else if (!open_func) { SNDERR("symbol %s is not defined inside %s", open_name, lib); dlclose(h); - return -ENXIO; + err = -ENXIO; } - err = open_func(pcmp, name, root, pcm_conf, stream, mode); - if (err < 0) - return err; - return 0; + _err: + if (type_conf) + snd_config_delete(type_conf); + return err >= 0 ? open_func(pcmp, name, pcm_root, pcm_conf, stream, mode) : err; } static int snd_pcm_open_noupdate(snd_pcm_t **pcmp, snd_config_t *root, @@ -4287,7 +4283,8 @@ int snd_pcm_slave_conf(snd_config_t *root, snd_config_t *conf, } if (snd_config_get_type(conf) != SND_CONFIG_TYPE_COMPOUND) { SNDERR("Invalid slave definition"); - return -EINVAL; + err = -EINVAL; + goto _err; } va_start(args, count); for (k = 0; k < count; ++k) { @@ -4303,7 +4300,10 @@ int snd_pcm_slave_conf(snd_config_t *root, snd_config_t *conf, if (strcmp(id, "comment") == 0) continue; if (strcmp(id, "pcm") == 0) { - pcm_conf = n; + if (pcm_conf != NULL) + snd_config_delete(pcm_conf); + if ((err = snd_config_copy(&pcm_conf, n)) < 0) + goto _err; continue; } for (k = 0; k < count; ++k) { @@ -4361,8 +4361,11 @@ int snd_pcm_slave_conf(snd_config_t *root, snd_config_t *conf, } } *_pcm_conf = pcm_conf; - return 0; + pcm_conf = NULL; + err = 0; _err: + if (pcm_conf) + snd_config_delete(pcm_conf); if (to_free) snd_config_delete(conf); return err; diff --git a/src/pcm/pcm_adpcm.c b/src/pcm/pcm_adpcm.c index 14472da9..304fcb97 100644 --- a/src/pcm/pcm_adpcm.c +++ b/src/pcm/pcm_adpcm.c @@ -578,10 +578,12 @@ int _snd_pcm_adpcm_open(snd_pcm_t **pcmp, const char *name, return err; if (snd_pcm_format_linear(sformat) != 1 && sformat != SND_PCM_FORMAT_IMA_ADPCM) { + snd_config_delete(sconf); SNDERR("invalid slave format"); return -EINVAL; } err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode); + snd_config_delete(sconf); if (err < 0) return err; err = snd_pcm_adpcm_open(pcmp, name, sformat, spcm, 1); diff --git a/src/pcm/pcm_alaw.c b/src/pcm/pcm_alaw.c index a64d826e..6ac4381f 100644 --- a/src/pcm/pcm_alaw.c +++ b/src/pcm/pcm_alaw.c @@ -451,10 +451,12 @@ int _snd_pcm_alaw_open(snd_pcm_t **pcmp, const char *name, return err; if (snd_pcm_format_linear(sformat) != 1 && sformat != SND_PCM_FORMAT_A_LAW) { + snd_config_delete(sconf); SNDERR("invalid slave format"); return -EINVAL; } err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode); + snd_config_delete(sconf); if (err < 0) return err; err = snd_pcm_alaw_open(pcmp, name, sformat, spcm, 1); diff --git a/src/pcm/pcm_copy.c b/src/pcm/pcm_copy.c index cdd299d9..35972dff 100644 --- a/src/pcm/pcm_copy.c +++ b/src/pcm/pcm_copy.c @@ -218,6 +218,7 @@ int _snd_pcm_copy_open(snd_pcm_t **pcmp, const char *name, if (err < 0) return err; err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode); + snd_config_delete(sconf); if (err < 0) return err; err = snd_pcm_copy_open(pcmp, name, spcm, 1); diff --git a/src/pcm/pcm_file.c b/src/pcm/pcm_file.c index c34310c0..c0f9d33e 100644 --- a/src/pcm/pcm_file.c +++ b/src/pcm/pcm_file.c @@ -505,10 +505,12 @@ int _snd_pcm_file_open(snd_pcm_t **pcmp, const char *name, if (err < 0) return err; if (!fname && fd < 0) { + snd_config_delete(sconf); SNDERR("file is not defined"); return -EINVAL; } err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode); + snd_config_delete(sconf); if (err < 0) return err; err = snd_pcm_file_open(pcmp, name, fname, fd, format, spcm, 1); diff --git a/src/pcm/pcm_hooks.c b/src/pcm/pcm_hooks.c index 5618cf47..74bf2873 100644 --- a/src/pcm/pcm_hooks.c +++ b/src/pcm/pcm_hooks.c @@ -325,7 +325,7 @@ int snd_pcm_hooks_open(snd_pcm_t **pcmp, const char *name, snd_pcm_t *slave, int return 0; } -int snd_pcm_hook_add_conf(snd_pcm_t *pcm, snd_config_t *conf) +int snd_pcm_hook_add_conf(snd_pcm_t *pcm, snd_config_t *root, snd_config_t *conf) { int err; char buf[256]; @@ -333,7 +333,7 @@ int snd_pcm_hook_add_conf(snd_pcm_t *pcm, snd_config_t *conf) const char *lib = NULL, *install = NULL; snd_config_t *type = NULL, *args = NULL; snd_config_iterator_t i, next; - int (*install_func)(snd_pcm_t *pcm, snd_config_t *args); + int (*install_func)(snd_pcm_t *pcm, snd_config_t *args) = NULL; void *h; if (snd_config_get_type(conf) != SND_CONFIG_TYPE_COMPOUND) { SNDERR("Invalid hook definition"); @@ -364,7 +364,7 @@ int snd_pcm_hook_add_conf(snd_pcm_t *pcm, snd_config_t *conf) SNDERR("Invalid type for %s", snd_config_get_id(type)); return err; } - err = snd_config_search_definition(snd_config, "pcm_hook_type", str, &type); + err = snd_config_search_definition(root, "pcm_hook_type", str, &type); if (err >= 0) { if (snd_config_get_type(type) != SND_CONFIG_TYPE_COMPOUND) { SNDERR("Invalid type for PCM type %s definition", str); @@ -392,9 +392,8 @@ int snd_pcm_hook_add_conf(snd_pcm_t *pcm, snd_config_t *conf) continue; } SNDERR("Unknown field %s", id); - _err: - snd_config_delete(type); - return -EINVAL; + err = -EINVAL; + goto _err; } } if (!install) { @@ -404,27 +403,27 @@ int snd_pcm_hook_add_conf(snd_pcm_t *pcm, snd_config_t *conf) if (!lib) lib = ALSA_LIB; h = dlopen(lib, RTLD_NOW); - if (h) - install_func = dlsym(h, install); - if (type) - snd_config_delete(type); + install_func = h ? dlsym(h, install) : NULL; + err = 0; if (!h) { SNDERR("Cannot open shared library %s", lib); - return -ENOENT; - } - if (!install_func) { + err = -ENOENT; + } else if (!install_func) { SNDERR("symbol %s is not defined inside %s", install, lib); dlclose(h); - return -ENXIO; + err = -ENXIO; } - if (args && snd_config_get_string(args, &str) >= 0) { - err = snd_config_search_definition(snd_config, "hook_args", str, &args); + _err: + if (type) + snd_config_delete(type); + if (err >= 0 && args && snd_config_get_string(args, &str) >= 0) { + err = snd_config_search_definition(root, "hook_args", str, &args); if (err < 0) { SNDERR("unknown hook_args %s", str); - return err; + } else { + err = install_func(pcm, args); + snd_config_delete(args); } - err = install_func(pcm, args); - snd_config_delete(args); } else err = install_func(pcm, args); if (err < 0) @@ -469,6 +468,7 @@ int _snd_pcm_hooks_open(snd_pcm_t **pcmp, const char *name, if (err < 0) return err; err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode); + snd_config_delete(sconf); if (err < 0) return err; err = snd_pcm_hooks_open(pcmp, name, spcm, 1); @@ -482,15 +482,15 @@ int _snd_pcm_hooks_open(snd_pcm_t **pcmp, const char *name, snd_config_t *n = snd_config_iterator_entry(i); const char *str; if (snd_config_get_string(n, &str) >= 0) { - err = snd_config_search_definition(snd_config, "pcm_hook", str, &n); + err = snd_config_search_definition(root, "pcm_hook", str, &n); if (err < 0) { SNDERR("unknown pcm_hook %s", str); - return err; + } else { + err = snd_pcm_hook_add_conf(*pcmp, root, n); + snd_config_delete(n); } - err = snd_pcm_hook_add_conf(*pcmp, n); - snd_config_delete(n); } else - err = snd_pcm_hook_add_conf(*pcmp, n); + err = snd_pcm_hook_add_conf(*pcmp, root, n); if (err < 0) { snd_pcm_close(*pcmp); return err; diff --git a/src/pcm/pcm_linear.c b/src/pcm/pcm_linear.c index 3f9f2aa4..f5187fcd 100644 --- a/src/pcm/pcm_linear.c +++ b/src/pcm/pcm_linear.c @@ -355,10 +355,12 @@ int _snd_pcm_linear_open(snd_pcm_t **pcmp, const char *name, if (err < 0) return err; if (snd_pcm_format_linear(sformat) != 1) { + snd_config_delete(sconf); SNDERR("slave format is not linear"); return -EINVAL; } err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode); + snd_config_delete(sconf); if (err < 0) return err; err = snd_pcm_linear_open(pcmp, name, sformat, spcm, 1); diff --git a/src/pcm/pcm_meter.c b/src/pcm/pcm_meter.c index 803c0ad7..f0e5f9b9 100644 --- a/src/pcm/pcm_meter.c +++ b/src/pcm/pcm_meter.c @@ -653,17 +653,16 @@ int snd_pcm_meter_open(snd_pcm_t **pcmp, const char *name, unsigned int frequenc static int snd_pcm_meter_add_scope_conf(snd_pcm_t *pcm, const char *name, - snd_config_t *conf) + snd_config_t *root, snd_config_t *conf) { char buf[256]; snd_config_iterator_t i, next; const char *lib = NULL, *open_name = NULL, *str = NULL; snd_config_t *c, *type_conf; int (*open_func)(snd_pcm_t *, const char *, - snd_config_t *); + snd_config_t *, snd_config_t *) = NULL; void *h; int err; - int to_free = 0; if (snd_config_get_type(conf) != SND_CONFIG_TYPE_COMPOUND) { SNDERR("Invalid type for scope %s", str); err = -EINVAL; @@ -679,7 +678,7 @@ static int snd_pcm_meter_add_scope_conf(snd_pcm_t *pcm, const char *name, SNDERR("Invalid type for %s", snd_config_get_id(c)); goto _err; } - err = snd_config_search_definition(snd_config, "pcm_scope_type", str, &type_conf); + err = snd_config_search_definition(root, "pcm_scope_type", str, &type_conf); if (err >= 0) { snd_config_for_each(i, next, type_conf) { snd_config_t *n = snd_config_iterator_entry(i); @@ -690,7 +689,7 @@ static int snd_pcm_meter_add_scope_conf(snd_pcm_t *pcm, const char *name, err = snd_config_get_string(n, &lib); if (err < 0) { SNDERR("Invalid type for %s", id); - goto _err1; + goto _err; } continue; } @@ -698,13 +697,13 @@ static int snd_pcm_meter_add_scope_conf(snd_pcm_t *pcm, const char *name, err = snd_config_get_string(n, &open_name); if (err < 0) { SNDERR("Invalid type for %s", id); - goto _err1; + goto _err; } continue; } SNDERR("Unknown field %s", id); err = -EINVAL; - goto _err1; + goto _err; } } if (!open_name) { @@ -714,26 +713,20 @@ static int snd_pcm_meter_add_scope_conf(snd_pcm_t *pcm, const char *name, if (!lib) lib = ALSA_LIB; h = dlopen(lib, RTLD_NOW); + open_func = h ? dlsym(h, open_name) : NULL; + err = 0; if (!h) { SNDERR("Cannot open shared library %s", lib); err = -ENOENT; - goto _err1; - } - open_func = dlsym(h, open_name); - if (type_conf) - snd_config_delete(type_conf); - if (!open_func) { + } else if (!open_func) { SNDERR("symbol %s is not defined inside %s", open_name, lib); dlclose(h); - goto _err; + err = -ENXIO; } - return open_func(pcm, name, conf); - _err1: - snd_config_delete(type_conf); - _err: - if (to_free) - snd_config_delete(conf); - return err; + _err: + if (type_conf) + snd_config_delete(type_conf); + return err >= 0 ? open_func(pcm, name, root, conf) : err; } @@ -783,6 +776,7 @@ int _snd_pcm_meter_open(snd_pcm_t **pcmp, const char *name, if (err < 0) return err; err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode); + snd_config_delete(sconf); if (err < 0) return err; err = snd_pcm_meter_open(pcmp, name, frequency > 0 ? (unsigned int) frequency : FREQUENCY, spcm, 1); @@ -797,15 +791,15 @@ int _snd_pcm_meter_open(snd_pcm_t **pcmp, const char *name, const char *id = snd_config_get_id(n); const char *str; if (snd_config_get_string(n, &str) >= 0) { - err = snd_config_search_definition(snd_config, "pcm_scope", str, &n); + err = snd_config_search_definition(root, "pcm_scope", str, &n); if (err < 0) { SNDERR("unknown pcm_scope %s", str); - return err; + } else { + err = snd_pcm_meter_add_scope_conf(*pcmp, id, root, n); + snd_config_delete(n); } - err = snd_pcm_meter_add_scope_conf(*pcmp, id, n); - snd_config_delete(n); } else - err = snd_pcm_meter_add_scope_conf(*pcmp, id, n); + err = snd_pcm_meter_add_scope_conf(*pcmp, id, root, n); if (err < 0) { snd_pcm_close(*pcmp); return err; diff --git a/src/pcm/pcm_mulaw.c b/src/pcm/pcm_mulaw.c index 79adbd32..2b4884c5 100644 --- a/src/pcm/pcm_mulaw.c +++ b/src/pcm/pcm_mulaw.c @@ -466,10 +466,12 @@ int _snd_pcm_mulaw_open(snd_pcm_t **pcmp, const char *name, return err; if (snd_pcm_format_linear(sformat) != 1 && sformat != SND_PCM_FORMAT_MU_LAW) { + snd_config_delete(sconf); SNDERR("invalid slave format"); return -EINVAL; } err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode); + snd_config_delete(sconf); if (err < 0) return err; err = snd_pcm_mulaw_open(pcmp, name, sformat, spcm, 1); diff --git a/src/pcm/pcm_multi.c b/src/pcm/pcm_multi.c index 4044e9e0..b7fa6261 100644 --- a/src/pcm/pcm_multi.c +++ b/src/pcm/pcm_multi.c @@ -819,6 +819,8 @@ int _snd_pcm_multi_open(snd_pcm_t **pcmp, const char *name, err = snd_pcm_open_slave(&slaves_pcm[idx], root, slaves_conf[idx], stream, mode); if (err < 0) goto _free; + snd_config_delete(slaves_conf[idx]); + slaves_conf[idx] = NULL; } err = snd_pcm_multi_open(pcmp, name, slaves_count, master_slave, slaves_pcm, slaves_channels, @@ -832,8 +834,13 @@ _free: snd_pcm_close(slaves_pcm[idx]); } } - if (slaves_conf) + if (slaves_conf) { + for (idx = 0; idx < slaves_count; ++idx) { + if (slaves_conf[idx]) + snd_config_delete(slaves_conf[idx]); + } free(slaves_conf); + } if (slaves_pcm) free(slaves_pcm); if (slaves_channels) diff --git a/src/pcm/pcm_plug.c b/src/pcm/pcm_plug.c index 1fe4b7bd..9426f04c 100644 --- a/src/pcm/pcm_plug.c +++ b/src/pcm/pcm_plug.c @@ -752,11 +752,14 @@ int _snd_pcm_plug_open(snd_pcm_t **pcmp, const char *name, ttable = malloc(MAX_CHANNELS * MAX_CHANNELS * sizeof(*ttable)); err = snd_pcm_route_load_ttable(tt, ttable, MAX_CHANNELS, MAX_CHANNELS, &cused, &sused, -1); - if (err < 0) + if (err < 0) { + snd_config_delete(sconf); return err; + } } err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode); + snd_config_delete(sconf); if (err < 0) return err; err = snd_pcm_plug_open(pcmp, name, ttable, MAX_CHANNELS, cused, sused, spcm, 1); diff --git a/src/pcm/pcm_rate.c b/src/pcm/pcm_rate.c index 62953fb0..27a34abc 100644 --- a/src/pcm/pcm_rate.c +++ b/src/pcm/pcm_rate.c @@ -567,10 +567,12 @@ int _snd_pcm_rate_open(snd_pcm_t **pcmp, const char *name, return err; if (sformat != SND_PCM_FORMAT_UNKNOWN && snd_pcm_format_linear(sformat) != 1) { + snd_config_delete(sconf); SNDERR("slave format is not linear"); return -EINVAL; } err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode); + snd_config_delete(sconf); if (err < 0) return err; err = snd_pcm_rate_open(pcmp, name, diff --git a/src/pcm/pcm_route.c b/src/pcm/pcm_route.c index 8724bde9..abe1aabd 100644 --- a/src/pcm/pcm_route.c +++ b/src/pcm/pcm_route.c @@ -883,16 +883,20 @@ int _snd_pcm_route_open(snd_pcm_t **pcmp, const char *name, return err; if (sformat != SND_PCM_FORMAT_UNKNOWN && snd_pcm_format_linear(sformat) != 1) { + snd_config_delete(sconf); SNDERR("slave format is not linear"); return -EINVAL; } err = snd_pcm_route_load_ttable(tt, ttable, MAX_CHANNELS, MAX_CHANNELS, &cused, &sused, schannels); - if (err < 0) + if (err < 0) { + snd_config_delete(sconf); return err; + } err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode); + snd_config_delete(sconf); if (err < 0) return err; err = snd_pcm_route_open(pcmp, name, sformat, schannels, diff --git a/src/pcm/pcm_share.c b/src/pcm/pcm_share.c index 9d37a419..9d845762 100644 --- a/src/pcm/pcm_share.c +++ b/src/pcm/pcm_share.c @@ -1426,6 +1426,7 @@ int _snd_pcm_share_open(snd_pcm_t **pcmp, const char *name, /* FIXME: nothing strictly forces to have named definition */ err = snd_config_get_string(sconf, &sname); if (err < 0) { + snd_config_delete(sconf); SNDERR("slave.pcm is not a string"); return err; } @@ -1440,6 +1441,7 @@ int _snd_pcm_share_open(snd_pcm_t **pcmp, const char *name, const char *id = snd_config_get_id(n); err = safe_strtol(id, &cchannel); if (err < 0 || cchannel < 0) { + snd_config_delete(sconf); SNDERR("Invalid client channel in binding: %s", id); return -EINVAL; } @@ -1447,6 +1449,7 @@ int _snd_pcm_share_open(snd_pcm_t **pcmp, const char *name, channels = cchannel + 1; } if (channels == 0) { + snd_config_delete(sconf); SNDERR("No bindings defined"); return -EINVAL; } @@ -1459,8 +1462,10 @@ int _snd_pcm_share_open(snd_pcm_t **pcmp, const char *name, long schannel = -1; cchannel = atoi(id); err = snd_config_get_integer(n, &schannel); - if (err < 0) + if (err < 0) { + snd_config_delete(sconf); goto _free; + } assert(schannel >= 0); assert(schannels <= 0 || schannel < schannels); channels_map[cchannel] = schannel; @@ -1473,6 +1478,7 @@ int _snd_pcm_share_open(snd_pcm_t **pcmp, const char *name, (unsigned int) schannels, speriod_time, sbuffer_time, channels, channels_map, stream, mode); + snd_config_delete(sconf); _free: free(channels_map); return err; diff --git a/src/pcm/pcm_shm.c b/src/pcm/pcm_shm.c index 5233376c..c59a81ef 100644 --- a/src/pcm/pcm_shm.c +++ b/src/pcm/pcm_shm.c @@ -720,7 +720,7 @@ int is_local(struct hostent *hent) } int _snd_pcm_shm_open(snd_pcm_t **pcmp, const char *name, - snd_config_t *root ATTRIBUTE_UNUSED, snd_config_t *conf, + snd_config_t *root, snd_config_t *conf, snd_pcm_stream_t stream, int mode) { snd_config_iterator_t i, next; @@ -765,7 +765,7 @@ int _snd_pcm_shm_open(snd_pcm_t **pcmp, const char *name, SNDERR("server is not defined"); return -EINVAL; } - err = snd_config_search_definition(snd_config, "server", server, &sconfig); + err = snd_config_search_definition(root, "server", server, &sconfig); if (err < 0) { SNDERR("Unknown server %s", server); return -EINVAL; @@ -804,9 +804,9 @@ int _snd_pcm_shm_open(snd_pcm_t **pcmp, const char *name, continue; } SNDERR("Unknown field %s", id); - _err: - snd_config_delete(sconfig); - return -EINVAL; + _err: + err = -EINVAL; + goto __error; } if (!host) { @@ -825,9 +825,10 @@ int _snd_pcm_shm_open(snd_pcm_t **pcmp, const char *name, local = is_local(h); if (!local) { SNDERR("%s is not the local host", host); - return -EINVAL; + goto _err; } err = snd_pcm_shm_open(pcmp, name, sockname, pcm_name, stream, mode); + __error: snd_config_delete(sconfig); return err; } diff --git a/src/rawmidi/rawmidi.c b/src/rawmidi/rawmidi.c index 5e3e14d1..f6169be1 100644 --- a/src/rawmidi/rawmidi.c +++ b/src/rawmidi/rawmidi.c @@ -61,8 +61,8 @@ static int snd_rawmidi_params_default(snd_rawmidi_t *rawmidi, snd_rawmidi_params } int snd_rawmidi_open_conf(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp, - const char *name, snd_config_t *rawmidi_conf, - int mode) + const char *name, snd_config_t *rawmidi_root, + snd_config_t *rawmidi_conf, int mode) { const char *str; char buf[256]; @@ -72,7 +72,7 @@ int snd_rawmidi_open_conf(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp, snd_rawmidi_params_t params; const char *lib = NULL, *open_name = NULL; int (*open_func)(snd_rawmidi_t **, snd_rawmidi_t **, - const char *, snd_config_t *, int); + const char *, snd_config_t *, snd_config_t *, int) = NULL; void *h; if (snd_config_get_type(rawmidi_conf) != SND_CONFIG_TYPE_COMPOUND) { if (name) @@ -91,7 +91,7 @@ int snd_rawmidi_open_conf(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp, SNDERR("Invalid type for %s", snd_config_get_id(conf)); return err; } - err = snd_config_search_definition(snd_config, "rawmidi_type", str, &type_conf); + err = snd_config_search_definition(rawmidi_root, "rawmidi_type", str, &type_conf); if (err >= 0) { if (snd_config_get_type(type_conf) != SND_CONFIG_TYPE_COMPOUND) { SNDERR("Invalid type for RAWMIDI type %s definition", str); @@ -119,9 +119,8 @@ int snd_rawmidi_open_conf(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp, continue; } SNDERR("Unknown field %s", id); - _err: - snd_config_delete(type_conf); - return -EINVAL; + err = -EINVAL; + goto _err; } } if (!open_name) { @@ -131,20 +130,20 @@ int snd_rawmidi_open_conf(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp, if (!lib) lib = ALSA_LIB; h = dlopen(lib, RTLD_NOW); - if (h) - open_func = dlsym(h, open_name); - if (type_conf) - snd_config_delete(type_conf); + open_func = h ? dlsym(h, open_name) : NULL; if (!h) { SNDERR("Cannot open shared library %s", lib); - return -ENOENT; - } - if (!open_func) { + err = -ENOENT; + } else if (!open_func) { SNDERR("symbol %s is not defined inside %s", open_name, lib); dlclose(h); - return -ENXIO; + err = -ENXIO; } - err = open_func(inputp, outputp, name, rawmidi_conf, mode); + _err: + if (type_conf) + snd_config_delete(type_conf); + if (err >= 0) + err = open_func(inputp, outputp, name, rawmidi_root, rawmidi_conf, mode); if (err < 0) return err; if (inputp) { @@ -170,7 +169,7 @@ int snd_rawmidi_open_noupdate(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp, SNDERR("Unknown RawMidi %s", name); return err; } - err = snd_rawmidi_open_conf(inputp, outputp, name, rawmidi_conf, mode); + err = snd_rawmidi_open_conf(inputp, outputp, name, root, rawmidi_conf, mode); snd_config_delete(rawmidi_conf); return err; } diff --git a/src/rawmidi/rawmidi_hw.c b/src/rawmidi/rawmidi_hw.c index f1bf093f..b09c2d76 100644 --- a/src/rawmidi/rawmidi_hw.c +++ b/src/rawmidi/rawmidi_hw.c @@ -303,7 +303,8 @@ int snd_rawmidi_hw_open(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp, } int _snd_rawmidi_hw_open(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp, - char *name, snd_config_t *conf, int mode) + char *name, snd_config_t *root ATTRIBUTE_UNUSED, + snd_config_t *conf, int mode) { snd_config_iterator_t i, next; long card = -1, device = 0, subdevice = -1; diff --git a/src/seq/seq.c b/src/seq/seq.c index 43f7740d..3933dc9c 100644 --- a/src/seq/seq.c +++ b/src/seq/seq.c @@ -61,7 +61,7 @@ snd_seq_type_t snd_seq_type(snd_seq_t *seq) } static int snd_seq_open_conf(snd_seq_t **seqp, const char *name, - snd_config_t *seq_conf, + snd_config_t *seq_root, snd_config_t *seq_conf, int streams, int mode) { const char *str; @@ -70,8 +70,9 @@ static int snd_seq_open_conf(snd_seq_t **seqp, const char *name, snd_config_t *conf, *type_conf = NULL; snd_config_iterator_t i, next; const char *lib = NULL, *open_name = NULL; - int (*open_func)(snd_seq_t **, const char *, snd_config_t *, - int, int); + int (*open_func)(snd_seq_t **, const char *, + snd_config_t *, snd_config_t *, + int, int) = NULL; void *h; if (snd_config_get_type(seq_conf) != SND_CONFIG_TYPE_COMPOUND) { if (name) @@ -90,7 +91,7 @@ static int snd_seq_open_conf(snd_seq_t **seqp, const char *name, SNDERR("Invalid type for %s", snd_config_get_id(conf)); return err; } - err = snd_config_search_definition(snd_config, "seq_type", str, &type_conf); + err = snd_config_search_definition(seq_root, "seq_type", str, &type_conf); if (err >= 0) { if (snd_config_get_type(type_conf) != SND_CONFIG_TYPE_COMPOUND) { SNDERR("Invalid type for SEQ type %s definition", str); @@ -118,9 +119,6 @@ static int snd_seq_open_conf(snd_seq_t **seqp, const char *name, continue; } SNDERR("Unknown field %s", id); - _err: - snd_config_delete(type_conf); - return -EINVAL; } } if (!open_name) { @@ -130,20 +128,20 @@ static int snd_seq_open_conf(snd_seq_t **seqp, const char *name, if (!lib) lib = ALSA_LIB; h = dlopen(lib, RTLD_NOW); - if (h) - open_func = dlsym(h, open_name); - if (type_conf) - snd_config_delete(type_conf); + open_func = h ? dlsym(h, open_name) : NULL; + err = 0; if (!h) { SNDERR("Cannot open shared library %s", lib); - return -ENOENT; - } - if (!open_func) { + err = -ENOENT; + } else if (!open_func) { SNDERR("symbol %s is not defined inside %s", open_name, lib); dlclose(h); - return -ENXIO; + err = -ENXIO; } - return open_func(seqp, name, seq_conf, streams, mode); + _err: + if (type_conf) + snd_config_delete(type_conf); + return err >= 0 ? open_func(seqp, name, seq_root, seq_conf, streams, mode) : err; } static int snd_seq_open_noupdate(snd_seq_t **seqp, snd_config_t *root, @@ -156,7 +154,7 @@ static int snd_seq_open_noupdate(snd_seq_t **seqp, snd_config_t *root, SNDERR("Unknown SEQ %s", name); return err; } - err = snd_seq_open_conf(seqp, name, seq_conf, streams, mode); + err = snd_seq_open_conf(seqp, name, root, seq_conf, streams, mode); snd_config_delete(seq_conf); return err; } diff --git a/src/seq/seq_hw.c b/src/seq/seq_hw.c index bcde6d0a..1fab56ab 100644 --- a/src/seq/seq_hw.c +++ b/src/seq/seq_hw.c @@ -525,7 +525,8 @@ int snd_seq_hw_open(snd_seq_t **handle, const char *name, int streams, int mode) return 0; } -int _snd_seq_hw_open(snd_seq_t **handlep, char *name, snd_config_t *conf, +int _snd_seq_hw_open(snd_seq_t **handlep, char *name, + snd_config_t *root ATTRIBUTE_UNUSED, snd_config_t *conf, int streams, int mode) { snd_config_iterator_t i, next;