diff options
author | Takashi Iwai <tiwai@suse.de> | 2015-06-01 16:18:25 +0200 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2015-06-01 16:21:01 +0200 |
commit | 504c7cf80cfdeaaf2391f76ebf1cafa97bf55ccc (patch) | |
tree | 3d0ab711c581a9da0273788b1892e87dadce7854 | |
parent | eeccbe15bd16dff8adb2edbba654c9f543e4a4d7 (diff) | |
download | salsa-lib-504c7cf80cfdeaaf2391f76ebf1cafa97bf55ccc.tar.gz |
Add ctl ASCII parser code
Added a few helper functions that have been added some time ago to
alsa-lib for dealing with ASCII <-> ctl conversions. They are mostly
used by amixer.
They are enabled via --enable-ctlasciiparser configure option.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r-- | configure.ac | 14 | ||||
-rw-r--r-- | src/control.c | 123 | ||||
-rw-r--r-- | src/recipe.h.in | 3 |
3 files changed, 140 insertions, 0 deletions
diff --git a/configure.ac b/configure.ac index eae1b81..19aff7e 100644 --- a/configure.ac +++ b/configure.ac @@ -137,6 +137,11 @@ AC_ARG_ENABLE(abicheck, [enable library ABI check]), abicheck="$enableval", abicheck="no") +AC_ARG_ENABLE(ctlasciiparser, + AS_HELP_STRING([--enable-ctlasciiparser], + [enable ctl ASCII parser (for amixer)]), + ctlasciiparser="$enableval", ctlasciiparser="no") + AC_ARG_ENABLE(everything, AS_HELP_STRING([--enable-everything], [enable everything :)]), @@ -160,6 +165,7 @@ if test "$everything" = "yes"; then support_float="yes" support_4bit="yes" abicheck="yes" + ctlasciiparser="yes" fi SALSA_DEPLIBS="" @@ -246,6 +252,13 @@ else fi AC_SUBST(SALSA_CHECK_ABI) +if test "$ctlasciiparser" = "yes"; then + SALSA_CTL_ASCII_PARSER=1 +else + SALSA_CTL_ASCII_PARSER=0 +fi +AC_SUBST(SALSA_CTL_ASCII_PARSER) + if test "$delight_valgrind" = "yes"; then AC_DEFINE(DELIGHT_VALGRIND) fi @@ -305,3 +318,4 @@ echo " - Mark deprecated attribute: $markdeprecated" echo " - Support string-output via snd_output: $output_buffer" echo " - Support floating-point: $support_float" echo " - Enable library ABI check: $abicheck" +echo " - Support ctl ASCII parser: $ctlasciiparser" diff --git a/src/control.c b/src/control.c index 4a7666f..1f19431 100644 --- a/src/control.c +++ b/src/control.c @@ -764,3 +764,126 @@ int snd_tlv_convert_from_dB(unsigned int *tlv, long rangemin, long rangemax, } #endif /* TLV */ + +#if SALSA_CTL_ASCII_PARSER +char *snd_ctl_ascii_elem_id_get(snd_ctl_elem_id_t *id) +{ + char buf[256]; + int len; + + len = snprintf(buf, sizeof(buf), "numid=%u,iface=%s,name='%s'", + id->numid, _snd_ctl_elem_iface_names[id->iface], + id->name); + if (len < sizeof(buf) && id->index > 0) + len += snprintf(buf + len, sizeof(buf) - len, + ",index=%d", id->index); + if (len < sizeof(buf) && id->device > 0) + len += snprintf(buf + len, sizeof(buf) - len, + ",device=%d", id->device); + if (len < sizeof(buf) && id->subdevice > 0) + len += snprintf(buf + len, sizeof(buf) - len, + ",subdevice=%d", id->subdevice); + return strdup(buf); +} + +int snd_ctl_ascii_elem_id_parse(snd_ctl_elem_id_t *dst, const char *str) +{ + char iface[20]; + char *p, *s = (char *)str; + int i; + + while ((p = strsep(&s, ",")) != NULL) { + if (sscanf(p, "iface=%20[^,]", iface) == 1) { + for (i = 0; i <= SND_CTL_ELEM_IFACE_LAST; i++) { + if (!strcmp(iface, + _snd_ctl_elem_iface_names[i])) { + dst->iface = i; + break; + } + } + if (i > SND_CTL_ELEM_IFACE_LAST) + return -EINVAL; + continue; + } + if (sscanf(p, "name='%42[^']", dst->name) == 1) + continue; + if (sscanf(p, "numid=%d", &dst->numid) == 1) + continue; + if (sscanf(p, "index=%d", &dst->index) == 1) + continue; + if (sscanf(p, "device=%d", &dst->device) == 1) + continue; + if (sscanf(p, "subdevice=%d", &dst->subdevice) == 1) + continue; + return -EINVAL; + } + return 0; +} + +static int match_yes(const char *ptr) +{ + static const char * const yes[] = { + "on", "up", "yes", "true", NULL, + }; + const char * const *p; + + for (p = yes; *p; p++) + if (strncasecmp(ptr, *p, strlen(*p))) + return 1; + return 0; +} + +static int get_enum_index(snd_ctl_t *handle, snd_ctl_elem_info_t *info, + const char *ptr) +{ + int i; + + for (i = 0; i < info->value.enumerated.items; i++) { + info->value.enumerated.item = i; + if (snd_ctl_elem_info(handle, info) < 0) + return -1; + if (!strncmp(ptr, info->value.enumerated.name, + strlen(info->value.enumerated.name))) + return i; + } + return -1; +} + +int snd_ctl_ascii_value_parse(snd_ctl_t *handle, + snd_ctl_elem_value_t *dst, + snd_ctl_elem_info_t *info, + const char *ptr) +{ + int idx = 0; + int tmp; + + for (idx = 0; idx < info->count && idx < 128 && *ptr; idx++) { + switch (info->type) { + case SND_CTL_ELEM_TYPE_BOOLEAN: + if (!strncasecmp(ptr, "toggle", 6)) + tmp = !dst->value.integer.value[idx]; + else if (match_yes(ptr) || *ptr == '1') + tmp = 1; + else + tmp = 0; + dst->value.integer.value[idx] = tmp; + break; + case SND_CTL_ELEM_TYPE_INTEGER: + dst->value.integer.value[idx] = strtol(ptr, NULL, 0); + break; + case SND_CTL_ELEM_TYPE_INTEGER64: + dst->value.integer.value[idx] = strtoll(ptr, NULL, 0); + break; + case SND_CTL_ELEM_TYPE_ENUMERATED: + tmp = get_enum_index(handle, info, ptr); + if (tmp < 0) + return -EINVAL; + dst->value.enumerated.item[idx] = tmp; + break; + } + while (*ptr && *ptr != ',') + ptr++; + } + return 0; +} +#endif /* SALSA_CTL_ASCII_PARSER */ diff --git a/src/recipe.h.in b/src/recipe.h.in index bbbdee3..620745f 100644 --- a/src/recipe.h.in +++ b/src/recipe.h.in @@ -31,6 +31,9 @@ /* Enable library ABI check */ #define SALSA_CHECK_ABI @SALSA_CHECK_ABI@ +/* Support ASCII value parser for ctl */ +#define SALSA_CTL_ASCII_PARSER @SALSA_CTL_ASCII_PARSER@ + /* Default device path prefix */ #define SALSA_DEVPATH "@DEVPATH@" |