aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2015-06-01 16:18:25 +0200
committerTakashi Iwai <tiwai@suse.de>2015-06-01 16:21:01 +0200
commit504c7cf80cfdeaaf2391f76ebf1cafa97bf55ccc (patch)
tree3d0ab711c581a9da0273788b1892e87dadce7854
parenteeccbe15bd16dff8adb2edbba654c9f543e4a4d7 (diff)
downloadsalsa-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.ac14
-rw-r--r--src/control.c123
-rw-r--r--src/recipe.h.in3
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@"