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));
#define convert_prange1(val, min, max) \
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 {
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,
invalid = 1;
if (*p == '+') {
val = orig + val;
- correct = -1;
+ correct = 1;
} else {
val = orig - val;
- correct = 1;
+ correct = -1;
}
}
p++;
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);
+ char *str;
+
+ str = snd_ctl_ascii_elem_id_get(id);
+ if (str)
+ printf("%s", str);
+ free(str);
}
static void print_spaces(unsigned int spaces)
static void print_dB(long dB)
{
- printf("%li.%02lidB", dB / 100, (dB < 0 ? -dB : dB) % 100);
+ if (dB < 0) {
+ printf("-%li.%02lidB", -dB / 100, -dB % 100);
+ } else {
+ printf("%li.%02lidB", dB / 100, 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;
+ const char *chmap_type = NULL;
if (tlv_size < 2 * sizeof(unsigned int)) {
printf("TLV size error!\n");
}
switch (type) {
case SND_CTL_TLVT_CONTAINER:
+ printf("container\n");
size += sizeof(unsigned int) -1;
size /= sizeof(unsigned int);
while (idx < size) {
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);
+ decode_tlv(spaces + 2, tlv + idx, tlv[idx+1] + 8);
+ idx += 2 + (tlv[idx+1] + sizeof(unsigned int) - 1) / sizeof(unsigned int);
}
break;
case SND_CTL_TLVT_DB_SCALE:
}
} else {
printf("min=");
- print_dB(tlv[2]);
+ print_dB((int)tlv[2]);
printf(",max=");
- print_dB(tlv[3]);
+ print_dB((int)tlv[3]);
}
break;
#endif
}
} else {
printf("min=");
- print_dB(tlv[2]);
+ print_dB((int)tlv[2]);
printf(",max=");
- print_dB(tlv[3]);
+ print_dB((int)tlv[3]);
+ }
+ break;
+#endif
+#ifdef SND_CTL_TLVT_CHMAP_FIXED
+ case SND_CTL_TLVT_CHMAP_FIXED:
+ chmap_type = "fixed";
+ /* Fall through */
+ case SND_CTL_TLVT_CHMAP_VAR:
+ if (!chmap_type)
+ chmap_type = "variable";
+ /* Fall through */
+ case SND_CTL_TLVT_CHMAP_PAIRED:
+ if (!chmap_type)
+ chmap_type = "paired";
+ printf("chmap-%s=", chmap_type);
+
+ while (size > 0) {
+ printf("%s", snd_pcm_chmap_name(tlv[idx++]));
+ size -= sizeof(unsigned int);
+ if (size > 0)
+ printf(",");
}
break;
#endif
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;
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;
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);
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)) {
+ if (snd_ctl_ascii_elem_id_parse(id, argv[0])) {
fprintf(stderr, "Wrong control identifier: %s\n", argv[0]);
return -EINVAL;
}
}
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);
-
+ snd_ctl_elem_info_get_id(info, id); /* FIXME: Remove it when hctl find works ok !!! */
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;
+ snd_ctl_elem_value_set_id(control, id);
+ if ((err = snd_ctl_elem_read(handle, control)) < 0) {
+ if (ignore_error)
+ return 0;
+ error("Cannot read the given element from control %s\n", card);
+ if (! keep_handle) {
+ snd_ctl_close(handle);
+ handle = NULL;
}
- if (!strchr(argv[1], ','))
- ptr = argv[1];
- else if (*ptr == ',')
- ptr++;
+ return err;
+ }
+ err = snd_ctl_ascii_value_parse(handle, control, info, argv[1]);
+ 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 (!ignore_error)