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:
Jaroslav Kysela 2013-04-09 18:38:58 +02:00
parent 9cb5e5bee7
commit e2eab09c1d

View file

@ -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); return err;
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], ',')) err = snd_ctl_ascii_value_parse(handle, control, info, argv[1]);
ptr = argv[1]; if (err < 0) {
else if (*ptr == ',') if (!ignore_error)
ptr++; 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)