📄 state.c
字号:
return -EINVAL; } } err = snd_config_compound_add(control, "value", 1, &value); if (err < 0) { error("snd_config_compound_add: %s", snd_strerror(err)); return err; } switch (type) { case SND_CTL_ELEM_TYPE_BOOLEAN: for (idx = 0; idx < count; idx++) { err = snd_config_string_add(value, num_str(idx), snd_ctl_elem_value_get_boolean(ctl, idx) ? "true" : "false"); if (err < 0) { error("snd_config_string_add: %s", snd_strerror(err)); return err; } } break; case SND_CTL_ELEM_TYPE_INTEGER: for (idx = 0; idx < count; idx++) { err = snd_config_integer_add(value, num_str(idx), snd_ctl_elem_value_get_integer(ctl, idx)); if (err < 0) { error("snd_config_integer_add: %s", snd_strerror(err)); return err; } } break; case SND_CTL_ELEM_TYPE_INTEGER64: for (idx = 0; idx < count; idx++) { err = snd_config_integer64_add(value, num_str(idx), snd_ctl_elem_value_get_integer64(ctl, idx)); if (err < 0) { error("snd_config_integer64_add: %s", snd_strerror(err)); return err; } } break; case SND_CTL_ELEM_TYPE_ENUMERATED: for (idx = 0; idx < count; idx++) { unsigned int v = snd_ctl_elem_value_get_enumerated(ctl, idx); snd_config_t *c; err = snd_config_search(item, num_str(v), &c); if (err == 0) { err = snd_config_get_string(c, &s); assert(err == 0); err = snd_config_string_add(value, num_str(idx), s); } else { err = snd_config_integer_add(value, num_str(idx), v); } if (err < 0) { error("snd_config add: %s", snd_strerror(err)); return err; } } break; default: error("Unknown control type: %d\n", type); return -EINVAL; } return 0;} 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); if (count < 0) { err = 0; goto _close; } 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;}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_bool(snd_config_t *n){ 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; 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 int config_enumerated(snd_config_t *n, snd_ctl_t *handle, snd_ctl_elem_info_t *info){ 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; 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;}static int is_user_control(snd_config_t *conf){ snd_config_iterator_t i, next; snd_config_for_each(i, next, conf) { snd_config_t *n = snd_config_iterator_entry(i); const char *id, *s; if (snd_config_get_id(n, &id) < 0) continue; if (strcmp(id, "access") == 0) { if (snd_config_get_string(n, &s) < 0) return 0; if (strstr(s, "user")) return 1; } } return 0;}static int add_user_control(snd_ctl_t *handle, snd_ctl_elem_info_t *info, snd_config_t *conf){ snd_ctl_elem_id_t *id; snd_config_iterator_t i, next; long imin, imax, istep; snd_ctl_elem_type_t ctype; unsigned int count; int err; unsigned int *tlv; imin = imax = istep = 0; count = 0; ctype = SND_CTL_ELEM_TYPE_NONE; tlv = NULL; snd_config_for_each(i, next, conf) { snd_config_t *n = snd_config_iterator_entry(i); const char *id, *type; if (snd_config_get_id(n, &id) < 0) continue; if (strcmp(id, "type") == 0) { if ((err = snd_config_get_string(n, &type)) < 0) return -EINVAL; if (strcmp(type, "BOOLEAN") == 0) ctype = SND_CTL_ELEM_TYPE_BOOLEAN; else if (strcmp(type, "INTEGER") == 0) ctype = SND_CTL_ELEM_TYPE_INTEGER; else if (strcmp(type, "IEC958") == 0) ctype = SND_CTL_ELEM_TYPE_IEC958; else return -EINVAL; continue; } if (strcmp(id, "range") == 0) { const char *s; if ((err = snd_config_get_string(n, &s)) < 0) return -EINVAL; switch (ctype) { case SND_CTL_ELEM_TYPE_INTEGER: err = sscanf(s, "%li - %li (step %li)", &imin, &imax, &istep); if (err != 3) { istep = 0; err = sscanf(s, "%li - %li", &imin, &imax); if (err != 2) return -EINVAL; } break; default: return -EINVAL; } continue; } if (strcmp(id, "count") == 0) { long v; if ((err = snd_config_get_integer(n, &v)) < 0) return err; count = v; continue; } if (strcmp(id, "tlv") == 0) { const char *s; if ((err = snd_config_get_string(n, &s)) < 0) return -EINVAL; if (tlv) free(tlv); if ((tlv = str_to_tlv(s)) == NULL) return -EINVAL; continue; } } snd_ctl_elem_id_alloca(&id); snd_ctl_elem_info_get_id(info, id); if (count <= 0) count = 1; switch (ctype) { case SND_CTL_ELEM_TYPE_INTEGER: if (imin > imax || istep > imax - imin) return -EINVAL; err = snd_ctl_elem_add_integer(handle, id, count, imin, imax, istep); if (err < 0) goto error; if (tlv) { fprintf(stderr, "XXX write TLV...\n"); snd_ctl_elem_tlv_write(handle, id, tlv); } break; case SND_CTL_ELEM_TYPE_BOOLEAN: err = snd_ctl_elem_add_boolean(handle, id, count); break; case SND_CTL_ELEM_TYPE_IEC958: err = snd_ctl_elem_add_iec958(handle, id); break; default: err = -EINVAL; break; } error: free(tlv); if (err < 0) return err; return snd_ctl_elem_info(handle, info);}static int set_control(snd_ctl_t *handle, snd_config_t *control){ snd_ctl_elem_value_t *ctl; snd_ctl_elem_info_t *info; snd_config_iterator_t i, next; unsigned int numid1; snd_ctl_elem_iface_t iface = -1; int iface1; const char *name1; unsigned int numid; snd_ctl_elem_type_t type; unsigned int count; long device = -1; long device1; long subdevice = -1; long subdevice1; const char *name = NULL; long index1; long index = -1; snd_config_t *value = NULL; snd_config_t *comment = NULL; long val; long long lval; unsigned int idx; int err; char *set; const char *id; snd_ctl_elem_value_alloca(&ctl); snd_ctl_elem_info_alloca(&info); if (snd_config_get_type(control) != SND_CONFIG_TYPE_COMPOUND) { error("control is not a compound"); return -EINVAL; } err = snd_config_get_id(control, &id); if (err < 0) { error("unable to get id"); return -EINVAL; } numid = atoi(id); snd_config_for_each(i, next, control) { snd_config_t *n = snd_config_iterator_entry(i); const char *fld; if (snd_config_get_id(n, &fld) < 0) continue; if (strcmp(fld, "comment") == 0) { if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) { error("control.%d.%s is invalid", numid, fld); return -EINVAL; } comment = n; continue; } if (strcmp(fld, "iface") == 0) { iface = (snd_ctl_elem_iface_t)config_iface(n); if (iface < 0) { error("control.%d.%s is invalid", numid, fld); return -EINVAL; } continue; } if (strcmp(fld, "device") == 0) { if (snd_config_get_type(n) != SND_CONFIG_TYPE_INTEGER) { error("control.%d.%s is invalid", numid, fld); return -EINVAL; } snd_config_get_integer(n, &device); continue;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -