mirror of
https://github.com/alsa-project/alsa-utils
synced 2024-11-10 00:05:42 +01:00
Support user-defined controls
Support store/restore of user-defined controls. Also, the numid is no longer checked when -F option is given. The element is determined only from the given name, iface, index, device and subdevice.
This commit is contained in:
parent
2904d69713
commit
2b86b6fe4e
1 changed files with 124 additions and 2 deletions
|
@ -218,6 +218,8 @@ static int get_control(snd_ctl_t *handle, snd_ctl_elem_id_t *id, snd_config_t *t
|
||||||
strcat(buf, " volatile");
|
strcat(buf, " volatile");
|
||||||
if (snd_ctl_elem_info_is_locked(info))
|
if (snd_ctl_elem_info_is_locked(info))
|
||||||
strcat(buf, " locked");
|
strcat(buf, " locked");
|
||||||
|
if (snd_ctl_elem_info_is_user(info))
|
||||||
|
strcat(buf, " user");
|
||||||
err = snd_config_string_add(comment, "access", buf + 1);
|
err = snd_config_string_add(comment, "access", buf + 1);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
error("snd_config_string_add: %s", snd_strerror(err));
|
error("snd_config_string_add: %s", snd_strerror(err));
|
||||||
|
@ -236,6 +238,11 @@ static int get_control(snd_ctl_t *handle, snd_ctl_elem_id_t *id, snd_config_t *t
|
||||||
error("snd_config_string_add: %s", snd_strerror(err));
|
error("snd_config_string_add: %s", snd_strerror(err));
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
err = snd_config_integer_add(comment, "count", count);
|
||||||
|
if (err < 0) {
|
||||||
|
error("snd_config_integer_add: %s", snd_strerror(err));
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case SND_CTL_ELEM_TYPE_BOOLEAN:
|
case SND_CTL_ELEM_TYPE_BOOLEAN:
|
||||||
|
@ -662,6 +669,106 @@ static int config_enumerated(snd_config_t *n, snd_ctl_t *handle,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int is_user_control(snd_config_t *conf)
|
||||||
|
{
|
||||||
|
snd_config_iterator_t i, next;
|
||||||
|
|
||||||
|
snd_config_for_each(i, next, conf) {
|
||||||
|
snd_config_t *n = snd_config_iterator_entry(i);
|
||||||
|
const char *id, *s;
|
||||||
|
if (snd_config_get_id(n, &id) < 0)
|
||||||
|
continue;
|
||||||
|
if (strcmp(id, "access") == 0) {
|
||||||
|
if (snd_config_get_string(n, &s) < 0)
|
||||||
|
return 0;
|
||||||
|
if (strstr(s, "user"))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int add_user_control(snd_ctl_t *handle, snd_ctl_elem_info_t *info, snd_config_t *conf)
|
||||||
|
{
|
||||||
|
snd_config_iterator_t i, next;
|
||||||
|
long imin, imax, istep;
|
||||||
|
snd_ctl_elem_type_t ctype;
|
||||||
|
unsigned int count;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
imin = imax = istep = 0;
|
||||||
|
count = 0;
|
||||||
|
ctype = SND_CTL_ELEM_TYPE_NONE;
|
||||||
|
snd_config_for_each(i, next, conf) {
|
||||||
|
snd_config_t *n = snd_config_iterator_entry(i);
|
||||||
|
const char *id, *type;
|
||||||
|
if (snd_config_get_id(n, &id) < 0)
|
||||||
|
continue;
|
||||||
|
if (strcmp(id, "type") == 0) {
|
||||||
|
if ((err = snd_config_get_string(n, &type)) < 0)
|
||||||
|
return -EINVAL;
|
||||||
|
if (strcmp(type, "BOOLEAN") == 0)
|
||||||
|
ctype = SND_CTL_ELEM_TYPE_BOOLEAN;
|
||||||
|
else if (strcmp(type, "INTEGER") == 0)
|
||||||
|
ctype = SND_CTL_ELEM_TYPE_INTEGER;
|
||||||
|
else if (strcmp(type, "IEC958") == 0)
|
||||||
|
ctype = SND_CTL_ELEM_TYPE_IEC958;
|
||||||
|
else
|
||||||
|
return -EINVAL;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (strcmp(id, "range") == 0) {
|
||||||
|
const char *s;
|
||||||
|
if ((err = snd_config_get_string(n, &s)) < 0)
|
||||||
|
return -EINVAL;
|
||||||
|
switch (ctype) {
|
||||||
|
case SND_CTL_ELEM_TYPE_INTEGER:
|
||||||
|
err = sscanf(s, "%li - %li (step %li)", &imin, &imax, &istep);
|
||||||
|
if (err != 3) {
|
||||||
|
istep = 0;
|
||||||
|
err = sscanf(s, "%li - %li", &imin, &imax);
|
||||||
|
if (err != 2)
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (strcmp(id, "count") == 0) {
|
||||||
|
long v;
|
||||||
|
if ((err = snd_config_get_integer(n, &v)) < 0)
|
||||||
|
return err;
|
||||||
|
count = v;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count <= 0)
|
||||||
|
count = 1;
|
||||||
|
switch (ctype) {
|
||||||
|
case SND_CTL_ELEM_TYPE_INTEGER:
|
||||||
|
if (imin > imax || istep > imax - imin)
|
||||||
|
return -EINVAL;
|
||||||
|
err = snd_ctl_elem_add_integer(handle, info, count, imin, imax, istep);
|
||||||
|
break;
|
||||||
|
case SND_CTL_ELEM_TYPE_BOOLEAN:
|
||||||
|
err = snd_ctl_elem_add_boolean(handle, info, count);
|
||||||
|
break;
|
||||||
|
case SND_CTL_ELEM_TYPE_IEC958:
|
||||||
|
err = snd_ctl_elem_add_iec958(handle, info);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
err = -EINVAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
return snd_ctl_elem_info(handle, info);
|
||||||
|
}
|
||||||
|
|
||||||
static int set_control(snd_ctl_t *handle, snd_config_t *control)
|
static int set_control(snd_ctl_t *handle, snd_config_t *control)
|
||||||
{
|
{
|
||||||
snd_ctl_elem_value_t *ctl;
|
snd_ctl_elem_value_t *ctl;
|
||||||
|
@ -682,6 +789,7 @@ static int set_control(snd_ctl_t *handle, snd_config_t *control)
|
||||||
long index1;
|
long index1;
|
||||||
long index = -1;
|
long index = -1;
|
||||||
snd_config_t *value = NULL;
|
snd_config_t *value = NULL;
|
||||||
|
snd_config_t *comment = NULL;
|
||||||
long val;
|
long val;
|
||||||
long long lval;
|
long long lval;
|
||||||
unsigned int idx;
|
unsigned int idx;
|
||||||
|
@ -705,8 +813,14 @@ static int set_control(snd_ctl_t *handle, snd_config_t *control)
|
||||||
const char *fld;
|
const char *fld;
|
||||||
if (snd_config_get_id(n, &fld) < 0)
|
if (snd_config_get_id(n, &fld) < 0)
|
||||||
continue;
|
continue;
|
||||||
if (strcmp(fld, "comment") == 0)
|
if (strcmp(fld, "comment") == 0) {
|
||||||
|
if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) {
|
||||||
|
error("control.%d.%s is invalid", numid, fld);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
comment = n;
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
if (strcmp(fld, "iface") == 0) {
|
if (strcmp(fld, "iface") == 0) {
|
||||||
iface = (snd_ctl_elem_iface_t)config_iface(n);
|
iface = (snd_ctl_elem_iface_t)config_iface(n);
|
||||||
if (iface < 0) {
|
if (iface < 0) {
|
||||||
|
@ -778,6 +892,14 @@ static int set_control(snd_ctl_t *handle, snd_config_t *control)
|
||||||
snd_ctl_elem_info_set_name(info, name);
|
snd_ctl_elem_info_set_name(info, name);
|
||||||
snd_ctl_elem_info_set_index(info, index);
|
snd_ctl_elem_info_set_index(info, index);
|
||||||
err = snd_ctl_elem_info(handle, info);
|
err = snd_ctl_elem_info(handle, info);
|
||||||
|
if (err < 0 && comment && is_user_control(comment)) {
|
||||||
|
err = add_user_control(handle, info, comment);
|
||||||
|
if (err < 0) {
|
||||||
|
error("failed to add user control #%d (%s)",
|
||||||
|
numid, snd_strerror(err));
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
|
@ -792,7 +914,7 @@ static int set_control(snd_ctl_t *handle, snd_config_t *control)
|
||||||
index1 = snd_ctl_elem_info_get_index(info);
|
index1 = snd_ctl_elem_info_get_index(info);
|
||||||
count = snd_ctl_elem_info_get_count(info);
|
count = snd_ctl_elem_info_get_count(info);
|
||||||
type = snd_ctl_elem_info_get_type(info);
|
type = snd_ctl_elem_info_get_type(info);
|
||||||
if (numid != numid1)
|
if (numid != numid1 && ! force_restore)
|
||||||
error("warning: numid mismatch (%d/%d) for control #%d",
|
error("warning: numid mismatch (%d/%d) for control #%d",
|
||||||
numid, numid1, numid);
|
numid, numid1, numid);
|
||||||
if (iface != iface1)
|
if (iface != iface1)
|
||||||
|
|
Loading…
Reference in a new issue