static int config_bool(snd_config_t *n, int doit) { const char *str; long val; long long lval; switch (snd_config_get_type(n)) { case SND_CONFIG_TYPE_INTEGER: snd_config_get_integer(n, &val); if (val < 0 || val > 1) return -1; return val; case SND_CONFIG_TYPE_INTEGER64: snd_config_get_integer64(n, &lval); if (lval < 0 || lval > 1) return -1; return (int) lval; case SND_CONFIG_TYPE_STRING: snd_config_get_string(n, &str); break; case SND_CONFIG_TYPE_COMPOUND: if (!force_restore || !doit) return -1; n = snd_config_iterator_entry(snd_config_iterator_first(n)); return config_bool(n, doit); default: return -1; } if (strcmp(str, "on") == 0 || strcmp(str, "true") == 0) return 1; if (strcmp(str, "off") == 0 || strcmp(str, "false") == 0) return 0; return -1; }
static long config_iface(snd_config_t *n) { long i; long long li; snd_ctl_elem_iface_t idx; const char *str; switch (snd_config_get_type(n)) { case SND_CONFIG_TYPE_INTEGER: snd_config_get_integer(n, &i); return i; case SND_CONFIG_TYPE_INTEGER64: snd_config_get_integer64(n, &li); return li; case SND_CONFIG_TYPE_STRING: snd_config_get_string(n, &str); break; default: return -1; } for (idx = 0; idx <= SND_CTL_ELEM_IFACE_LAST; idx++) { if (strcasecmp(snd_ctl_elem_iface_name(idx), str) == 0) return idx; } return -1; }
static int config_integer64(snd_config_t *n, long long *val, int doit) { int err = snd_config_get_integer64(n, val); if (err < 0 && force_restore && doit) { if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) return err; n = snd_config_iterator_entry(snd_config_iterator_first(n)); return config_integer64(n, val, doit); } return err; }
/* * Parse transition */ static int parse_transition(snd_use_case_mgr_t *uc_mgr, struct list_head *tlist, snd_config_t *cfg) { struct transition_sequence *tseq; const char *id; snd_config_iterator_t i, next; snd_config_t *n; int err; if (snd_config_get_id(cfg, &id) < 0) return -EINVAL; if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) { uc_error("compound type expected for %s", id); return -EINVAL; } snd_config_for_each(i, next, cfg) { n = snd_config_iterator_entry(i); if (snd_config_get_id(n, &id) < 0) return -EINVAL; tseq = calloc(1, sizeof(*tseq)); if (tseq == NULL) return -ENOMEM; INIT_LIST_HEAD(&tseq->transition_list); tseq->name = strdup(id); if (tseq->name == NULL) { free(tseq); return -ENOMEM; } err = parse_sequence(uc_mgr, &tseq->transition_list, n); if (err < 0) { uc_mgr_free_transition_element(tseq); return err; } list_add(&tseq->list, tlist); }
static int config_enumerated(snd_config_t *n, snd_ctl_t *handle, snd_ctl_elem_info_t *info, int doit) { const char *str; long val; long long lval; unsigned int idx, items; switch (snd_config_get_type(n)) { case SND_CONFIG_TYPE_INTEGER: snd_config_get_integer(n, &val); return val; case SND_CONFIG_TYPE_INTEGER64: snd_config_get_integer64(n, &lval); return (int) lval; case SND_CONFIG_TYPE_STRING: snd_config_get_string(n, &str); break; case SND_CONFIG_TYPE_COMPOUND: if (!force_restore || !doit) return -1; n = snd_config_iterator_entry(snd_config_iterator_first(n)); return config_enumerated(n, handle, info, doit); default: return -1; } items = snd_ctl_elem_info_get_items(info); for (idx = 0; idx < items; idx++) { int err; snd_ctl_elem_info_set_item(info, idx); err = snd_ctl_elem_info(handle, info); if (err < 0) { error("snd_ctl_elem_info: %s", snd_strerror(err)); return err; } if (strcmp(str, snd_ctl_elem_info_get_item_name(info)) == 0) return idx; } return -1; }
/*---------------------------------------------------------------------------- ** ALSA_CheckEnvironment ** ** Given an Alsa style configuration node, scan its subitems ** for environment variable names, and use them to find an override, ** if appropriate. ** This is essentially a long and convoluted way of doing: ** getenv("ALSA_CARD") ** getenv("ALSA_CTL_CARD") ** getenv("ALSA_PCM_CARD") ** getenv("ALSA_PCM_DEVICE") ** ** The output value is set with the atoi() of the first environment ** variable found to be set, if any; otherwise, it is left alone */ static void ALSA_CheckEnvironment(snd_config_t *node, int *outvalue) { snd_config_iterator_t iter; for (iter = snd_config_iterator_first(node); iter != snd_config_iterator_end(node); iter = snd_config_iterator_next(iter)) { snd_config_t *leaf = snd_config_iterator_entry(iter); if (snd_config_get_type(leaf) == SND_CONFIG_TYPE_STRING) { const char *value; if (snd_config_get_string(leaf, &value) >= 0) { char *p = getenv(value); if (p) { *outvalue = atoi(p); return; } } } } }
static int snd_rawmidi_open_conf(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp, const char *name, snd_config_t *rawmidi_root, snd_config_t *rawmidi_conf, int mode) { const char *str; char buf[256]; int err; snd_config_t *conf, *type_conf = NULL; snd_config_iterator_t i, next; snd_rawmidi_params_t params; const char *id; const char *lib = NULL, *open_name = NULL; int (*open_func)(snd_rawmidi_t **, snd_rawmidi_t **, const char *, snd_config_t *, snd_config_t *, int) = NULL; #ifndef PIC extern void *snd_rawmidi_open_symbols(void); #endif void *h = NULL; if (snd_config_get_type(rawmidi_conf) != SND_CONFIG_TYPE_COMPOUND) { if (name) SNDERR("Invalid type for RAWMIDI %s definition", name); else SNDERR("Invalid type for RAWMIDI definition"); return -EINVAL; } err = snd_config_search(rawmidi_conf, "type", &conf); if (err < 0) { SNDERR("type is not defined"); return err; } err = snd_config_get_id(conf, &id); if (err < 0) { SNDERR("unable to get id"); return err; } err = snd_config_get_string(conf, &str); if (err < 0) { SNDERR("Invalid type for %s", id); return err; } 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); goto _err; } snd_config_for_each(i, next, type_conf) { snd_config_t *n = snd_config_iterator_entry(i); const char *id; if (snd_config_get_id(n, &id) < 0) continue; 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, &open_name); if (err < 0) { SNDERR("Invalid type for %s", id); goto _err; } continue; } SNDERR("Unknown field %s", id); err = -EINVAL; goto _err; } }
static int get_controls(int cardno, snd_config_t *top) { snd_ctl_t *handle; snd_ctl_card_info_t *info; snd_config_t *state, *card, *control; snd_ctl_elem_list_t *list; unsigned int idx; int err; char name[32]; unsigned int count; const char *id; snd_ctl_card_info_alloca(&info); snd_ctl_elem_list_alloca(&list); sprintf(name, "hw:%d", cardno); err = snd_ctl_open(&handle, name, SND_CTL_READONLY); if (err < 0) { error("snd_ctl_open error: %s", snd_strerror(err)); return err; } err = snd_ctl_card_info(handle, info); if (err < 0) { error("snd_ctl_card_info error: %s", snd_strerror(err)); goto _close; } id = snd_ctl_card_info_get_id(info); err = snd_config_search(top, "state", &state); if (err == 0 && snd_config_get_type(state) != SND_CONFIG_TYPE_COMPOUND) { error("config state node is not a compound"); err = -EINVAL; goto _close; } if (err < 0) { err = snd_config_compound_add(top, "state", 1, &state); if (err < 0) { error("snd_config_compound_add: %s", snd_strerror(err)); goto _close; } } err = snd_config_search(state, id, &card); if (err == 0 && snd_config_get_type(card) != SND_CONFIG_TYPE_COMPOUND) { error("config state.%s node is not a compound", id); err = -EINVAL; goto _close; } if (err < 0) { err = snd_config_compound_add(state, id, 0, &card); if (err < 0) { error("snd_config_compound_add: %s", snd_strerror(err)); goto _close; } } err = snd_config_search(card, "control", &control); if (err == 0) { err = snd_config_delete(control); if (err < 0) { error("snd_config_delete: %s", snd_strerror(err)); goto _close; } } err = snd_ctl_elem_list(handle, list); if (err < 0) { error("Cannot determine controls: %s", snd_strerror(err)); goto _close; } count = snd_ctl_elem_list_get_count(list); err = snd_config_compound_add(card, "control", count > 0, &control); if (err < 0) { error("snd_config_compound_add: %s", snd_strerror(err)); goto _close; } if (count == 0) { err = 0; goto _close; } snd_ctl_elem_list_set_offset(list, 0); if (snd_ctl_elem_list_alloc_space(list, count) < 0) { error("No enough memory..."); goto _close; } if ((err = snd_ctl_elem_list(handle, list)) < 0) { error("Cannot determine controls (2): %s", snd_strerror(err)); goto _free; } for (idx = 0; idx < count; ++idx) { snd_ctl_elem_id_t *id; snd_ctl_elem_id_alloca(&id); snd_ctl_elem_list_get_id(list, idx, id); err = get_control(handle, id, control); if (err < 0) goto _free; } err = 0; _free: snd_ctl_elem_list_free_space(list); _close: snd_ctl_close(handle); return err; }
/** * \brief Returns an environment value. * \param dst The function puts the handle to the result configuration node * (with type string) at the address specified by \p dst. * \param root Handle to the root source node. * \param src Handle to the source node, with definitions for \c vars and * \c default. * \param private_data Handle to the \c private_data node. * \return Zero if successful, otherwise a negative error code. * * Example: \code { @func getenv vars [ MY_CARD CARD C ] default 0 } \endcode */ int snd_func_getenv(snd_config_t **dst, snd_config_t *root, snd_config_t *src, snd_config_t *private_data) { snd_config_t *n, *d; snd_config_iterator_t i, next; const char *res, *id; char *def = NULL; int idx = 0, err, hit; err = snd_config_search(src, "vars", &n); if (err < 0) { SNDERR("field vars not found"); goto __error; } err = snd_config_evaluate(n, root, private_data, NULL); if (err < 0) { SNDERR("error evaluating vars"); goto __error; } err = snd_config_search(src, "default", &d); if (err < 0) { SNDERR("field default not found"); goto __error; } err = snd_config_evaluate(d, root, 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"); goto __error; } do { hit = 0; snd_config_for_each(i, next, n) { snd_config_t *n = snd_config_iterator_entry(i); const char *ptr; long i; if (snd_config_get_id(n, &id) < 0) continue; if (snd_config_get_type(n) != SND_CONFIG_TYPE_STRING) { SNDERR("field %s is not a string", id); err = -EINVAL; goto __error; } err = safe_strtol(id, &i); if (err < 0) { SNDERR("id of field %s is not an integer", id); err = -EINVAL; goto __error; } if (i == idx) { idx++; err = snd_config_get_string(n, &ptr); if (err < 0) { SNDERR("invalid string for id %s", id); err = -EINVAL; goto __error; } res = getenv(ptr); if (res != NULL && *res != '\0') goto __ok; hit = 1; } } } while (hit); res = def; __ok: err = snd_config_get_id(src, &id); if (err >= 0) err = snd_config_imake_string(dst, id, res); __error: free(def); return err; }