From: Clemens Ladisch Date: Fri, 7 Oct 2011 20:46:51 +0000 (+0200) Subject: control: add snd_ctl_elem_add_enumerated() X-Git-Tag: v1.0.25~8 X-Git-Url: https://git.alsa-project.org/?a=commitdiff_plain;h=15c6f832968c1f69a7c744f7051e4fc622acd62f;p=alsa-lib.git control: add snd_ctl_elem_add_enumerated() 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 --- diff --git a/include/control.h b/include/control.h index f265e349..488629d9 100644 --- a/include/control.h +++ b/include/control.h @@ -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); diff --git a/include/sound/asound.h b/include/sound/asound.h index 5dddd87d..07c03faa 100644 --- a/include/sound/asound.h +++ b/include/sound/asound.h @@ -26,10 +26,10 @@ #if defined(LINUX) || defined(__LINUX__) || defined(__linux__) #include +#include #ifdef __KERNEL__ -#include #include #include @@ -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; diff --git a/src/control/control.c b/src/control/control.c index cd17c6f4..a0965c6c 100644 --- a/src/control/control.c +++ b/src/control/control.c @@ -42,6 +42,7 @@ and IEC958 structure. #include #include +#include #include #include #include @@ -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: + *
+ *
-EBUSY
A control element with ID \a id already exists. + *
-EINVAL
\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. + *
-ENOMEM
Out of memory, or there are too many user control elements. + *
-ENXIO
This driver does not support (enumerated) user controls. + *
-ENODEV
Device unplugged. + *
+ * + * \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 diff --git a/src/control/control_hw.c b/src/control/control_hw.c index 16c4987d..1920c99a 100644 --- a/src/control/control_hw.c +++ b/src/control/control_hw.c @@ -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;