⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 amixer.c

📁 ALSA驱动的一些调试测试工具
💻 C
📖 第 1 页 / 共 4 页
字号:
	}	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 + -