mirror of
https://github.com/alsa-project/alsa-utils
synced 2024-11-10 00:45:41 +01:00
alsactl: add support for recreating enumerated user controls
Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
This commit is contained in:
parent
e80b015689
commit
5a6ca47cb9
2 changed files with 72 additions and 9 deletions
|
@ -847,6 +847,49 @@ static int get_comment_range(snd_config_t *n, int ctype,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct string_array {
|
||||||
|
unsigned int count;
|
||||||
|
const char **strings;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int get_comment_items(snd_config_t *n, struct string_array *items)
|
||||||
|
{
|
||||||
|
snd_config_iterator_t it, next;
|
||||||
|
unsigned int i;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
snd_config_for_each(it, next, n) {
|
||||||
|
snd_config_t *item = snd_config_iterator_entry(it);
|
||||||
|
const char *id;
|
||||||
|
unsigned int numid;
|
||||||
|
|
||||||
|
if (snd_config_get_id(item, &id) < 0)
|
||||||
|
return -EINVAL;
|
||||||
|
numid = atoi(id);
|
||||||
|
if (numid > 999999)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (numid >= items->count) {
|
||||||
|
const char **strings = realloc(items->strings, (numid + 1) * sizeof(char *));
|
||||||
|
if (!strings)
|
||||||
|
return -ENOMEM;
|
||||||
|
for (i = items->count; i < numid + 1; ++i)
|
||||||
|
strings[i] = NULL;
|
||||||
|
items->count = numid + 1;
|
||||||
|
items->strings = strings;
|
||||||
|
}
|
||||||
|
err = snd_config_get_string(item, &items->strings[numid]);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < items->count; ++i)
|
||||||
|
if (!items->strings[i])
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int add_user_control(snd_ctl_t *handle, snd_ctl_elem_info_t *info, snd_config_t *conf)
|
static int add_user_control(snd_ctl_t *handle, snd_ctl_elem_info_t *info, snd_config_t *conf)
|
||||||
{
|
{
|
||||||
snd_ctl_elem_id_t *id;
|
snd_ctl_elem_id_t *id;
|
||||||
|
@ -854,12 +897,15 @@ static int add_user_control(snd_ctl_t *handle, snd_ctl_elem_info_t *info, snd_co
|
||||||
long imin, imax, istep;
|
long imin, imax, istep;
|
||||||
snd_ctl_elem_type_t ctype;
|
snd_ctl_elem_type_t ctype;
|
||||||
unsigned int count;
|
unsigned int count;
|
||||||
|
struct string_array enum_items;
|
||||||
int err;
|
int err;
|
||||||
unsigned int *tlv;
|
unsigned int *tlv;
|
||||||
|
|
||||||
imin = imax = istep = 0;
|
imin = imax = istep = 0;
|
||||||
count = 0;
|
count = 0;
|
||||||
ctype = SND_CTL_ELEM_TYPE_NONE;
|
ctype = SND_CTL_ELEM_TYPE_NONE;
|
||||||
|
enum_items.count = 0;
|
||||||
|
enum_items.strings = NULL;
|
||||||
tlv = NULL;
|
tlv = NULL;
|
||||||
snd_config_for_each(i, next, conf) {
|
snd_config_for_each(i, next, conf) {
|
||||||
snd_config_t *n = snd_config_iterator_entry(i);
|
snd_config_t *n = snd_config_iterator_entry(i);
|
||||||
|
@ -869,31 +915,39 @@ static int add_user_control(snd_ctl_t *handle, snd_ctl_elem_info_t *info, snd_co
|
||||||
if (strcmp(id, "type") == 0) {
|
if (strcmp(id, "type") == 0) {
|
||||||
err = get_comment_type(n);
|
err = get_comment_type(n);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
goto error;
|
||||||
ctype = err;
|
ctype = err;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (strcmp(id, "range") == 0) {
|
if (strcmp(id, "range") == 0) {
|
||||||
err = get_comment_range(n, ctype, &imin, &imax, &istep);
|
err = get_comment_range(n, ctype, &imin, &imax, &istep);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
goto error;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (strcmp(id, "count") == 0) {
|
if (strcmp(id, "count") == 0) {
|
||||||
long v;
|
long v;
|
||||||
if ((err = snd_config_get_integer(n, &v)) < 0)
|
if ((err = snd_config_get_integer(n, &v)) < 0)
|
||||||
return err;
|
goto error;
|
||||||
count = v;
|
count = v;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (strcmp(id, "item") == 0) {
|
||||||
|
err = get_comment_items(n, &enum_items);
|
||||||
|
if (err < 0)
|
||||||
|
goto error;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (strcmp(id, "tlv") == 0) {
|
if (strcmp(id, "tlv") == 0) {
|
||||||
const char *s;
|
const char *s;
|
||||||
if ((err = snd_config_get_string(n, &s)) < 0)
|
if ((err = snd_config_get_string(n, &s)) < 0)
|
||||||
return -EINVAL;
|
goto error;
|
||||||
if (tlv)
|
if (tlv)
|
||||||
free(tlv);
|
free(tlv);
|
||||||
if ((tlv = str_to_tlv(s)) == NULL)
|
if ((tlv = str_to_tlv(s)) == NULL) {
|
||||||
return -EINVAL;
|
err = -EINVAL;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -904,8 +958,10 @@ static int add_user_control(snd_ctl_t *handle, snd_ctl_elem_info_t *info, snd_co
|
||||||
count = 1;
|
count = 1;
|
||||||
switch (ctype) {
|
switch (ctype) {
|
||||||
case SND_CTL_ELEM_TYPE_INTEGER:
|
case SND_CTL_ELEM_TYPE_INTEGER:
|
||||||
if (imin > imax || istep > imax - imin)
|
if (imin > imax || istep > imax - imin) {
|
||||||
return -EINVAL;
|
err = -EINVAL;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
err = snd_ctl_elem_add_integer(handle, id, count, imin, imax, istep);
|
err = snd_ctl_elem_add_integer(handle, id, count, imin, imax, istep);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -915,6 +971,10 @@ static int add_user_control(snd_ctl_t *handle, snd_ctl_elem_info_t *info, snd_co
|
||||||
case SND_CTL_ELEM_TYPE_BOOLEAN:
|
case SND_CTL_ELEM_TYPE_BOOLEAN:
|
||||||
err = snd_ctl_elem_add_boolean(handle, id, count);
|
err = snd_ctl_elem_add_boolean(handle, id, count);
|
||||||
break;
|
break;
|
||||||
|
case SND_CTL_ELEM_TYPE_ENUMERATED:
|
||||||
|
err = snd_ctl_elem_add_enumerated(handle, id, count,
|
||||||
|
enum_items.count, enum_items.strings);
|
||||||
|
break;
|
||||||
case SND_CTL_ELEM_TYPE_IEC958:
|
case SND_CTL_ELEM_TYPE_IEC958:
|
||||||
err = snd_ctl_elem_add_iec958(handle, id);
|
err = snd_ctl_elem_add_iec958(handle, id);
|
||||||
break;
|
break;
|
||||||
|
@ -925,6 +985,7 @@ static int add_user_control(snd_ctl_t *handle, snd_ctl_elem_info_t *info, snd_co
|
||||||
|
|
||||||
error:
|
error:
|
||||||
free(tlv);
|
free(tlv);
|
||||||
|
free(enum_items.strings);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
return snd_ctl_elem_info(handle, info);
|
return snd_ctl_elem_info(handle, info);
|
||||||
|
|
|
@ -29,7 +29,9 @@ AC_PROG_INSTALL
|
||||||
AC_PROG_MKDIR_P
|
AC_PROG_MKDIR_P
|
||||||
AC_PROG_LN_S
|
AC_PROG_LN_S
|
||||||
AC_PROG_SED
|
AC_PROG_SED
|
||||||
AM_PATH_ALSA(1.0.16)
|
AM_PATH_ALSA(1.0.24)
|
||||||
|
AC_CHECK_FUNC([snd_ctl_elem_add_enumerated],
|
||||||
|
, [AC_ERROR([No user enum control support in alsa-lib])])
|
||||||
|
|
||||||
dnl Check components
|
dnl Check components
|
||||||
AC_CHECK_HEADERS([alsa/pcm.h], [have_pcm="yes"], [have_pcm="no"],
|
AC_CHECK_HEADERS([alsa/pcm.h], [have_pcm="yes"], [have_pcm="no"],
|
||||||
|
|
Loading…
Reference in a new issue