📄 init_parse.c
字号:
} if (strncasecmp(attr, "step", 3) == 0) { if (check_id_changed(space, 1)) return NULL; type = snd_ctl_elem_info_get_type(space->ctl_info); if (type == SND_CTL_ELEM_TYPE_INTEGER64) val = snd_ctl_elem_info_get_step64(space->ctl_info); else if (type == SND_CTL_ELEM_TYPE_INTEGER) val = snd_ctl_elem_info_get_step(space->ctl_info); else goto empty; goto value; } if (strncasecmp(attr, "items", 5) == 0) { if (check_id_changed(space, 1)) return NULL; if (snd_ctl_elem_info_get_type(space->ctl_info) == SND_CTL_ELEM_TYPE_ENUMERATED) val = snd_ctl_elem_info_get_items(space->ctl_info); else { empty: res[0] = '\0'; return res; } goto value; } if (strncasecmp(attr, "value", 5) == 0) { if (check_id_changed(space, 3)) return NULL; return get_ctl_value(space); } if (strncasecmp(attr, "dBmin", 5) == 0) { long min, max; if (check_id_changed(space, 1)) return NULL; if (snd_ctl_get_dB_range(snd_hctl_ctl(space->ctl_handle), space->ctl_id, &min, &max) < 0) goto empty; val = min;dbvalue: sprintf(res, "%li.%02idB", (long)(val / 100), (int)abs(val % 100)); return res; } if (strncasecmp(attr, "dBmax", 5) == 0) { long min, max; if (check_id_changed(space, 1)) return NULL; if (snd_ctl_get_dB_range(snd_hctl_ctl(space->ctl_handle), space->ctl_id, &min, &max) < 0) goto empty; val = max; goto dbvalue; } if (strncasecmp(attr, "enums", 5) == 0) { unsigned int idx, items; snd_hctl_elem_t *elem; if (check_id_changed(space, 1)) return NULL; if (snd_ctl_elem_info_get_type(space->ctl_info) != SND_CTL_ELEM_TYPE_ENUMERATED) goto empty; items = snd_ctl_elem_info_get_items(space->ctl_info); strcpy(res, "|"); for (idx = 0; idx < items; idx++) { snd_ctl_elem_info_set_item(space->ctl_info, idx); elem = snd_hctl_find_elem(space->ctl_handle, space->ctl_id); if (elem == NULL) break; if (snd_hctl_elem_info(elem, space->ctl_info) < 0) break; strlcat(res, snd_ctl_elem_info_get_item_name(space->ctl_info), sizeof(res)); strlcat(res, "|", sizeof(res)); } return res; } Perror(space, "unknown ctl{} attribute '%s'", attr); return NULL; value: sprintf(res, "%lli", val); return res;}static int elemid_set(struct space *space, const char *attr, const char *value){ unsigned int val; void (*fcn)(snd_ctl_elem_id_t *, unsigned int); snd_ctl_elem_iface_t iface; int err; if (strncasecmp(attr, "numid", 5) == 0) { fcn = snd_ctl_elem_id_set_numid; goto value; } if (strncasecmp(attr, "iface", 5) == 0 || strncasecmp(attr, "interface", 9) == 0 || strncasecmp(attr, "reset", 5) == 0 || strncasecmp(attr, "search", 6) == 0) { if (strlen(value) == 0 && strncasecmp(attr, "search", 6) == 0) { iface = 0; goto search; } for (iface = 0; iface <= SND_CTL_ELEM_IFACE_LAST; iface++) { if (strcasecmp(value, snd_ctl_elem_iface_name(iface)) == 0) { if (strncasecmp(attr, "reset", 5) == 0) snd_ctl_elem_id_clear(space->ctl_id); if (strncasecmp(attr, "search", 5) == 0) { search: snd_ctl_elem_id_clear(space->ctl_id); /* -1 means all */ snd_ctl_elem_id_set_interface(space->ctl_id, -1); snd_ctl_elem_id_set_device(space->ctl_id, -1); snd_ctl_elem_id_set_subdevice(space->ctl_id, -1); snd_ctl_elem_id_set_name(space->ctl_id, "*"); snd_ctl_elem_id_set_index(space->ctl_id, -1); if (strlen(value) == 0) return 0; } snd_ctl_elem_id_set_interface(space->ctl_id, iface); space->ctl_id_changed = ~0; return 0; } } Perror(space, "unknown control interface name '%s'", value); return -EINVAL; } if (strncasecmp(attr, "device", 6) == 0) { fcn = snd_ctl_elem_id_set_device; goto value; } if (strncasecmp(attr, "subdev", 6) == 0) { fcn = snd_ctl_elem_id_set_subdevice; goto value; } if (strncasecmp(attr, "name", 4) == 0) { snd_ctl_elem_id_set_name(space->ctl_id, value); space->ctl_id_changed = ~0; return 0; } if (strncasecmp(attr, "index", 5) == 0) { fcn = snd_ctl_elem_id_set_index; goto value; } if (strncasecmp(attr, "values", 6) == 0 || strncasecmp(attr, "value", 5) == 0) { err = check_id_changed(space, 1); if (err < 0) { Perror(space, "control element not found"); return err; } err = set_ctl_value(space, value, strncasecmp(attr, "values", 6) == 0); if (err < 0) { space->ctl_id_changed |= 2; } else { space->ctl_id_changed &= ~2; snd_ctl_elem_value_set_id(space->ctl_value, space->ctl_id); err = snd_ctl_elem_write(snd_hctl_ctl(space->ctl_handle), space->ctl_value); if (err < 0) { Perror(space, "value write error: %s", snd_strerror(err)); return err; } } return err; } Perror(space, "unknown CTL{} attribute '%s'", attr); return -EINVAL; value: val = (unsigned int)strtol(value, NULL, 0); fcn(space->ctl_id, val); space->ctl_id_changed = ~0; return 0;}static int get_key(char **line, char **key, enum key_op *op, char **value){ char *linepos; char *temp; linepos = *line; if (linepos == NULL && linepos[0] == '\0') return -EINVAL; /* skip whitespace */ while (isspace(linepos[0]) || linepos[0] == ',') linepos++; /* get the key */ if (linepos[0] == '\0') return -EINVAL; *key = linepos; while (1) { linepos++; if (linepos[0] == '\0') return -1; if (isspace(linepos[0])) break; if (linepos[0] == '=') break; if (linepos[0] == '+') break; if (linepos[0] == '!') break; if (linepos[0] == ':') break; } /* remember end of key */ temp = linepos; /* skip whitespace after key */ while (isspace(linepos[0])) linepos++; if (linepos[0] == '\0') return -EINVAL; /* get operation type */ if (linepos[0] == '=' && linepos[1] == '=') { *op = KEY_OP_MATCH; linepos += 2; dbg("operator=match"); } else if (linepos[0] == '!' && linepos[1] == '=') { *op = KEY_OP_NOMATCH; linepos += 2; dbg("operator=nomatch"); } else if (linepos[0] == '+' && linepos[1] == '=') { *op = KEY_OP_ADD; linepos += 2; dbg("operator=add"); } else if (linepos[0] == '=') { *op = KEY_OP_ASSIGN; linepos++; dbg("operator=assign"); } else if (linepos[0] == ':' && linepos[1] == '=') { *op = KEY_OP_ASSIGN_FINAL; linepos += 2; dbg("operator=assign_final"); } else return -EINVAL; /* terminate key */ temp[0] = '\0'; dbg("key='%s'", *key); /* skip whitespace after operator */ while (isspace(linepos[0])) linepos++; if (linepos[0] == '\0') return -EINVAL; /* get the value*/ if (linepos[0] != '"') return -EINVAL; linepos++; *value = linepos; while (1) { temp = strchr(linepos, '"'); if (temp && temp[-1] == '\\') { linepos = temp + 1; continue; } break; } if (!temp) return -EINVAL; temp[0] = '\0'; temp++; dbg("value='%s'", *value); /* move line to next key */ *line = temp; return 0;}/* extract possible KEY{attr} */static char *get_key_attribute(struct space *space, char *str, char *res, size_t ressize){ char *pos; char *attr; attr = strchr(str, '{'); if (attr != NULL) { attr++; pos = strchr(attr, '}'); if (pos == NULL) { Perror(space, "missing closing brace for format"); return NULL; } pos[0] = '\0'; strlcpy(res, attr, ressize); pos[0] = '}'; dbg("attribute='%s'", res); return res; } return NULL;}/* extract possible {attr} and move str behind it */static char *get_format_attribute(struct space *space, char **str){ char *pos; char *attr = NULL; if (*str[0] == '{') { pos = strchr(*str, '}'); if (pos == NULL) { Perror(space, "missing closing brace for format"); return NULL; } pos[0] = '\0'; attr = *str+1; *str = pos+1; dbg("attribute='%s', str='%s'", attr, *str); } return attr;}/* extract possible format length and move str behind it*/static int get_format_len(struct space *space, char **str){ int num; char *tail; if (isdigit(*str[0])) { num = (int) strtoul(*str, &tail, 10); if (num > 0) { *str = tail; dbg("format length=%i", num); return num; } else { Perror(space, "format parsing error '%s'", *str); } } return -1;}static void apply_format(struct space *space, char *string, size_t maxsize){ char temp[PATH_SIZE]; char temp2[PATH_SIZE]; char *head, *tail, *pos, *cpos, *attr, *rest; struct pair *pair; int len; int i; int count; enum subst_type { SUBST_UNKNOWN, SUBST_CARDINFO, SUBST_CTL, SUBST_RESULT, SUBST_ATTR, SUBST_SYSFSROOT, SUBST_ENV, }; static const struct subst_map { char *name; char fmt; enum subst_type type; } map[] = { { .name = "cardinfo", .fmt = 'i', .type = SUBST_CARDINFO }, { .name = "ctl", .fmt = 'C', .type = SUBST_CTL }, { .name = "result", .fmt = 'c', .type = SUBST_RESULT }, { .name = "attr", .fmt = 's', .type = SUBST_ATTR }, { .name = "sysfsroot", .fmt = 'r', .type = SUBST_SYSFSROOT }, { .name = "env", .fmt = 'E', .type = SUBST_ENV }, { NULL, '\0', 0 } }; enum subst_type type; const struct subst_map *subst; head = string; while (1) { len = -1; while (head[0] != '\0') { if (head[0] == '$') { /* substitute named variable */ if (head[1] == '\0') break; if (head[1] == '$') { strlcpy(temp, head+2, sizeof(temp)); strlcpy(head+1, temp, maxsize); head++; continue; } head[0] = '\0'; for (subst = map; subst->name; subst++) { if (strncasecmp(&head[1], subst->name, strlen(subst->name)) == 0) { type = subst->type; tail = head + strlen(subst->name)+1; dbg("will substitute format name '%s'", subst->name); goto found; } } } else if (head[0] == '%') { /* substitute format char */ if (head[1] == '\0') break; if (head[1] == '%') { strlcpy(temp, head+2, sizeof(temp)); strlcpy(head+1, temp, maxsize); head++; continue; } head[0] = '\0'; tail = head+1; len = get_format_len(space, &tail); for (subst = map; subst->name; subst++) { if (tail[0] == subst->fmt) { type = subst->type; tail++; dbg("will substitute format char '%c'", subst->fmt); goto found; } } } head++; } break;found: attr = get_format_attribute(space, &tail); strlcpy(temp, tail, sizeof(temp)); dbg("format=%i, string='%s', tail='%s'", type ,string, tail); switch (type) { case SUBST_CARDINFO: if (attr == NULL) Perror(space, "missing identification parametr for cardinfo"); else { const char *value = cardinfo_get(space, attr); if (value == NULL) break; strlcat(string, value, maxsize); dbg("substitute cardinfo{%s} '%s'", attr, value); } break; case SUBST_CTL: if (attr == NULL) Perror(space, "missing identification parametr for ctl"); else { const char *value = elemid_get(space, attr); if (value == NULL) break; strlcat(string, value, maxsize); dbg("substitute ctl{%s} '%s'", attr, value); } break; case SUBST_RESULT: if (space->program_result == NULL) break; /* get part part of the result string */ i = 0; if (attr != NULL) i = strtoul(attr, &rest, 10); if (i > 0) { dbg("request part #%d of result string", i); cpos = space->program_result; while (--i) { while (cpos[0] != '\0' && !isspace(cpos[0])) cpos++; while (isspace(cpos[0])) cpos++; } if (i > 0) { Perror(space, "requested part of result string not found"); break; } strlcpy(temp2, cpos, sizeof(temp2)); /* %{2+}c copies the whole string from the second part on */ if (rest[0] != '+') { cpos = strchr(temp2, ' '); if (cpos) cpos[0] = '\0'; } strlcat(string, temp2, maxsize); dbg("substitute part of result string '%s'", temp2); } else { strlcat(string, space->program_result, maxsize); dbg("substitute result string '%s'", space->program_result); } break; case SUBST_ATTR: if (attr == NULL) Perror(space, "missing file parameter for attr"); else { const char *value = NULL; size_t size; pair = value_find(space, "sysfs_device"); if (pair == NULL) break; value = sysfs_attr_get_value(pair->value, attr); if (value == NULL) break; /* strip trailing whitespace and replace untrusted characters of sysfs value */ size = strlcpy(temp2, value, sizeof(temp2)); if (size >= sizeof(temp2)) size = sizeof(temp2)-1; while (size > 0 && isspace(temp2[size-1])) temp2[--size] = '\0'; count = replace_untrusted_chars(temp2); if (count > 0) Perror(space, "%i untrusted character(s) replaced" , count); strlcat(string, temp2, maxsize); dbg("substitute sysfs value '%s'", temp2); } break; case SUBST_SYSFSROOT: strlcat(string, sysfs_path, maxsize); dbg("substitute sysfs_path '%s'", sysfs_path); break; case SUBST_ENV: if (attr == NULL) { dbg("missing attribute"); break; } pos = getenv(attr); if (pos == NULL) { dbg("env '%s' not available", attr); break; } dbg("substitute env '%s=%s'", attr, pos); strlcat(string, pos, maxsize); break; default: Perror(space, "unknown substitution type=%i", type); break; } /* possibly truncate to format-char specified length */ if (len != -1) { head[len] = '\0'; dbg("truncate to %i chars, subtitution string becomes '%s'", len, head); } strlcat(string, temp, maxsize); } /* unescape strings */ head = tail = string; while (*head != '\0') { if (*head == '\\') { head++; if (*head == '\0') break; switch (*head) { case 'a': *tail++ = '\a'; break; case 'b': *tail++ = '\b'; break; case 'n': *tail++ = '\n'; break; case 'r': *tail++ = '\r'; break; case 't': *tail++ = '\t'; break; case 'v': *tail++ = '\v'; break; case '\\': *tail++ = '\\'; break; default: *tail++ = *head; break; } head++; continue; } if (*head) *tail++ = *head++; } *tail = 0;}static int do_match(const char *key, enum key_op op, const char *key_value, const char *value){ int match; if (value == NULL) return 0; dbg("match %s '%s' <-> '%s'", key, key_value, value); match = fnmatch(key_value, value, 0) == 0; if (match && op == KEY_OP_MATCH) { dbg("%s is true (matching value)", key); return 1; } if (!match && op == KEY_OP_NOMATCH) { dbg("%s is true (non-matching value)", key); return 1; } dbg("%s is false", key); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -