📄 amixer.c
字号:
} if ((err = snd_mixer_selem_register(handle, smixer_level > 0 ? &smixer_options : NULL, NULL)) < 0) { error("Mixer register error: %s", snd_strerror(err)); snd_mixer_close(handle); return err; } err = snd_mixer_load(handle); if (err < 0) { error("Mixer %s load error: %s", card, snd_strerror(err)); snd_mixer_close(handle); return err; } for (elem = snd_mixer_first_elem(handle); elem; elem = snd_mixer_elem_next(elem)) { snd_mixer_selem_get_id(elem, sid); if (!(level & LEVEL_INACTIVE) && !snd_mixer_selem_is_active(elem)) continue; printf("Simple mixer control '%s',%i\n", snd_mixer_selem_id_get_name(sid), snd_mixer_selem_id_get_index(sid)); show_selem(handle, sid, " ", level); } snd_mixer_close(handle); return 0;}static int parse_control_id(const char *str, snd_ctl_elem_id_t *id){ int c, size, numid; char *ptr; while (*str == ' ' || *str == '\t') str++; if (!(*str)) return -EINVAL; snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER); /* default */ while (*str) { if (!strncasecmp(str, "numid=", 6)) { str += 6; numid = atoi(str); if (numid <= 0) { fprintf(stderr, "amixer: Invalid numid %d\n", numid); return -EINVAL; } snd_ctl_elem_id_set_numid(id, atoi(str)); while (isdigit(*str)) str++; } else if (!strncasecmp(str, "iface=", 6)) { str += 6; if (!strncasecmp(str, "card", 4)) { snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_CARD); str += 4; } else if (!strncasecmp(str, "mixer", 5)) { snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER); str += 5; } else if (!strncasecmp(str, "pcm", 3)) { snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_PCM); str += 3; } else if (!strncasecmp(str, "rawmidi", 7)) { snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_RAWMIDI); str += 7; } else if (!strncasecmp(str, "timer", 5)) { snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_TIMER); str += 5; } else if (!strncasecmp(str, "sequencer", 9)) { snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_SEQUENCER); str += 9; } else { return -EINVAL; } } else if (!strncasecmp(str, "name=", 5)) { char buf[64]; str += 5; ptr = buf; size = 0; if (*str == '\'' || *str == '\"') { c = *str++; while (*str && *str != c) { if (size < (int)sizeof(buf)) { *ptr++ = *str; size++; } str++; } if (*str == c) str++; } else { while (*str && *str != ',') { if (size < (int)sizeof(buf)) { *ptr++ = *str; size++; } str++; } *ptr = '\0'; } snd_ctl_elem_id_set_name(id, buf); } else if (!strncasecmp(str, "index=", 6)) { str += 6; snd_ctl_elem_id_set_index(id, atoi(str)); while (isdigit(*str)) str++; } else if (!strncasecmp(str, "device=", 7)) { str += 7; snd_ctl_elem_id_set_device(id, atoi(str)); while (isdigit(*str)) str++; } else if (!strncasecmp(str, "subdevice=", 10)) { str += 10; snd_ctl_elem_id_set_subdevice(id, atoi(str)); while (isdigit(*str)) str++; } if (*str == ',') { str++; } else { if (*str) return -EINVAL; } } return 0;}static int parse_simple_id(const char *str, snd_mixer_selem_id_t *sid){ int c, size; char buf[128]; char *ptr = buf; while (*str == ' ' || *str == '\t') str++; if (!(*str)) return -EINVAL; size = 1; /* for '\0' */ if (*str != '"' && *str != '\'') { while (*str && *str != ',') { if (size < (int)sizeof(buf)) { *ptr++ = *str; size++; } str++; } } else { c = *str++; while (*str && *str != c) { if (size < (int)sizeof(buf)) { *ptr++ = *str; size++; } str++; } if (*str == c) str++; } if (*str == '\0') { snd_mixer_selem_id_set_index(sid, 0); *ptr = 0; goto _set; } if (*str != ',') return -EINVAL; *ptr = 0; /* terminate the string */ str++; if (!isdigit(*str)) return -EINVAL; snd_mixer_selem_id_set_index(sid, atoi(str)); _set: snd_mixer_selem_id_set_name(sid, buf); return 0;}static int get_ctl_enum_item_index(snd_ctl_t *handle, snd_ctl_elem_info_t *info, char **ptrp){ char *ptr = *ptrp; int items, i, len; const char *name; items = snd_ctl_elem_info_get_items(info); if (items <= 0) return -1; for (i = 0; i < items; i++) { snd_ctl_elem_info_set_item(info, i); if (snd_ctl_elem_info(handle, info) < 0) return -1; name = snd_ctl_elem_info_get_item_name(info); len = strlen(name); if (! strncmp(name, ptr, len)) { if (! ptr[len] || ptr[len] == ',' || ptr[len] == '\n') { ptr += len; *ptrp = ptr; return i; } } } return -1;}static int cset(int argc, char *argv[], int roflag, int keep_handle){ int err; static snd_ctl_t *handle = NULL; snd_ctl_elem_info_t *info; snd_ctl_elem_id_t *id; snd_ctl_elem_value_t *control; char *ptr; unsigned int idx, count; long tmp; snd_ctl_elem_type_t type; snd_ctl_elem_info_alloca(&info); snd_ctl_elem_id_alloca(&id); snd_ctl_elem_value_alloca(&control); if (argc < 1) { fprintf(stderr, "Specify a full control identifier: [[iface=<iface>,][name='name',][index=<index>,][device=<device>,][subdevice=<subdevice>]]|[numid=<numid>]\n"); return -EINVAL; } if (parse_control_id(argv[0], id)) { fprintf(stderr, "Wrong control identifier: %s\n", argv[0]); return -EINVAL; } if (debugflag) { printf("VERIFY ID: "); show_control_id(id); printf("\n"); } if (handle == NULL && (err = snd_ctl_open(&handle, card, 0)) < 0) { error("Control %s open error: %s\n", card, snd_strerror(err)); return err; } snd_ctl_elem_info_set_id(info, id); if ((err = snd_ctl_elem_info(handle, info)) < 0) { if (ignore_error) return 0; error("Cannot find the given element from control %s\n", card); if (! keep_handle) { snd_ctl_close(handle); handle = NULL; } return err; } snd_ctl_elem_info_get_id(info, id); /* FIXME: Remove it when hctl find works ok !!! */ type = snd_ctl_elem_info_get_type(info); count = snd_ctl_elem_info_get_count(info); snd_ctl_elem_value_set_id(control, id); if (!roflag) { ptr = argv[1]; for (idx = 0; idx < count && idx < 128 && ptr && *ptr; idx++) { switch (type) { case SND_CTL_ELEM_TYPE_BOOLEAN: tmp = 0; if (!strncasecmp(ptr, "on", 2) || !strncasecmp(ptr, "up", 2)) { tmp = 1; ptr += 2; } else if (!strncasecmp(ptr, "yes", 3)) { tmp = 1; ptr += 3; } else if (!strncasecmp(ptr, "toggle", 6)) { tmp = snd_ctl_elem_value_get_boolean(control, idx); tmp = tmp > 0 ? 0 : 1; ptr += 6; } else if (isdigit(*ptr)) { tmp = atoi(ptr) > 0 ? 1 : 0; while (isdigit(*ptr)) ptr++; } else { while (*ptr && *ptr != ',') ptr++; } snd_ctl_elem_value_set_boolean(control, idx, tmp); break; case SND_CTL_ELEM_TYPE_INTEGER: tmp = get_integer(&ptr, snd_ctl_elem_info_get_min(info), snd_ctl_elem_info_get_max(info)); snd_ctl_elem_value_set_integer(control, idx, tmp); break; case SND_CTL_ELEM_TYPE_INTEGER64: tmp = get_integer64(&ptr, snd_ctl_elem_info_get_min64(info), snd_ctl_elem_info_get_max64(info)); snd_ctl_elem_value_set_integer64(control, idx, tmp); break; case SND_CTL_ELEM_TYPE_ENUMERATED: tmp = get_ctl_enum_item_index(handle, info, &ptr); if (tmp < 0) tmp = get_integer(&ptr, 0, snd_ctl_elem_info_get_items(info) - 1); snd_ctl_elem_value_set_enumerated(control, idx, tmp); break; case SND_CTL_ELEM_TYPE_BYTES: tmp = get_integer(&ptr, 0, 255); snd_ctl_elem_value_set_byte(control, idx, tmp); break; default: break; } if (!strchr(argv[1], ',')) ptr = argv[1]; else if (*ptr == ',') ptr++; } if ((err = snd_ctl_elem_write(handle, control)) < 0) { if (!ignore_error) error("Control %s element write error: %s\n", card, snd_strerror(err)); if (!keep_handle) { snd_ctl_close(handle); handle = NULL; } return ignore_error ? 0 : err; } } if (! keep_handle) { snd_ctl_close(handle); handle = NULL; } if (!quiet) { snd_hctl_t *hctl; snd_hctl_elem_t *elem; if ((err = snd_hctl_open(&hctl, card, 0)) < 0) { error("Control %s open error: %s\n", card, snd_strerror(err)); return err; } if ((err = snd_hctl_load(hctl)) < 0) { error("Control %s load error: %s\n", card, snd_strerror(err)); return err; } elem = snd_hctl_find_elem(hctl, id); if (elem) show_control(" ", elem, LEVEL_BASIC | LEVEL_ID); else printf("Could not find the specified element\n"); snd_hctl_close(hctl); } return 0;}typedef struct channel_mask { char *name; unsigned int mask;} channel_mask_t;static const channel_mask_t chanmask[] = { {"frontleft", 1 << SND_MIXER_SCHN_FRONT_LEFT}, {"frontright", 1 << SND_MIXER_SCHN_FRONT_RIGHT}, {"frontcenter", 1 << SND_MIXER_SCHN_FRONT_CENTER}, {"front", ((1 << SND_MIXER_SCHN_FRONT_LEFT) | (1 << SND_MIXER_SCHN_FRONT_RIGHT))}, {"center", 1 << SND_MIXER_SCHN_FRONT_CENTER}, {"rearleft", 1 << SND_MIXER_SCHN_REAR_LEFT}, {"rearright", 1 << SND_MIXER_SCHN_REAR_RIGHT}, {"rear", ((1 << SND_MIXER_SCHN_REAR_LEFT) | (1 << SND_MIXER_SCHN_REAR_RIGHT))}, {"woofer", 1 << SND_MIXER_SCHN_WOOFER}, {NULL, 0}};static unsigned int channels_mask(char **arg, unsigned int def){ const channel_mask_t *c; for (c = chanmask; c->name; c++) { if (strncasecmp(*arg, c->name, strlen(c->name)) == 0) { while (**arg != '\0' && **arg != ',' && **arg != ' ' && **arg != '\t') (*arg)++; if (**arg == ',' || **arg == ' ' || **arg == '\t') (*arg)++; return c->mask; } } return def;}static unsigned int dir_mask(char **arg, unsigned int def){ int findend = 0; if (strncasecmp(*arg, "playback", 8) == 0) def = findend = 1; else if (strncasecmp(*arg, "capture", 8) == 0) def = findend = 2; if (findend) { while (**arg != '\0' && **arg != ',' && **arg != ' ' && **arg != '\t') (*arg)++; if (**arg == ',' || **arg == ' ' || **arg == '\t') (*arg)++; } return def;}static int get_enum_item_index(snd_mixer_elem_t *elem, char **ptrp){ char *ptr = *ptrp; int items, i, len; char name[40]; items = snd_mixer_selem_get_enum_items(elem); if (items <= 0) return -1; for (i = 0; i < items; i++) { if (snd_mixer_selem_get_enum_item_name(elem, i, sizeof(name)-1, name) < 0) continue; len = strlen(name); if (! strncmp(name, ptr, len)) { if (! ptr[len] || ptr[len] == ',' || ptr[len] == '\n') { ptr += len; *ptrp = ptr; return i; } } } return -1;}static int sset_enum(snd_mixer_elem_t *elem, unsigned int argc, char **argv){ unsigned int idx, chn = 0; int check_flag = ignore_error ? 0 : -1; for (idx = 1; idx < argc; idx++) { char *ptr = argv[idx]; while (*ptr) { int ival = get_enum_item_index(elem, &ptr); if (ival < 0) return check_flag; if (snd_mixer_selem_set_enum_item(elem, chn, ival) >= 0) check_flag = 1; /* skip separators */ while (*ptr == ',' || isspace(*ptr)) ptr++; } } return check_flag;}static int sset_channels(snd_mixer_elem_t *elem, unsigned int argc, char **argv){ unsigned int channels = ~0U; unsigned int dir = 3, okflag = 3; unsigned int idx; snd_mixer_selem_channel_id_t chn; int check_flag = ignore_error ? 0 : -1; for (idx = 1; idx < argc; idx++) { char *ptr = argv[idx], *optr; int multi, firstchn = 1; channels = channels_mask(&ptr, channels); if (*ptr == '\0') continue; dir = dir_mask(&ptr, dir); if (*ptr == '\0') continue; multi = (strchr(ptr, ',') != NULL); optr = ptr; for (chn = 0; chn <= SND_MIXER_SCHN_LAST; chn++) { char *sptr = NULL; int ival; if (!(channels & (1 << chn))) continue; if ((dir & 1) && snd_mixer_selem_has_playback_channel(elem, chn)) { sptr = ptr; if (!strncmp(ptr, "mute", 4) && snd_mixer_selem_has_playback_switch(elem)) { snd_mixer_selem_get_playback_switch(elem, chn, &ival); if (snd_mixer_selem_set_playback_switch(elem, chn, get_bool_simple(&ptr, "mute", 1, ival)) >= 0) check_flag = 1; } else if (!strncmp(ptr, "off", 3) && snd_mixer_selem_has_playback_switch(elem)) { snd_mixer_selem_get_playback_switch(elem, chn, &ival); if (snd_mixer_selem_set_playback_switch(elem, chn, get_bool_simple(&ptr, "off", 1, ival)) >= 0) check_flag = 1; } else if (!strncmp(ptr, "unmute", 6) && snd_mixer_selem_has_playback_switch(elem)) { snd_mixer_selem_get_playback_switch(elem, chn, &ival); if (snd_mixer_selem_set_playback_switch(elem, chn, get_bool_simple(&ptr, "unmute", 0, ival)) >= 0) check_flag = 1; } else if (!strncmp(ptr, "on", 2) && snd_mixer_selem_has_playback_switch(elem)) { snd_mixer_selem_get_playback_switch(elem, chn, &ival); if (snd_mixer_selem_set_playback_switch(elem, chn, get_bool_simple(&ptr, "on", 0, ival)) >= 0) check_flag = 1; } else if (!strncmp(ptr, "toggle", 6) && snd_mixer_selem_has_playback_switch(elem)) { if (firstchn || !snd_mixer_selem_has_playback_switch_joined(elem)) { snd_mixer_selem_get_playback_switch(elem, chn, &ival); if (snd_mixer_selem_set_playback_switch(elem, chn, (ival ? 1 : 0) ^ 1) >= 0) check_flag = 1; } simple_skip_word(&ptr, "toggle"); } else if (isdigit(*ptr) || *ptr == '-' || *ptr == '+') { if (set_volume_simple(elem, chn, &ptr, 0) >= 0) check_flag = 1; } else if (simple_skip_word(&ptr, "cap") || simple_skip_word(&ptr, "rec") || simple_skip_word(&ptr, "nocap") || simple_skip_word(&ptr, "norec")) { /* nothing */ } else { okflag &= ~1; } } if ((dir & 2) && snd_mixer_selem_has_capture_channel(elem, chn)) { if (sptr != NULL) ptr = sptr; sptr = ptr; if (!strncmp(ptr, "cap", 3) && snd_mixer_selem_has_capture_switch(elem)) { snd_mixer_selem_get_capture_switch(elem, chn, &ival); if (snd_mixer_selem_set_capture_switch(elem, chn, get_bool_simple(&ptr, "cap", 0, ival)) >= 0) check_flag = 1; } else if (!strncmp(ptr, "rec", 3) && snd_mixer_selem_has_capture_switch(elem)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -