]> git.alsa-project.org Git - alsa-lib.git/commitdiff
control: add snd_ctl_elem_add_enumerated()
authorClemens Ladisch <clemens@ladisch.de>
Fri, 7 Oct 2011 20:46:51 +0000 (22:46 +0200)
committerClemens Ladisch <clemens@ladisch.de>
Fri, 7 Oct 2011 21:38:55 +0000 (23:38 +0200)
Handling of user control elements was implemented for all types except
BYTES and ENUMERATED.  Enumerated user controls will be needed for the
device-specific mixers of upcoming FireWire drivers.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
include/control.h
include/sound/asound.h
src/control/control.c
src/control/control_hw.c

index f265e349443785a3a72655d67dae6ab204296c36..488629d9f3decaa1f96ee50ff086e3deaf050a4f 100644 (file)
@@ -418,6 +418,7 @@ void snd_ctl_elem_info_set_index(snd_ctl_elem_info_t *obj, unsigned int val);
 int snd_ctl_elem_add_integer(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, unsigned int count, long imin, long imax, long istep);
 int snd_ctl_elem_add_integer64(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, unsigned int count, long long imin, long long imax, long long istep);
 int snd_ctl_elem_add_boolean(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, unsigned int count);
+int snd_ctl_elem_add_enumerated(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, unsigned int count, unsigned int items, const char *const names[]);
 int snd_ctl_elem_add_iec958(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id);
 int snd_ctl_elem_remove(snd_ctl_t *ctl, snd_ctl_elem_id_t *id);
 
index 5dddd87d07756936cf4769ab57439903b1df6a66..07c03faa16f2bc9ab8bcfc10d51660f51c8ce454 100644 (file)
 #if defined(LINUX) || defined(__LINUX__) || defined(__linux__)
 
 #include <linux/ioctl.h>
+#include <linux/types.h>
 
 #ifdef __KERNEL__
 
-#include <linux/types.h>
 #include <linux/time.h>
 #include <asm/byteorder.h>
 
@@ -734,7 +734,7 @@ struct sndrv_timer_tread {
  *                                                                          *
  ****************************************************************************/
 
-#define SNDRV_CTL_VERSION              SNDRV_PROTOCOL_VERSION(2, 0, 6)
+#define SNDRV_CTL_VERSION              SNDRV_PROTOCOL_VERSION(2, 0, 7)
 
 struct sndrv_ctl_card_info {
        int card;                       /* card number */
@@ -833,6 +833,8 @@ struct sndrv_ctl_elem_info {
                        unsigned int items;     /* R: number of items */
                        unsigned int item;      /* W: item number */
                        char name[64];          /* R: value name */
+                       __u64 names_ptr;        /* W: names list (ELEM_ADD only) */
+                       unsigned int names_length;
                } enumerated;
                unsigned char reserved[128];
        } value;
index cd17c6f4efe7d9b50329fa5cc37d4094a12364b9..a0965c6c901f8979cb1ebaaa54cb4a7979b1ae90 100644 (file)
@@ -42,6 +42,7 @@ and IEC958 structure.
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <stdint.h>
 #include <stdarg.h>
 #include <unistd.h>
 #include <string.h>
@@ -358,6 +359,74 @@ int snd_ctl_elem_add_boolean(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id,
        return ctl->ops->element_add(ctl, info);
 }
 
+/**
+ * \brief Create and add a user-defined control element of type enumerated.
+ * \param[in] ctl Control device handle.
+ * \param[in] id ID of the new control element.
+ * \param[in] count Number of element values.
+ * \param[in] items Range of possible values (0 ... \a items - 1).
+ * \param[in] names An array containing \a items strings.
+ * \return Zero on success, otherwise a negative error code.
+ *
+ * This function creates a user element, i.e., a control element that is not
+ * controlled by the control device's driver but that is just stored together
+ * with the other elements of \a ctl.
+ *
+ * The fields of \a id, except numid, must be set to unique values that
+ * identify the new element.
+ *
+ * The new element is locked; its value is initialized as zero.
+ *
+ * \par Errors:
+ * <dl>
+ * <dt>-EBUSY<dd>A control element with ID \a id already exists.
+ * <dt>-EINVAL<dd>\a count is not at least one or greater than 128, or \a items
+ *     is not at least one, or a string in \a names is empty or longer than 63
+ *     bytes, or the strings in \a names require more than 64 KB storage.
+ * <dt>-ENOMEM<dd>Out of memory, or there are too many user control elements.
+ * <dt>-ENXIO<dd>This driver does not support (enumerated) user controls.
+ * <dt>-ENODEV<dd>Device unplugged.
+ * </dl>
+ *
+ * \par Compatibility:
+ * snd_ctl_elem_add_enumerated() was introduced in ALSA 1.0.25.
+ */
+int snd_ctl_elem_add_enumerated(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id,
+                               unsigned int count, unsigned int items,
+                               const char *const names[])
+{
+       snd_ctl_elem_info_t *info;
+       unsigned int i, bytes;
+       char *buf, *p;
+       int err;
+
+       assert(ctl && id && id->name[0] && names);
+
+       snd_ctl_elem_info_alloca(&info);
+       info->id = *id;
+       info->type = SND_CTL_ELEM_TYPE_ENUMERATED;
+       info->count = count;
+       info->value.enumerated.items = items;
+
+       bytes = 0;
+       for (i = 0; i < items; ++i)
+               bytes += strlen(names[i]) + 1;
+       buf = malloc(bytes);
+       if (!buf)
+               return -ENOMEM;
+       info->value.enumerated.names_ptr = (uintptr_t)buf;
+       info->value.enumerated.names_length = bytes;
+       p = buf;
+       for (i = 0; i < items; ++i)
+               p = stpcpy(p, names[i]) + 1;
+
+       err = ctl->ops->element_add(ctl, info);
+
+       free(buf);
+
+       return err;
+}
+
 /**
  * \brief Create and add an user IEC958 CTL element
  * \param ctl CTL handle
index 16c4987d2e9c2e42ff90c8fbb0d0636f3a6959f5..1920c99a5ad3c5c34dafe7dd2c2f51bb801dea5c 100644 (file)
@@ -148,6 +148,11 @@ static int snd_ctl_hw_elem_info(snd_ctl_t *handle, snd_ctl_elem_info_t *info)
 static int snd_ctl_hw_elem_add(snd_ctl_t *handle, snd_ctl_elem_info_t *info)
 {
        snd_ctl_hw_t *hw = handle->private_data;
+
+       if (info->type == SNDRV_CTL_ELEM_TYPE_ENUMERATED &&
+           hw->protocol < SNDRV_PROTOCOL_VERSION(2, 0, 7))
+               return -ENXIO;
+
        if (ioctl(hw->fd, SNDRV_CTL_IOCTL_ELEM_ADD, info) < 0)
                return -errno;
        return 0;
@@ -156,6 +161,11 @@ static int snd_ctl_hw_elem_add(snd_ctl_t *handle, snd_ctl_elem_info_t *info)
 static int snd_ctl_hw_elem_replace(snd_ctl_t *handle, snd_ctl_elem_info_t *info)
 {
        snd_ctl_hw_t *hw = handle->private_data;
+
+       if (info->type == SNDRV_CTL_ELEM_TYPE_ENUMERATED &&
+           hw->protocol < SNDRV_PROTOCOL_VERSION(2, 0, 7))
+               return -ENXIO;
+
        if (ioctl(hw->fd, SNDRV_CTL_IOCTL_ELEM_REPLACE, info) < 0)
                return -errno;
        return 0;