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

📄 amixer.c

📁 alsa-utils-1.0.14编译声卡驱动所需要的一些文件源码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* *   ALSA command line mixer utility *   Copyright (c) 1999-2000 by Jaroslav Kysela <perex@suse.cz> * *   This program is free software; you can redistribute it and/or modify *   it under the terms of the GNU General Public License as published by *   the Free Software Foundation; either version 2 of the License, or *   (at your option) any later version. * *   This program is distributed in the hope that it will be useful, *   but WITHOUT ANY WARRANTY; without even the implied warranty of *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *   GNU General Public License for more details. * *   You should have received a copy of the GNU General Public License *   along with this program; if not, write to the Free Software *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA * */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <getopt.h>#include <stdarg.h>#include <ctype.h>#include <math.h>#include <errno.h>#include <assert.h>#include <alsa/asoundlib.h>#include <sys/poll.h>#include "amixer.h"#define LEVEL_BASIC		(1<<0)#define LEVEL_INACTIVE		(1<<1)#define LEVEL_ID		(1<<2)static int quiet = 0;static int debugflag = 0;static int no_check = 0;static int smixer_level = 0;static int ignore_error = 0;static struct snd_mixer_selem_regopt smixer_options;static char card[64] = "default";static void error(const char *fmt,...){	va_list va;	va_start(va, fmt);	fprintf(stderr, "amixer: ");	vfprintf(stderr, fmt, va);	fprintf(stderr, "\n");	va_end(va);}static int help(void){	printf("Usage: amixer <options> [command]\n");	printf("\nAvailable options:\n");	printf("  -h,--help       this help\n");	printf("  -c,--card N     select the card\n");	printf("  -D,--device N   select the device, default '%s'\n", card);	printf("  -d,--debug      debug mode\n");	printf("  -n,--nocheck    do not perform range checking\n");	printf("  -v,--version    print version of this program\n");	printf("  -q,--quiet      be quiet\n");	printf("  -i,--inactive   show also inactive controls\n");	printf("  -a,--abstract L select abstraction level (none or basic)\n");	printf("  -s,--stdin      Read and execute commands from stdin sequentially\n");	printf("\nAvailable commands:\n");	printf("  scontrols       show all mixer simple controls\n");	printf("  scontents	  show contents of all mixer simple controls (default command)\n");	printf("  sset sID P      set contents for one mixer simple control\n");	printf("  sget sID        get contents for one mixer simple control\n");	printf("  controls        show all controls for given card\n");	printf("  contents        show contents of all controls for given card\n");	printf("  cset cID P      set control contents for one control\n");	printf("  cget cID        get control contents for one control\n");	return 0;}static int info(void){	int err;	snd_ctl_t *handle;	snd_mixer_t *mhandle;	snd_ctl_card_info_t *info;	snd_ctl_elem_list_t *clist;	snd_ctl_card_info_alloca(&info);	snd_ctl_elem_list_alloca(&clist);		if ((err = snd_ctl_open(&handle, card, 0)) < 0) {		error("Control device %s open error: %s", card, snd_strerror(err));		return err;	}		if ((err = snd_ctl_card_info(handle, info)) < 0) {		error("Control device %s hw info error: %s", card, snd_strerror(err));		return err;	}	printf("Card %s '%s'/'%s'\n", card, snd_ctl_card_info_get_id(info),	       snd_ctl_card_info_get_longname(info));	printf("  Mixer name	: '%s'\n", snd_ctl_card_info_get_mixername(info));	printf("  Components	: '%s'\n", snd_ctl_card_info_get_components(info));	if ((err = snd_ctl_elem_list(handle, clist)) < 0) {		error("snd_ctl_elem_list failure: %s", snd_strerror(err));	} else {		printf("  Controls      : %i\n", snd_ctl_elem_list_get_count(clist));	}	snd_ctl_close(handle);	if ((err = snd_mixer_open(&mhandle, 0)) < 0) {		error("Mixer open error: %s", snd_strerror(err));		return err;	}	if (smixer_level == 0 && (err = snd_mixer_attach(mhandle, card)) < 0) {		error("Mixer attach %s error: %s", card, snd_strerror(err));		snd_mixer_close(mhandle);		return err;	}	if ((err = snd_mixer_selem_register(mhandle, smixer_level > 0 ? &smixer_options : NULL, NULL)) < 0) {		error("Mixer register error: %s", snd_strerror(err));		snd_mixer_close(mhandle);		return err;	}	err = snd_mixer_load(mhandle);	if (err < 0) {		error("Mixer load %s error: %s", card, snd_strerror(err));		snd_mixer_close(mhandle);		return err;	}	printf("  Simple ctrls  : %i\n", snd_mixer_get_count(mhandle));	snd_mixer_close(mhandle);	return 0;}static const char *control_iface(snd_ctl_elem_id_t *id){	return snd_ctl_elem_iface_name(snd_ctl_elem_id_get_interface(id));}static const char *control_type(snd_ctl_elem_info_t *info){	return snd_ctl_elem_type_name(snd_ctl_elem_info_get_type(info));}static const char *control_access(snd_ctl_elem_info_t *info){	static char result[10];	char *res = result;	*res++ = snd_ctl_elem_info_is_readable(info) ? 'r' : '-';	*res++ = snd_ctl_elem_info_is_writable(info) ? 'w' : '-';	*res++ = snd_ctl_elem_info_is_inactive(info) ? 'i' : '-';	*res++ = snd_ctl_elem_info_is_volatile(info) ? 'v' : '-';	*res++ = snd_ctl_elem_info_is_locked(info) ? 'l' : '-';	*res++ = snd_ctl_elem_info_is_tlv_readable(info) ? 'R' : '-';	*res++ = snd_ctl_elem_info_is_tlv_writable(info) ? 'W' : '-';	*res++ = snd_ctl_elem_info_is_tlv_commandable(info) ? 'C' : '-';	*res++ = '\0';	return result;}#define check_range(val, min, max) \	(no_check ? (val) : ((val < min) ? (min) : (val > max) ? (max) : (val))) #if 0static int convert_range(int val, int omin, int omax, int nmin, int nmax){	int orange = omax - omin, nrange = nmax - nmin;		if (orange == 0)		return 0;	return rint((((double)nrange * ((double)val - (double)omin)) + ((double)orange / 2.0)) / ((double)orange + (double)nmin));}#endif#if 0static int convert_db_range(int val, int omin, int omax, int nmin, int nmax){	int orange = omax - omin, nrange = nmax - nmin;		if (orange == 0)		return 0;	return rint((((double)nrange * ((double)val - (double)omin)) + ((double)orange / 2.0)) / (double)orange + (double)nmin);}#endif/* Fuction to convert from volume to percentage. val = volume */static int convert_prange(int val, int min, int max){	int range = max - min;	int tmp;	if (range == 0)		return 0;	val -= min;	tmp = rint((double)val/(double)range * 100);	return tmp;}/* Function to convert from percentage to volume. val = percentage */#define convert_prange1(val, min, max) \	ceil((val) * ((max) - (min)) * 0.01 + (min))static const char *get_percent(int val, int min, int max){	static char str[32];	int p;		p = convert_prange(val, min, max);	sprintf(str, "%i [%i%%]", val, p);	return str;}#if 0static const char *get_percent1(int val, int min, int max, int min_dB, int max_dB){	static char str[32];	int p, db;	p = convert_prange(val, min, max);	db = convert_db_range(val, min, max, min_dB, max_dB);	sprintf(str, "%i [%i%%] [%i.%02idB]", val, p, db / 100, abs(db % 100));	return str;}#endifstatic long get_integer(char **ptr, long min, long max){	long val = min;	char *p = *ptr, *s;	if (*p == ':')		p++;	if (*p == '\0' || (!isdigit(*p) && *p != '-'))		goto out;	s = p;	val = strtol(s, &p, 10);	if (*p == '.') {		p++;		strtol(p, &p, 10);	}	if (*p == '%') {		val = (long)convert_prange1(strtod(s, NULL), min, max);		p++;	}	val = check_range(val, min, max);	if (*p == ',')		p++; out:	*ptr = p;	return val;}static long get_integer64(char **ptr, long long min, long long max){	long long val = min;	char *p = *ptr, *s;	if (*p == ':')		p++;	if (*p == '\0' || (!isdigit(*p) && *p != '-'))		goto out;	s = p;	val = strtol(s, &p, 10);	if (*p == '.') {		p++;		strtol(p, &p, 10);	}	if (*p == '%') {		val = (long long)convert_prange1(strtod(s, NULL), min, max);		p++;	}	val = check_range(val, min, max);	if (*p == ',')		p++; out:	*ptr = p;	return val;}struct volume_ops {	int (*get_range)(snd_mixer_elem_t *elem, long *min, long *max);	int (*get)(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t c,		   long *value);	int (*set)(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t c,		   long value);};	enum { VOL_RAW, VOL_DB };struct volume_ops_set {	int (*has_volume)(snd_mixer_elem_t *elem);	struct volume_ops v[2];};static int set_playback_dB(snd_mixer_elem_t *elem,			   snd_mixer_selem_channel_id_t c, long value){	return snd_mixer_selem_set_playback_dB(elem, c, value, 0);}static int set_capture_dB(snd_mixer_elem_t *elem,			  snd_mixer_selem_channel_id_t c, long value){	return snd_mixer_selem_set_capture_dB(elem, c, value, 0);}static struct volume_ops_set vol_ops[2] = {	{		.has_volume = snd_mixer_selem_has_playback_volume,		.v = {{ snd_mixer_selem_get_playback_volume_range,			snd_mixer_selem_get_playback_volume,			snd_mixer_selem_set_playback_volume },		      { snd_mixer_selem_get_playback_dB_range,			snd_mixer_selem_get_playback_dB,			set_playback_dB }},	},	{		.has_volume = snd_mixer_selem_has_capture_volume,		.v = {{ snd_mixer_selem_get_capture_volume_range,			snd_mixer_selem_get_capture_volume,			snd_mixer_selem_set_capture_volume },		      { snd_mixer_selem_get_capture_dB_range,			snd_mixer_selem_get_capture_dB,			set_capture_dB }},	},};static int set_volume_simple(snd_mixer_elem_t *elem,			     snd_mixer_selem_channel_id_t chn,			     char **ptr, int dir){	long val, orig, pmin, pmax;	char *p = *ptr, *s;	int invalid = 0, err = 0, vol_type = VOL_RAW;	if (! vol_ops[dir].has_volume(elem))		invalid = 1;	if (*p == ':')		p++;	if (*p == '\0' || (!isdigit(*p) && *p != '-'))		goto skip;	if (! invalid &&	    vol_ops[dir].v[VOL_RAW].get_range(elem, &pmin, &pmax) < 0)		invalid = 1;	s = p;	val = strtol(s, &p, 10);	if (*p == '.') {		p++;		strtol(p, &p, 10);	}	if (*p == '%') {		if (! invalid)			val = (long)convert_prange1(strtod(s, NULL), pmin, pmax);		p++;	} else if (p[0] == 'd' && p[1] == 'B') {		if (! invalid) {			val = (long)(strtod(s, NULL) * 100.0);			vol_type = VOL_DB;			if (vol_ops[dir].v[vol_type].get_range(elem, &pmin, &pmax) < 0)				invalid = 1;		}		p += 2;	}	if (*p == '+' || *p == '-') {		if (! invalid) {			if (vol_ops[dir].v[vol_type].get(elem, chn, &orig) < 0)				invalid = 1;			if (*p == '+')				val = orig + val;			else				val = orig - val;		}		p++;	}	if (! invalid) {		val = check_range(val, pmin, pmax);		err = vol_ops[dir].v[vol_type].set(elem, chn, val);	} skip:	if (*p == ',')		p++;	*ptr = p;	return err ? err : (invalid ? -ENOENT : 0);}static int get_bool_simple(char **ptr, char *str, int invert, int orig){	if (**ptr == ':')		(*ptr)++;	if (!strncasecmp(*ptr, str, strlen(str))) {		orig = 1 ^ (invert ? 1 : 0);		while (**ptr != '\0' && **ptr != ',' && **ptr != ':')			(*ptr)++;	}	if (**ptr == ',' || **ptr == ':')		(*ptr)++;	return orig;}		static int simple_skip_word(char **ptr, char *str){	char *xptr = *ptr;	if (*xptr == ':')		xptr++;	if (!strncasecmp(xptr, str, strlen(str))) {		while (*xptr != '\0' && *xptr != ',' && *xptr != ':')			xptr++;		if (*xptr == ',' || *xptr == ':')			xptr++;		*ptr = xptr;		return 1;	}	return 0;}		static void show_control_id(snd_ctl_elem_id_t *id){	unsigned int index, device, subdevice;	printf("numid=%u,iface=%s,name='%s'",	       snd_ctl_elem_id_get_numid(id),	       control_iface(id),	       snd_ctl_elem_id_get_name(id));	index = snd_ctl_elem_id_get_index(id);	device = snd_ctl_elem_id_get_device(id);	subdevice = snd_ctl_elem_id_get_subdevice(id);	if (index)		printf(",index=%i", index);	if (device)		printf(",device=%i", device);	if (subdevice)		printf(",subdevice=%i", subdevice);}static void print_spaces(unsigned int spaces){	while (spaces-- > 0)		putc(' ', stdout);}static void print_dB(long dB){	printf("%li.%02lidB", dB / 100, (dB < 0 ? -dB : dB) % 100);}static void decode_tlv(unsigned int spaces, unsigned int *tlv, unsigned int tlv_size){	unsigned int type = tlv[0];	unsigned int size;	unsigned int idx = 0;		if (tlv_size < 2 * sizeof(unsigned int)) {		printf("TLV size error!\n");		return;	}	print_spaces(spaces);	printf("| ");	type = tlv[idx++];	size = tlv[idx++];	tlv_size -= 2 * sizeof(unsigned int);	if (size > tlv_size) {		printf("TLV size error (%i, %i, %i)!\n", type, size, tlv_size);		return;	}	switch (type) {	case SND_CTL_TLVT_CONTAINER:		size += sizeof(unsigned int) -1;		size /= sizeof(unsigned int);		while (idx < size) {			if (tlv[idx+1] > (size - idx) * sizeof(unsigned int)) {				printf("TLV size error in compound!\n");				return;			}			decode_tlv(spaces + 2, tlv + idx, tlv[idx+1]);			idx += 2 + (tlv[1] + sizeof(unsigned int) - 1) / sizeof(unsigned int);		}		break;	case SND_CTL_TLVT_DB_SCALE:		printf("dBscale-");		if (size != 2 * sizeof(unsigned int)) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -