mirror of
https://github.com/alsa-project/alsa-utils
synced 2024-12-22 13:16:31 +01:00
amixer: Use the alsa-lib functions for id print and parse and value parse
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
This commit is contained in:
parent
9cb5e5bee7
commit
e2eab09c1d
1 changed files with 26 additions and 263 deletions
289
amixer/amixer.c
289
amixer/amixer.c
|
@ -138,11 +138,6 @@ static int info(void)
|
||||||
return 0;
|
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)
|
static const char *control_type(snd_ctl_elem_info_t *info)
|
||||||
{
|
{
|
||||||
return snd_ctl_elem_type_name(snd_ctl_elem_info_get_type(info));
|
return snd_ctl_elem_type_name(snd_ctl_elem_info_get_type(info));
|
||||||
|
@ -208,62 +203,6 @@ static int convert_prange(long val, long min, long max)
|
||||||
#define convert_prange1(val, min, max) \
|
#define convert_prange1(val, min, max) \
|
||||||
ceil((val) * ((max) - (min)) * 0.01 + (min))
|
ceil((val) * ((max) - (min)) * 0.01 + (min))
|
||||||
|
|
||||||
static 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 {
|
struct volume_ops {
|
||||||
int (*get_range)(snd_mixer_elem_t *elem, long *min, long *max);
|
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,
|
int (*get)(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t c,
|
||||||
|
@ -476,20 +415,12 @@ static int simple_skip_word(char **ptr, char *str)
|
||||||
|
|
||||||
static void show_control_id(snd_ctl_elem_id_t *id)
|
static void show_control_id(snd_ctl_elem_id_t *id)
|
||||||
{
|
{
|
||||||
unsigned int index, device, subdevice;
|
char *str;
|
||||||
printf("numid=%u,iface=%s,name='%s'",
|
|
||||||
snd_ctl_elem_id_get_numid(id),
|
str = snd_ctl_ascii_elem_id_get(id);
|
||||||
control_iface(id),
|
if (str)
|
||||||
snd_ctl_elem_id_get_name(id));
|
printf("%s", str);
|
||||||
index = snd_ctl_elem_id_get_index(id);
|
free(str);
|
||||||
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)
|
static void print_spaces(unsigned int spaces)
|
||||||
|
@ -1086,103 +1017,6 @@ static int selems(int level)
|
||||||
return 0;
|
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)
|
static int parse_simple_id(const char *str, snd_mixer_selem_id_t *sid)
|
||||||
{
|
{
|
||||||
int c, size;
|
int c, size;
|
||||||
|
@ -1231,34 +1065,6 @@ static int parse_simple_id(const char *str, snd_mixer_selem_id_t *sid)
|
||||||
return 0;
|
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)
|
static int cset(int argc, char *argv[], int roflag, int keep_handle)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
@ -1266,10 +1072,6 @@ static int cset(int argc, char *argv[], int roflag, int keep_handle)
|
||||||
snd_ctl_elem_info_t *info;
|
snd_ctl_elem_info_t *info;
|
||||||
snd_ctl_elem_id_t *id;
|
snd_ctl_elem_id_t *id;
|
||||||
snd_ctl_elem_value_t *control;
|
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_info_alloca(&info);
|
||||||
snd_ctl_elem_id_alloca(&id);
|
snd_ctl_elem_id_alloca(&id);
|
||||||
snd_ctl_elem_value_alloca(&control);
|
snd_ctl_elem_value_alloca(&control);
|
||||||
|
@ -1278,7 +1080,7 @@ static int cset(int argc, char *argv[], int roflag, int keep_handle)
|
||||||
fprintf(stderr, "Specify a full control identifier: [[iface=<iface>,][name='name',][index=<index>,][device=<device>,][subdevice=<subdevice>]]|[numid=<numid>]\n");
|
fprintf(stderr, "Specify a full control identifier: [[iface=<iface>,][name='name',][index=<index>,][device=<device>,][subdevice=<subdevice>]]|[numid=<numid>]\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if (parse_control_id(argv[0], id)) {
|
if (snd_ctl_ascii_elem_id_parse(id, argv[0])) {
|
||||||
fprintf(stderr, "Wrong control identifier: %s\n", argv[0]);
|
fprintf(stderr, "Wrong control identifier: %s\n", argv[0]);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -1303,66 +1105,27 @@ static int cset(int argc, char *argv[], int roflag, int keep_handle)
|
||||||
}
|
}
|
||||||
return err;
|
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) {
|
if (!roflag) {
|
||||||
ptr = argv[1];
|
snd_ctl_elem_value_set_id(control, id);
|
||||||
for (idx = 0; idx < count && idx < 128 && ptr && *ptr; idx++) {
|
if ((err = snd_ctl_elem_read(handle, control)) < 0) {
|
||||||
switch (type) {
|
if (ignore_error)
|
||||||
case SND_CTL_ELEM_TYPE_BOOLEAN:
|
return 0;
|
||||||
tmp = 0;
|
error("Cannot read the given element from control %s\n", card);
|
||||||
if (!strncasecmp(ptr, "on", 2) || !strncasecmp(ptr, "up", 2)) {
|
if (! keep_handle) {
|
||||||
tmp = 1;
|
snd_ctl_close(handle);
|
||||||
ptr += 2;
|
handle = NULL;
|
||||||
} 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], ','))
|
return err;
|
||||||
ptr = argv[1];
|
}
|
||||||
else if (*ptr == ',')
|
err = snd_ctl_ascii_value_parse(handle, control, info, argv[1]);
|
||||||
ptr++;
|
if (err < 0) {
|
||||||
|
if (!ignore_error)
|
||||||
|
error("Control %s parse error: %s\n", card, snd_strerror(err));
|
||||||
|
if (!keep_handle) {
|
||||||
|
snd_ctl_close(handle);
|
||||||
|
handle = NULL;
|
||||||
|
}
|
||||||
|
return ignore_error ? 0 : err;
|
||||||
}
|
}
|
||||||
if ((err = snd_ctl_elem_write(handle, control)) < 0) {
|
if ((err = snd_ctl_elem_write(handle, control)) < 0) {
|
||||||
if (!ignore_error)
|
if (!ignore_error)
|
||||||
|
|
Loading…
Reference in a new issue