📄 state.c
字号:
int err = restore_config_value(handle, info, type, value, ctl, idx, doit); long val; if (err != 0) return err; switch (type) { case SND_CTL_ELEM_TYPE_BYTES: case SND_CTL_ELEM_TYPE_IEC958: err = snd_config_get_integer(value, &val); if (err < 0 || val < 0 || val > 255) { cerror(doit, "bad control.%d.value.%d content", numid, idx); return force_restore && doit ? 0 : -EINVAL; } snd_ctl_elem_value_set_byte(ctl, idx, val); return 1; break; default: break; } return 0;}static int set_control(snd_ctl_t *handle, snd_config_t *control, int *maxnumid, int doit){ 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; 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) { cerror(doit, "control is not a compound"); return -EINVAL; } err = snd_config_get_id(control, &id); if (err < 0) { cerror(doit, "unable to get id"); return -EINVAL; } numid = atoi(id); if ((int)numid > *maxnumid) *maxnumid = numid; 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) { cerror(doit, "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); continue; } if (strcmp(fld, "device") == 0) { if (snd_config_get_type(n) != SND_CONFIG_TYPE_INTEGER) { cerror(doit, "control.%d.%s is invalid", numid, fld); return -EINVAL; } snd_config_get_integer(n, &device); continue; } if (strcmp(fld, "subdevice") == 0) { if (snd_config_get_type(n) != SND_CONFIG_TYPE_INTEGER) { cerror(doit, "control.%d.%s is invalid", numid, fld); return -EINVAL; } snd_config_get_integer(n, &subdevice); continue; } if (strcmp(fld, "name") == 0) { if (snd_config_get_type(n) != SND_CONFIG_TYPE_STRING) { cerror(doit, "control.%d.%s is invalid", numid, fld); return -EINVAL; } snd_config_get_string(n, &name); continue; } if (strcmp(fld, "index") == 0) { if (snd_config_get_type(n) != SND_CONFIG_TYPE_INTEGER) { cerror(doit, "control.%d.%s is invalid", numid, fld); return -EINVAL; } snd_config_get_integer(n, &index); continue; } if (strcmp(fld, "value") == 0) { value = n; continue; } cerror(doit, "unknown control.%d.%s field", numid, fld); } if (!value) { cerror(doit, "missing control.%d.value", numid); return -EINVAL; } if (device < 0) device = 0; if (subdevice < 0) subdevice = 0; if (index < 0) index = 0; err = -EINVAL; if (!force_restore) { snd_ctl_elem_info_set_numid(info, numid); err = snd_ctl_elem_info(handle, info); } if (err < 0 && name) { snd_ctl_elem_info_set_numid(info, 0); snd_ctl_elem_info_set_interface(info, iface); snd_ctl_elem_info_set_device(info, device); snd_ctl_elem_info_set_subdevice(info, subdevice); snd_ctl_elem_info_set_name(info, name); snd_ctl_elem_info_set_index(info, index); err = snd_ctl_elem_info(handle, info); if (err < 0 && comment && is_user_control(comment)) { err = add_user_control(handle, info, comment); if (err < 0) { cerror(doit, "failed to add user control #%d (%s)", numid, snd_strerror(err)); return err; } } } if (err < 0) { cerror(doit, "failed to obtain info for control #%d (%s)", numid, snd_strerror(err)); return -ENOENT; } numid1 = snd_ctl_elem_info_get_numid(info); iface1 = snd_ctl_elem_info_get_interface(info); device1 = snd_ctl_elem_info_get_device(info); subdevice1 = snd_ctl_elem_info_get_subdevice(info); name1 = snd_ctl_elem_info_get_name(info); index1 = snd_ctl_elem_info_get_index(info); count = snd_ctl_elem_info_get_count(info); type = snd_ctl_elem_info_get_type(info); if (err |= numid != numid1 && !force_restore) cerror(doit, "warning: numid mismatch (%d/%d) for control #%d", numid, numid1, numid); if (err |= iface != iface1) cerror(doit, "warning: iface mismatch (%d/%d) for control #%d", iface, iface1, numid); if (err |= device != device1) cerror(doit, "warning: device mismatch (%ld/%ld) for control #%d", device, device1, numid); if (err |= subdevice != subdevice1) cerror(doit, "warning: subdevice mismatch (%ld/%ld) for control #%d", subdevice, subdevice1, numid); if (err |= strcmp(name, name1)) cerror(doit, "warning: name mismatch (%s/%s) for control #%d", name, name1, numid); if (err |= index != index1) cerror(doit, "warning: index mismatch (%ld/%ld) for control #%d", index, index1, numid); if (err < 0) { cerror(doit, "failed to obtain info for control #%d (%s)", numid, snd_strerror(err)); return -ENOENT; } if (comment) { if (check_comment_type(comment, type) < 0) cerror(doit, "incompatible field type for control #%d", numid); if (type == SND_CTL_ELEM_TYPE_INTEGER) { if (check_comment_range(handle, comment, info, value, doit) < 0) { cerror(doit, "value range mismatch for control #%d", numid); return -EINVAL; } } } if (snd_ctl_elem_info_is_inactive(info) || !snd_ctl_elem_info_is_writable(info)) return 0; snd_ctl_elem_value_set_numid(ctl, numid1); if (count == 1) { err = restore_config_value(handle, info, type, value, ctl, 0, doit); if (err < 0) return err; if (err > 0) goto _ok; } switch (type) { case SND_CTL_ELEM_TYPE_BYTES: case SND_CTL_ELEM_TYPE_IEC958: { const char *buf; err = snd_config_get_string(value, &buf); if (err >= 0) { int c1 = 0; int len = strlen(buf); unsigned int idx = 0; int size = type == SND_CTL_ELEM_TYPE_BYTES ? count : sizeof(snd_aes_iec958_t); if (size * 2 != len) { cerror(doit, "bad control.%d.value contents\n", numid); return -EINVAL; } while (*buf) { int c = *buf++; if ((c = hextodigit(c)) < 0) { cerror(doit, "bad control.%d.value contents\n", numid); return -EINVAL; } if (idx % 2 == 1) snd_ctl_elem_value_set_byte(ctl, idx / 2, c1 << 4 | c); else c1 = c; idx++; } goto _ok; } } default: break; } if (snd_config_get_type(value) != SND_CONFIG_TYPE_COMPOUND) { if (!force_restore || !doit) { cerror(doit, "bad control.%d.value type", numid); return -EINVAL; } for (idx = 0; idx < count; ++idx) { err = restore_config_value2(handle, info, type, value, ctl, idx, numid, doit); if (err < 0) return err; } goto _ok; } set = (char*) alloca(count); memset(set, 0, count); snd_config_for_each(i, next, value) { snd_config_t *n = snd_config_iterator_entry(i); const char *id; if (snd_config_get_id(n, &id) < 0) continue; idx = atoi(id); if (idx >= count || set[idx]) { cerror(doit, "bad control.%d.value index", numid); if (!force_restore || !doit) return -EINVAL; continue; } err = restore_config_value2(handle, info, type, n, ctl, idx, numid, doit); if (err < 0) return err; if (err > 0) set[idx] = 1; } for (idx = 0; idx < count; ++idx) { if (!set[idx]) { cerror(doit, "control.%d.value.%d is not specified", numid, idx); if (!force_restore || !doit) return -EINVAL; } } _ok: err = doit ? snd_ctl_elem_write(handle, ctl) : 0; if (err < 0) { error("Cannot write control '%d:%ld:%ld:%s:%ld' : %s", (int)iface, device, subdevice, name, index, snd_strerror(err)); return err; } return 0;}static int set_controls(int card, snd_config_t *top, int doit){ snd_ctl_t *handle; snd_ctl_card_info_t *info; snd_config_t *control; snd_config_iterator_t i, next; int err, maxnumid = -1; char name[32], tmpid[16]; const char *id; snd_ctl_card_info_alloca(&info); sprintf(name, "hw:%d", card); err = snd_ctl_open(&handle, name, 0); 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_searchv(top, &control, "state", id, "control", 0); if (err < 0) { if (force_restore) { sprintf(tmpid, "card%d", card); err = snd_config_searchv(top, &control, "state", tmpid, "control", 0); if (! err) id = tmpid; } if (err < 0) { fprintf(stderr, "No state is present for card %s\n", id); goto _close; } id = tmpid; } if (snd_config_get_type(control) != SND_CONFIG_TYPE_COMPOUND) { cerror(doit, "state.%s.control is not a compound\n", id); return -EINVAL; } snd_config_for_each(i, next, control) { snd_config_t *n = snd_config_iterator_entry(i); err = set_control(handle, n, &maxnumid, doit); if (err < 0 && (!force_restore || !doit)) goto _close; } /* check if we have additional controls in driver */ /* in this case we should go through init procedure */ if (!doit && maxnumid >= 0) { snd_ctl_elem_id_t *id; snd_ctl_elem_info_t *info; snd_ctl_elem_id_alloca(&id); snd_ctl_elem_info_alloca(&info); snd_ctl_elem_info_set_numid(info, maxnumid+1); if (snd_ctl_elem_info(handle, info) == 0) { /* not very informative */ /* but value is used for check only */ err = -EAGAIN; goto _close; } } _close: snd_ctl_close(handle); return err;}int save_state(const char *file, const char *cardname){ int err; snd_config_t *config; snd_input_t *in; snd_output_t *out; int stdio; err = snd_config_top(&config); if (err < 0) { error("snd_config_top error: %s", snd_strerror(err)); return err; } stdio = !strcmp(file, "-"); if (!stdio && (err = snd_input_stdio_open(&in, file, "r")) >= 0) { err = snd_config_load(config, in); snd_input_close(in);#if 0 if (err < 0) { error("snd_config_load error: %s", snd_strerror(err)); return err; }#endif } if (!cardname) { int card, first = 1; card = -1; /* find each installed soundcards */ while (1) { if (snd_card_next(&card) < 0) break; if (card < 0) { if (first) { if (ignore_nocards) { return 0; } else { error("No soundcards found..."); return -ENODEV; } } break; } first = 0; if ((err = get_controls(card, config))) return err; } } else { int cardno; cardno = snd_card_get_index(cardname); if (cardno < 0) { error("Cannot find soundcard '%s'...", cardname); return cardno; } if ((err = get_controls(cardno, config))) { return err; } } if (stdio) err = snd_output_stdio_attach(&out, stdout, 0); else err = snd_output_stdio_open(&out, file, "w"); if (err < 0) { error("Cannot open %s for writing: %s", file, snd_strerror(err)); return -errno; } err = snd_config_save(config, out); snd_output_close(out); if (err < 0) error("snd_config_save: %s", snd_strerror(err)); return 0;}int load_state(const char *file, const char *initfile, const char *cardname, int do_init){ int err, finalerr = 0; snd_config_t *config; snd_input_t *in; int stdio; err = snd_config_top(&config); if (err < 0) { error("snd_config_top error: %s", snd_strerror(err)); return err; } stdio = !strcmp(file, "-"); if (stdio) err = snd_input_stdio_attach(&in, stdin, 0); else err = snd_input_stdio_open(&in, file, "r"); if (err >= 0) { err = snd_config_load(config, in); snd_input_close(in); if (err < 0) { error("snd_config_load error: %s", snd_strerror(err)); return err; } } else { int card, first = 1; char cardname1[16]; error("Cannot open %s for reading: %s", file, snd_strerror(err)); finalerr = err; card = -1; /* find each installed soundcards */ while (1) { if (snd_card_next(&card) < 0) break; if (card < 0) break; first = 0; if (!do_init) break; sprintf(cardname1, "%i", card); err = init(initfile, cardname1); if (err < 0) { finalerr = err; initfailed(card, "init"); } initfailed(card, "restore"); } if (first) finalerr = 0; /* no cards, no error code */ return finalerr; } if (!cardname) { int card, first = 1; char cardname1[16]; card = -1; /* find each installed soundcards */ while (1) { if (snd_card_next(&card) < 0) break; if (card < 0) { if (first) { if (ignore_nocards) { return 0; } else { error("No soundcards found..."); return -ENODEV; } } break; } first = 0; /* do a check if controls matches state file */ if (do_init && set_controls(card, config, 0)) { sprintf(cardname1, "%i", card); err = init(initfile, cardname1); if (err < 0) { initfailed(card, "init"); finalerr = err; } } if ((err = set_controls(card, config, 1))) { if (!force_restore) finalerr = err; initfailed(card, "restore"); } } } else { int cardno; cardno = snd_card_get_index(cardname); if (cardno < 0) { error("Cannot find soundcard '%s'...", cardname); return -ENODEV; } /* do a check if controls matches state file */ if (do_init && set_controls(cardno, config, 0)) { err = init(initfile, cardname); if (err < 0) { initfailed(cardno, "init"); return err; } } if ((err = set_controls(cardno, config, 1))) { initfailed(cardno, "restore"); if (!force_restore) return err; } } return finalerr;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -