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_add(snd_config_t *config, snd_config_t *leaf);
int snd_config_delete(snd_config_t *config);
@args [ CARD DEV SUBDEV ]
@args.CARD {
type integer
+ default {
+ @func igetenv
+ envname [
+ ALSA_PCM_CARD
+ ALSA_CARD
+ ]
+ default 0
+ }
}
@args.DEV {
type integer
+ default {
+ @func igetenv
+ envname [
+ ALSA_PCM_DEVICE
+ ]
+ default 0
+ }
}
@args.SUBDEV {
type integer
@args [ CARD DEV SUBDEV ]
@args.CARD {
type integer
+ default {
+ @func igetenv
+ envname [
+ ALSA_PCM_CARD
+ ALSA_CARD
+ ]
+ default 0
+ }
}
@args.DEV {
type integer
+ default {
+ @func igetenv
+ envname [
+ ALSA_PCM_DEVICE
+ ]
+ default 0
+ }
}
@args.SUBDEV {
type integer
@args[ CARD ]
@args.CARD {
type integer
+ default {
+ @func igetenv
+ envname [
+ ALSA_CTL_CARD
+ ALSA_CARD
+ ]
+ default 0
+ }
}
type hw
card $(CARD)
ctl.default {
type hw
card {
- @func getenv
+ @func igetenv
envname [
+ ALSA_CTL_CARD
ALSA_CARD
]
default 0
@args [ CARD DEV SUBDEV ]
@args.CARD {
type integer
+ default {
+ @func igetenv
+ envname [
+ ALSA_RAWMIDI_CARD
+ ALSA_CARD
+ ]
+ default 0
+ }
}
@args.DEV {
type integer
+ default {
+ @func igetenv
+ envname [
+ ALSA_RAWMIDI_DEVICE
+ ]
+ default 0
+ }
}
@args.SUBDEV {
type integer
return 1;
}
-static int evaluate_node(snd_config_t *father, snd_config_t *src,
- void *private_data, snd_config_t **dst)
+void snd_config_substitute(snd_config_t *dst, snd_config_t *src)
{
- snd_config_iterator_t i, next;
- const char *lib = NULL, *func = NULL;
- int err;
- char buf[64];
- char *evaluate_name = NULL;
- int (*evaluate_func)(snd_config_t **dst, snd_config_t *src, void *private_data);
- void *h;
-
- assert(father && src && dst);
+ free(dst->id);
+ dst->id = src->id;
+ dst->type = src->type;
+ dst->u = src->u;
+}
- snd_config_for_each(i, next, src) {
- snd_config_t *n = snd_config_iterator_entry(i);
- const char *id;
- if (snd_config_get_type(n) == SND_CONFIG_TYPE_COMPOUND) {
- snd_config_t *n1;
- err = evaluate_node(src, n, private_data, &n1);
- if (err < 0) {
- SNDERR("Error in node %s", snd_config_get_id(n));
- goto __error;
+static int _snd_config_evaluate(snd_config_t *src,
+ 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];
+ 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;
+ err = snd_config_search(src, "@func", &c);
+ if (err < 0)
+ return 1;
+ err = snd_config_get_string(c, &str);
+ if (err < 0) {
+ SNDERR("Invalid type for @func");
+ return err;
+ }
+ err = snd_config_search_definition(snd_config, "func", str, &func_conf);
+ if (err >= 0) {
+ snd_config_iterator_t i, next;
+ if (snd_config_get_type(func_conf) != SND_CONFIG_TYPE_COMPOUND) {
+ SNDERR("Invalid type for func %s definition", str);
+ goto _err;
}
- if (n1) { /* replace node */
- snd_config_delete(n);
- err = snd_config_add(src, n1);
- if (err < 0)
- goto __error;
+ snd_config_for_each(i, next, func_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, "lib") == 0) {
+ err = snd_config_get_string(n, &lib);
+ if (err < 0) {
+ SNDERR("Invalid type for %s", id);
+ goto _err;
+ }
+ continue;
+ }
+ if (strcmp(id, "open") == 0) {
+ err = snd_config_get_string(n, &func_name);
+ if (err < 0) {
+ SNDERR("Invalid type for %s", id);
+ goto _err;
+ }
+ continue;
+ }
+ SNDERR("Unknown field %s", id);
+ _err:
+ snd_config_delete(func_conf);
+ return -EINVAL;
}
}
- id = snd_config_get_id(n);
- if (*id++ != '@') /* quick look */
- continue;
- if (!strcmp(id, "lib")) {
- if ((err = snd_config_get_string(n, &lib)) < 0) {
- _invalid_field:
- SNDERR("Unknown type of field %s", id);
- return err;
- }
- lib = strdup(lib);
- if (lib == NULL)
- goto __error;
- snd_config_delete(n);
- } else if (!strcmp(id, "func")) {
- if ((err = snd_config_get_string(n, &func)) < 0)
- goto _invalid_field;
- func = strdup(func);
- if (func == NULL)
- goto __error;
- snd_config_delete(n);
+ if (!func_name) {
+ 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);
+ if (!h) {
+ SNDERR("Cannot open shared library %s", lib);
+ return -ENOENT;
}
- }
-
- if (func == NULL) {
- *dst = NULL;
- return 0;
- }
-
- if (evaluate_name == NULL) {
- snprintf(buf, sizeof(buf), "snd_func_%s", func);
- buf[sizeof(buf) - 1] = '\0';
- evaluate_name = buf;
- }
-
- h = dlopen(lib, RTLD_NOW);
- if (!h) {
- SNDERR("Cannot open shared library %s", lib);
- err = -ENOENT;
- goto __error;
- }
- evaluate_func = dlsym(h, evaluate_name);
- if (!evaluate_func) {
+ 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);
- SNDERR("symbol %s is not defined inside %s", evaluate_name, lib ? lib : ALSA_LIB);
- err = -ENXIO;
- goto __error;
- }
- err = evaluate_func(dst, src, private_data);
- dlclose(h);
- if (err < 0) {
- SNDERR("function %s returned error: %s", evaluate_name, snd_strerror(err));
- goto __error;
+ 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);
+ }
+ return 0;
}
- err = 0;
-
- __error:
- if (func)
- free((void *)func);
- if (lib)
- free((void *)lib);
- return err;
+ return 1;
}
-int snd_config_evaluate(snd_config_t *conf, void *private_data)
-{
- snd_config_iterator_t i, next;
- assert(conf);
- if (snd_config_get_type(conf) != SND_CONFIG_TYPE_COMPOUND)
- return 0;
- snd_config_for_each(i, next, conf) {
- snd_config_t *n = snd_config_iterator_entry(i);
- if (snd_config_get_type(n) == SND_CONFIG_TYPE_COMPOUND) {
- snd_config_t *n1;
- int err = evaluate_node(conf, n, private_data, &n1);
- if (err < 0) {
- SNDERR("Error in node %s", snd_config_get_id(n));
- return err;
- }
- if (n1) { /* replace node */
- snd_config_delete(n);
- err = snd_config_add(conf, n1);
- if (err < 0)
- return err;
- }
- }
- }
- return 0;
+int snd_config_evaluate(snd_config_t *config, 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);
}
static int load_defaults(snd_config_t *subs, snd_config_t *defs)
SNDERR("Parse arguments error: %s", snd_strerror(err));
goto _end;
}
+ err = snd_config_evaluate(subs, 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);
if (err < 0) {
SNDERR("Expand error (walk): %s", snd_strerror(err));
goto _end;
}
}
- err = snd_config_evaluate(res, private_data);
+ err = snd_config_evaluate(res, private_data, NULL);
if (err < 0) {
SNDERR("Evaluate error: %s", snd_strerror(err));
snd_config_delete(res);
memcpy(key, name, args - name - 1);
key[args - name - 1] = '\0';
} else {
- key = (char *) base;
+ key = (char *) name;
}
err = snd_config_search_alias(config, base, key, &conf);
if (err < 0)
int snd_func_getenv(snd_config_t **dst, snd_config_t *src, void *private_data)
{
- snd_config_t *n, *d, *e;
+ snd_config_t *n, *d;
snd_config_iterator_t i, next;
char *res, *def = NULL;
int idx = 0, err;
- err = snd_config_expand(src, NULL, private_data, &e);
- if (err < 0)
- return err;
- err = snd_config_search(e, "envname", &n);
+ err = snd_config_search(src, "envname", &n);
if (err < 0) {
SNDERR("field envname not found");
goto __error;
}
- err = snd_config_search(e, "default", &d);
+ err = snd_config_evaluate(n, private_data, NULL);
+ if (err < 0) {
+ SNDERR("error evaluating envname");
+ goto __error;
+ }
+ err = snd_config_search(src, "default", &d);
if (err < 0) {
SNDERR("field default not found");
goto __error;
}
+ err = snd_config_evaluate(d, private_data, NULL);
+ if (err < 0) {
+ SNDERR("error evaluating default");
+ goto __error;
+ }
err = snd_config_get_ascii(d, &def);
if (err < 0) {
SNDERR("error getting field default");
__error:
if (def)
free(def);
- snd_config_delete(e);
return err;
}
err = 0;
_end:
- snd_config_delete(d);
return err;
}
int snd_func_concat(snd_config_t **dst, snd_config_t *src, void *private_data)
{
- snd_config_t *n, *e;
+ snd_config_t *n;
snd_config_iterator_t i, next;
char *res = NULL, *tmp;
int idx = 0, len = 0, len1, err;
- err = snd_config_expand(src, NULL, private_data, &e);
- if (err < 0)
- return err;
- err = snd_config_search(e, "strings", &n);
+ err = snd_config_search(src, "strings", &n);
if (err < 0) {
SNDERR("field strings not found");
goto __error;
}
+ err = snd_config_evaluate(n, private_data, NULL);
+ if (err < 0) {
+ SNDERR("error evaluating strings");
+ goto __error;
+ }
__retry:
snd_config_for_each(i, next, n) {
snd_config_t *n = snd_config_iterator_entry(i);
snd_config_set_string(*dst, res);
free(res);
__error:
- snd_config_delete(e);
return err;
}
int snd_func_card_strtype(snd_config_t **dst, snd_config_t *src, void *private_data)
{
- snd_config_t *n, *e;
+ snd_config_t *n;
char *res = NULL;
snd_ctl_t *ctl = NULL;
snd_ctl_card_info_t *info;
long v;
int err;
- err = snd_config_expand(src, NULL, private_data, &e);
- if (err < 0)
- return err;
- err = snd_config_search(e, "card", &n);
+ err = snd_config_search(src, "card", &n);
if (err < 0) {
SNDERR("field card not found");
goto __error;
}
+ err = snd_config_evaluate(n, private_data, NULL);
+ if (err < 0) {
+ SNDERR("error evaluating card");
+ goto __error;
+ }
err = snd_config_get_integer(n, &v);
if (err < 0) {
SNDERR("field card is not an integer");
__error:
if (ctl)
snd_ctl_close(ctl);
- snd_config_delete(e);
return err;
}
int snd_func_card_id(snd_config_t **dst, snd_config_t *src, void *private_data)
{
- snd_config_t *n, *e;
+ snd_config_t *n;
char *res = NULL;
snd_ctl_t *ctl = NULL;
snd_ctl_card_info_t *info;
long v;
int err;
- err = snd_config_expand(src, NULL, private_data, &e);
- if (err < 0)
- return err;
- err = snd_config_search(e, "card", &n);
+ err = snd_config_search(src, "card", &n);
if (err < 0) {
SNDERR("field card not found");
goto __error;
}
+ err = snd_config_evaluate(n, private_data, NULL);
+ if (err < 0) {
+ SNDERR("error evaluating card");
+ goto __error;
+ }
err = snd_config_get_integer(n, &v);
if (err < 0) {
SNDERR("field card is not an integer");
__error:
if (ctl)
snd_ctl_close(ctl);
- snd_config_delete(e);
return err;
}
int snd_func_pcm_id(snd_config_t **dst, snd_config_t *src, void *private_data)
{
- snd_config_t *n, *e;
+ snd_config_t *n;
char *res = NULL;
snd_ctl_t *ctl = NULL;
snd_pcm_info_t *info;
long card, device, subdevice = 0;
int err;
- err = snd_config_expand(src, NULL, private_data, &e);
- if (err < 0)
- return err;
- err = snd_config_search(e, "card", &n);
+ err = snd_config_search(src, "card", &n);
if (err < 0) {
SNDERR("field card not found");
goto __error;
}
+ err = snd_config_evaluate(n, private_data, NULL);
+ if (err < 0) {
+ SNDERR("error evaluating card");
+ goto __error;
+ }
err = snd_config_get_integer(n, &card);
if (err < 0) {
SNDERR("field card is not an integer");
goto __error;
}
- err = snd_config_search(e, "device", &n);
+ err = snd_config_search(src, "device", &n);
if (err < 0) {
SNDERR("field device not found");
goto __error;
}
+ err = snd_config_evaluate(n, private_data, NULL);
+ if (err < 0) {
+ SNDERR("error evaluating device");
+ goto __error;
+ }
err = snd_config_get_integer(n, &device);
if (err < 0) {
SNDERR("field device is not an integer");
goto __error;
}
- if (snd_config_search(e, "subdevice", &n) >= 0) {
+ if (snd_config_search(src, "subdevice", &n) >= 0) {
+ err = snd_config_evaluate(n, private_data, NULL);
+ if (err < 0) {
+ SNDERR("error evaluating subdevice");
+ goto __error;
+ }
err = snd_config_get_integer(n, &subdevice);
if (err < 0) {
SNDERR("field subdevice is not an integer");
__error:
if (ctl)
snd_ctl_close(ctl);
- snd_config_delete(e);
return err;
}
int snd_func_refer(snd_config_t **dst, snd_config_t *src, void *private_data)
{
- snd_config_t *n, *e;
+ snd_config_t *n;
snd_config_t *root = NULL;
const char *file = NULL, *name = NULL;
int err;
- err = snd_config_expand(src, NULL, private_data, &e);
- if (err < 0)
- return err;
- err = snd_config_search(e, "file", &n);
+ err = snd_config_search(src, "file", &n);
if (err >= 0) {
+ err = snd_config_evaluate(n, private_data, NULL);
+ if (err < 0) {
+ SNDERR("error evaluating file");
+ goto _end;
+ }
err = snd_config_get_string(n, &file);
if (err < 0) {
SNDERR("file is not a string");
goto _end;
}
}
- err = snd_config_search(e, "name", &n);
+ err = snd_config_search(src, "name", &n);
if (err >= 0) {
+ if (err < 0) {
+ SNDERR("error evaluating name");
+ goto _end;
+ }
err = snd_config_get_string(n, &name);
if (err < 0) {
SNDERR("name is not a string");