[alsa-devel] [RFC][PATCH 0/5] alsa-lib: add APIs for control element set
Hi,
This patchset adds some APIs for control element set, according to design of ALSA Ctl core.
In ALSA Ctl core, each sound card can have control elements. The elements are managed according to below design.
* element set * A set of elements with the same attribute (i.e. name, get/put operations). * element * An element can be identified by userspace applications. * channel * An element has channels which can be changed by userspace applications or hardware device itself. * value * Each channel has its own value. The place to kept the value depends on design of each device driver (i.e. in hardware register or kernel space).
There're two ways to identify the element; by identification number (numid), or by a combination of name of the element set and index from the first element in the element set.
Both of device driver in kernel land and ALSA Ctl application in user land can add the element set. When userspace applications add them, ALSA Ctl core works as Inter Process Communication mechanism between event-listening applications and usual control applications. Such element is refered as 'user-defined control elements' in alsa-lib.
Typically, device driver in kernel land adds one element set for a single element. So users and userspace developers are hard to realize that an existence of the element set.
There're more items to describe the design. But here I focus on what relates to this patchset.
Well, current alsa-lib implementation includes small bugs, some misleadings, a lack of feature related to user-defined control elements. This patchset is my attempt to improves such issues.
Regards
Takashi Sakamoto (5): control: initialize element channel values according to identification number control: rename variables so that it represents the number of channels which an element has control: improve API documentation control: add a function to add an element of bytes type control: add functions to add element set
include/control.h | 35 +++- src/control/control.c | 484 +++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 413 insertions(+), 106 deletions(-)
In ALSA Ctl core, there're two ways to identify elements. One is by numid. Another is by name/index. The former way is lighter than the latter way.
In control API, after adding elements by snd_ctl_elem_add_integer() and snd_ctl_elem_add_integer64(), these functions manage to initialize value of each channel. When executing this operation, used ID information is still given by applications. Although, in this time, the element can be identified according to numid.
This commit uses the numid instead of name/index pair.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- src/control/control.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/control/control.c b/src/control/control.c index 328920d..691b69c 100644 --- a/src/control/control.c +++ b/src/control/control.c @@ -292,7 +292,7 @@ int snd_ctl_elem_add_integer(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, if (err < 0) return err; snd_ctl_elem_value_alloca(&val); - val->id = *id; + val->id = info->id; for (i = 0; i < count; i++) val->value.integer.value[i] = min; err = ctl->ops->element_write(ctl, val); @@ -330,7 +330,7 @@ int snd_ctl_elem_add_integer64(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, if (err < 0) return err; snd_ctl_elem_value_alloca(&val); - val->id = *id; + val->id = info->id; for (i = 0; i < count; i++) val->value.integer64.value[i] = min; err = ctl->ops->element_write(ctl, val);
An element has some channels which can be changed in a single operation. In control API, variables to represents the number of channels is described as 'count'. On the other hand, in ALSA Ctl core, the number of elements in an element set is also described as 'count'. They're a bit confusing.
This commit renames 'count' with 'channels'. The 'count' is reserved for future commit to describe the number of elements in an element set.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- src/control/control.c | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-)
diff --git a/src/control/control.c b/src/control/control.c index 691b69c..96dfbf6 100644 --- a/src/control/control.c +++ b/src/control/control.c @@ -264,14 +264,15 @@ int snd_ctl_elem_info(snd_ctl_t *ctl, snd_ctl_elem_info_t *info) * \brief Create and add an user INTEGER CTL element * \param ctl CTL handle * \param id CTL element id to add - * \param count number of elements + * \param channels number of elements * \param min minimum value * \param max maximum value * \param step value step * \return 0 on success otherwise a negative error code */ int snd_ctl_elem_add_integer(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, - unsigned int count, long min, long max, long step) + unsigned int channels, long min, long max, + long step) { snd_ctl_elem_info_t *info; snd_ctl_elem_value_t *val; @@ -284,7 +285,7 @@ int snd_ctl_elem_add_integer(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, info->type = SND_CTL_ELEM_TYPE_INTEGER; info->access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE; - info->count = count; + info->count = channels; info->value.integer.min = min; info->value.integer.max = max; info->value.integer.step = step; @@ -293,7 +294,7 @@ int snd_ctl_elem_add_integer(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, return err; snd_ctl_elem_value_alloca(&val); val->id = info->id; - for (i = 0; i < count; i++) + for (i = 0; i < channels; i++) val->value.integer.value[i] = min; err = ctl->ops->element_write(ctl, val); return err; @@ -303,15 +304,15 @@ int snd_ctl_elem_add_integer(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, * \brief Create and add an user INTEGER64 CTL element * \param ctl CTL handle * \param id CTL element id to add - * \param count number of elements + * \param channels number of elements * \param min minimum value * \param max maximum value * \param step value step * \return 0 on success otherwise a negative error code */ int snd_ctl_elem_add_integer64(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, - unsigned int count, long long min, long long max, - long long step) + unsigned int channels, long long min, + long long max, long long step) { snd_ctl_elem_info_t *info; snd_ctl_elem_value_t *val; @@ -322,7 +323,7 @@ int snd_ctl_elem_add_integer64(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, snd_ctl_elem_info_alloca(&info); info->id = *id; info->type = SND_CTL_ELEM_TYPE_INTEGER64; - info->count = count; + info->count = channels; info->value.integer64.min = min; info->value.integer64.max = max; info->value.integer64.step = step; @@ -331,7 +332,7 @@ int snd_ctl_elem_add_integer64(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, return err; snd_ctl_elem_value_alloca(&val); val->id = info->id; - for (i = 0; i < count; i++) + for (i = 0; i < channels; i++) val->value.integer64.value[i] = min; err = ctl->ops->element_write(ctl, val); return err; @@ -341,11 +342,11 @@ int snd_ctl_elem_add_integer64(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, * \brief Create and add an user BOOLEAN CTL element * \param ctl CTL handle * \param id CTL element id to add - * \param count number of elements + * \param channels number of elements * \return 0 on success otherwise a negative error code */ int snd_ctl_elem_add_boolean(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, - unsigned int count) + unsigned int channels) { snd_ctl_elem_info_t *info;
@@ -353,7 +354,7 @@ int snd_ctl_elem_add_boolean(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, snd_ctl_elem_info_alloca(&info); info->id = *id; info->type = SND_CTL_ELEM_TYPE_BOOLEAN; - info->count = count; + info->count = channels; info->value.integer.min = 0; info->value.integer.max = 1; return ctl->ops->element_add(ctl, info); @@ -363,7 +364,7 @@ int snd_ctl_elem_add_boolean(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, * \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] channels 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. @@ -380,9 +381,10 @@ int snd_ctl_elem_add_boolean(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, * \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>-EINVAL<dd>\a channels 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. @@ -392,7 +394,7 @@ int snd_ctl_elem_add_boolean(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, * 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, + unsigned int channels, unsigned int items, const char *const names[]) { snd_ctl_elem_info_t *info; @@ -405,7 +407,7 @@ int snd_ctl_elem_add_enumerated(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, snd_ctl_elem_info_alloca(&info); info->id = *id; info->type = SND_CTL_ELEM_TYPE_ENUMERATED; - info->count = count; + info->count = channels; info->value.enumerated.items = items;
bytes = 0;
Some parts of control API documentation are described with core-developer friendly representations. To usual developer, they have little meanings.
This commit improves such comments.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- src/control/control.c | 230 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 151 insertions(+), 79 deletions(-)
diff --git a/src/control/control.c b/src/control/control.c index 96dfbf6..3533ffe 100644 --- a/src/control/control.c +++ b/src/control/control.c @@ -261,14 +261,33 @@ int snd_ctl_elem_info(snd_ctl_t *ctl, snd_ctl_elem_info_t *info) }
/** - * \brief Create and add an user INTEGER CTL element - * \param ctl CTL handle - * \param id CTL element id to add - * \param channels number of elements - * \param min minimum value - * \param max maximum value - * \param step value step - * \return 0 on success otherwise a negative error code + * \brief Create and add an user-defined control element of integer type. + * \param[in] ctl CTL handle + * \param[in/out] id ID of the new control element. + * \param[in] channels The number of channels which a control element includes. + * \param[in] min Minimum value for the value of each channel. + * \param[in] max Maximum value for the value of each channel. + * \param[in] step The step of value for the value of each channel. + * \return Zero on success, otherwise a negative error code. + * + * This function creates a user control element. This control element is not + * controlled by device drivers in kernel, but can be handled by the same way as + * usual control elements added by the device drivers. + * + * The fields of \a id, except for numid, must be set with unique values to + * identify the new element. After returning, all fields of \a id are filled. + * + * All of channels in the new element are locked. The value of each channel is + * initialized with the minimum value. + * + * \par Errors: + * <dl> + * <dt>-EBUSY<dd>A control element with ID \a id already exists. + * <dt>-EINVAL<dd>ID has no name, or \a channels is not between 1 to 127. + * <dt>-ENOMEM<dd>Out of memory, or there are too many user control elements. + * <dt>-ENXIO<dd>This driver does not support (integer) user controls. + * <dt>-ENODEV<dd>Device unplugged. + * </dl> */ int snd_ctl_elem_add_integer(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, unsigned int channels, long min, long max, @@ -301,14 +320,33 @@ int snd_ctl_elem_add_integer(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, }
/** - * \brief Create and add an user INTEGER64 CTL element - * \param ctl CTL handle - * \param id CTL element id to add - * \param channels number of elements - * \param min minimum value - * \param max maximum value - * \param step value step - * \return 0 on success otherwise a negative error code + * \brief Create and add an user-defined control element of integer64 type. + * \param[in] ctl CTL handle + * \param[in/out] id ID of the new control element. + * \param[in] channels The number of channels which a control element includes. + * \param[in] min Minimum value for the value of each channel + * \param[in] max Maximum value for the value of each channel + * \param[in] step Step of value for the value of each channel + * \return Zero on success, otherwise a negative error code. + * + * This function creates a user control element. This control element is not + * controlled by device drivers in kernel, but can be handled by the same way as + * usual control elements added by the device drivers. + * + * The fields of \a id, except for numid, must be set with unique values to + * identify the new element. After returning, all fields of \a id are filled. + * + * All of channels in the new element are locked. The value of each channel is + * initialized with the minimum value. + * + * \par Errors: + * <dl> + * <dt>-EBUSY<dd>A control element with ID \a id already exists. + * <dt>-EINVAL<dd>ID has no name, or \a channels is not between 1 to 63. + * <dt>-ENOMEM<dd>Out of memory, or there are too many user control elements. + * <dt>-ENXIO<dd>This driver does not support (integer64) user controls. + * <dt>-ENODEV<dd>Device unplugged. + * </dl> */ int snd_ctl_elem_add_integer64(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, unsigned int channels, long long min, @@ -339,11 +377,29 @@ int snd_ctl_elem_add_integer64(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, }
/** - * \brief Create and add an user BOOLEAN CTL element - * \param ctl CTL handle - * \param id CTL element id to add - * \param channels number of elements - * \return 0 on success otherwise a negative error code + * \brief Create and add an user-defined control element of boolean type. + * \param[in] ctl CTL handle + * \param[in/out] id ID of the new control element. + * \param[in] channels The number of channels which a control element includes. + * + * This function creates a user control element. This control element is not + * controlled by device drivers in kernel, but can be handled by the same way as + * usual control elements added by the device drivers. + * + * The fields of \a id, except for numid, must be set with unique values to + * identify the new element. After returning, all fields of \a id are filled. + * + * All of channels in the new element are locked. The value of each channel is + * initialized with false. + * + * \par Errors: + * <dl> + * <dt>-EBUSY<dd>A control element with ID \a id already exists. + * <dt>-EINVAL<dd>ID has no name, or \a channels is not between 1 to 127. + * <dt>-ENOMEM<dd>Out of memory, or there are too many user control elements. + * <dt>-ENXIO<dd>This driver does not support (boolean) user controls. + * <dt>-ENODEV<dd>Device unplugged. + * </dl> */ int snd_ctl_elem_add_boolean(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, unsigned int channels) @@ -361,37 +417,37 @@ int snd_ctl_elem_add_boolean(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, }
/** - * \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] channels Number of element values. + * \brief Create and add a user-defined control element of enumerated type. + * \param[in] ctl CTL handle + * \param[in/out] id ID of the new control element. + * \param[in] channels The number of channels which a control element includes. * \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. + * This function creates a user control element. This control element is not + * controlled by device drivers in kernel, but can be handled by the same way as + * usual control elements added by the device drivers. * - * The fields of \a id, except numid, must be set to unique values that + * The fields of \a id, except for numid, must be set to unique values that * identify the new element. * - * The new element is locked; its value is initialized as zero. + * All of channels in the new element are locked. The value of each channel is + * initialized with the first entry of names. * * \par Errors: * <dl> * <dt>-EBUSY<dd>A control element with ID \a id already exists. - * <dt>-EINVAL<dd>\a channels 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>-EINVAL<dd>\a channels is not between 1 to 127, 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. + * This function is added in ALSA 1.0.25. */ int snd_ctl_elem_add_enumerated(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, unsigned int channels, unsigned int items, @@ -432,10 +488,26 @@ int snd_ctl_elem_add_enumerated(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, }
/** - * \brief Create and add an user IEC958 CTL element - * \param ctl CTL handle - * \param id CTL element info to add - * \return 0 on success otherwise a negative error code + * \brief Create and add a user-defined control element of IEC958 type. + * \param[in] ctl CTL handle + * \param[in/out] id ID of the new control element. + * + * This function creates a user control element, This control element is not + * controlled by device drivers in kernel but that is handled by the same way as + * the control elements added by the device drivers. + * + * The fields of \a id, except numid, must be set with unique values to identify + * the new element. After returning, all fields of \a id are filled. + * + * The channel in the new element is locked; the value is initialized with zero. + * + * \par Errors: + * <dl> + * <dt>-EBUSY<dd>A control element with ID \a id already exists. + * <dt>-ENOMEM<dd>Out of memory, or there are too many user control elements. + * <dt>-ENXIO<dd>This driver does not support (IEC958) user controls. + * <dt>-ENODEV<dd>Device unplugged. + * </dl> */ int snd_ctl_elem_add_iec958(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id) { @@ -2491,10 +2563,10 @@ void snd_ctl_elem_value_set_index(snd_ctl_elem_value_t *obj, unsigned int val) }
/** - * \brief Get value for an entry of a #SND_CTL_ELEM_TYPE_BOOLEAN CTL element id/value - * \param obj CTL element id/value - * \param idx Entry index - * \return value for the entry + * \brief Get value of a specified channel in the control element of boolean type. + * \param[in] ctl CTL handle + * \param[in] idx The index of channel in the control element + * \return value for specified channel */ int snd_ctl_elem_value_get_boolean(const snd_ctl_elem_value_t *obj, unsigned int idx) { @@ -2504,10 +2576,10 @@ int snd_ctl_elem_value_get_boolean(const snd_ctl_elem_value_t *obj, unsigned int }
/** - * \brief Get value for an entry of a #SND_CTL_ELEM_TYPE_INTEGER CTL element id/value - * \param obj CTL element id/value - * \param idx Entry index - * \return value for the entry + * \brief Get value of a specified channel in the control element of integer type. + * \param[in] ctl CTL handle + * \param[in] idx The index of channel in the control element + * \return value in specified channel */ long snd_ctl_elem_value_get_integer(const snd_ctl_elem_value_t *obj, unsigned int idx) { @@ -2517,10 +2589,10 @@ long snd_ctl_elem_value_get_integer(const snd_ctl_elem_value_t *obj, unsigned in }
/** - * \brief Get value for an entry of a #SND_CTL_ELEM_TYPE_INTEGER64 CTL element id/value - * \param obj CTL element id/value - * \param idx Entry index - * \return value for the entry + * \brief Get value of a specified channel in the control element of integer64 type. + * \param[in] ctl CTL handle + * \param[in] idx The index of channel in the control element + * \return value in specified channel */ long long snd_ctl_elem_value_get_integer64(const snd_ctl_elem_value_t *obj, unsigned int idx) { @@ -2530,10 +2602,10 @@ long long snd_ctl_elem_value_get_integer64(const snd_ctl_elem_value_t *obj, unsi }
/** - * \brief Get value for an entry of a #SND_CTL_ELEM_TYPE_ENUMERATED CTL element id/value - * \param obj CTL element id/value - * \param idx Entry index - * \return value for the entry + * \brief Get value of a specified channel in the control element of enumerated type. + * \param[in] ctl CTL handle + * \param[in] idx The index of channel in the control element + * \return value of specified channel */ unsigned int snd_ctl_elem_value_get_enumerated(const snd_ctl_elem_value_t *obj, unsigned int idx) { @@ -2543,10 +2615,10 @@ unsigned int snd_ctl_elem_value_get_enumerated(const snd_ctl_elem_value_t *obj, }
/** - * \brief Get value for an entry of a #SND_CTL_ELEM_TYPE_BYTES CTL element id/value - * \param obj CTL element id/value - * \param idx Entry index - * \return value for the entry + * \brief Get value of a specified channel in the control element of bytes type. + * \param[in] ctl CTL handle + * \param[in] idx The index of channel in the control element + * \return value of specified channel */ unsigned char snd_ctl_elem_value_get_byte(const snd_ctl_elem_value_t *obj, unsigned int idx) { @@ -2556,10 +2628,10 @@ unsigned char snd_ctl_elem_value_get_byte(const snd_ctl_elem_value_t *obj, unsig }
/** - * \brief Set value for an entry of a #SND_CTL_ELEM_TYPE_BOOLEAN CTL element id/value - * \param obj CTL element id/value - * \param idx Entry index - * \param val value for the entry + * \brief Get value of a specified channel in the control element of boolean type. + * \param[in] ctl CTL handle + * \param[in] idx The index of channel in the control element + * \return value of specified channel */ void snd_ctl_elem_value_set_boolean(snd_ctl_elem_value_t *obj, unsigned int idx, long val) { @@ -2569,10 +2641,10 @@ void snd_ctl_elem_value_set_boolean(snd_ctl_elem_value_t *obj, unsigned int idx, }
/** - * \brief Set value for an entry of a #SND_CTL_ELEM_TYPE_INTEGER CTL element id/value - * \param obj CTL element id/value - * \param idx Entry index - * \param val value for the entry + * \brief Set value of a specified channel in the control element of integer type. + * \param[in] ctl CTL handle + * \param[in] idx The index of channel in the control element + * \param[in] val The value to the specified channel */ void snd_ctl_elem_value_set_integer(snd_ctl_elem_value_t *obj, unsigned int idx, long val) { @@ -2582,10 +2654,10 @@ void snd_ctl_elem_value_set_integer(snd_ctl_elem_value_t *obj, unsigned int idx, }
/** - * \brief Set value for an entry of a #SND_CTL_ELEM_TYPE_INTEGER64 CTL element id/value - * \param obj CTL element id/value - * \param idx Entry index - * \param val value for the entry + * \brief Set value of a specified channel in the control element of integer64 type. + * \param[in] ctl CTL handle + * \param[in] idx The index of channel in the control element + * \param[in] val The value to the specified channel */ void snd_ctl_elem_value_set_integer64(snd_ctl_elem_value_t *obj, unsigned int idx, long long val) { @@ -2595,10 +2667,10 @@ void snd_ctl_elem_value_set_integer64(snd_ctl_elem_value_t *obj, unsigned int id }
/** - * \brief Set value for an entry of a #SND_CTL_ELEM_TYPE_ENUMERATED CTL element id/value - * \param obj CTL element id/value - * \param idx Entry index - * \param val value for the entry + * \brief Set value of a specified channel in the control element of enumerated type. + * \param[in] ctl CTL handle + * \param[in] idx The index of channel in the control element + * \param[in] val The value to the specified channel */ void snd_ctl_elem_value_set_enumerated(snd_ctl_elem_value_t *obj, unsigned int idx, unsigned int val) { @@ -2608,10 +2680,10 @@ void snd_ctl_elem_value_set_enumerated(snd_ctl_elem_value_t *obj, unsigned int i }
/** - * \brief Set value for an entry of a #SND_CTL_ELEM_TYPE_BYTES CTL element id/value - * \param obj CTL element id/value - * \param idx Entry index - * \param val value for the entry + * \brief Set value of a specified channel in the control element of bytes type. + * \param[in] ctl CTL handle + * \param[in] idx The index of channel in the control element + * \param[in] val The value to the specified channel */ void snd_ctl_elem_value_set_byte(snd_ctl_elem_value_t *obj, unsigned int idx, unsigned char val) {
ALSA Ctl core allows userspace applications to add elements of bytes type, while there's no APIs for this purpose in alsa-lib.
This commit adds the missing function.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- src/control/control.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+)
diff --git a/src/control/control.c b/src/control/control.c index 3533ffe..38d66e8 100644 --- a/src/control/control.c +++ b/src/control/control.c @@ -488,6 +488,51 @@ int snd_ctl_elem_add_enumerated(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, }
/** + * \brief Create and add a user-defined control element of bytes type. + * \param[in] ctl Control device handle. + * \param[in/out] id ID of the new control element. + * \param[in] channels The number of channels which one control element includes + * \return Zero on success, otherwise a negative error code. + * + * This function creates a user control element, This control element is not + * controlled by device drivers in kernel but that is handled by the same way as + * the control elements added by the device drivers. + * + * The fields of \a id, except numid, must be set with unique values to identify + * the new element. After returning, all fields of \a id are filled. + * + * All of channels in the new element are locked; these values are initialized + * with the minimum value. + * + * \par Errors: + * <dl> + * <dt>-EBUSY<dd>A control element with ID \a id already exists. + * <dt>-EINVAL<dd>\a channels is not between 1 to 511. + * <dt>-ENOMEM<dd>Out of memory, or there are too many user control elements. + * <dt>-ENXIO<dd>This driver does not support (bytes) user controls. + * <dt>-ENODEV<dd>Device unplugged. + * </dl> + * + * \par Compatibility: + * This function is added in ALSA 1.1.1. + */ +int snd_ctl_elem_add_bytes(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, + unsigned int channels) +{ + snd_ctl_elem_info_t *info; + + assert(ctl && id && id->name[0]); + + snd_ctl_elem_info_alloca(&info); + info->id = *id; + info->type = SND_CTL_ELEM_TYPE_BYTES; + info->owner = 1; + info->count = channels; + + return ctl->ops->element_add(ctl, info); +} + +/** * \brief Create and add a user-defined control element of IEC958 type. * \param[in] ctl CTL handle * \param[in/out] id ID of the new control element.
ALSA Ctl core allows userspace applications to add element sets. Currently, some APIs use the functionality to add a single element.
This commit adds functions to add element set for each type. Some existed functions are simple wrappers of the new ones to add one elements.
I note that some old APIs get static id variables, although Linux kernel 4.1 or later fills id field with all parameters. In this commit, old APIs are what they're to keep signature, while new APIs get non-static id parameters.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- include/control.h | 35 ++++++- src/control/control.c | 265 ++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 244 insertions(+), 56 deletions(-)
diff --git a/include/control.h b/include/control.h index 5fdf379..40a2de0 100644 --- a/include/control.h +++ b/include/control.h @@ -423,11 +423,38 @@ void snd_ctl_elem_info_set_subdevice(snd_ctl_elem_info_t *obj, unsigned int val) void snd_ctl_elem_info_set_name(snd_ctl_elem_info_t *obj, const char *val); 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_integer_set(snd_ctl_t *ctl, snd_ctl_elem_id_t *id, + unsigned int count, unsigned int channels, + long min, long max, long step); +int snd_ctl_elem_add_integer64_set(snd_ctl_t *ctl, snd_ctl_elem_id_t *id, + unsigned int count, unsigned int channels, + long long min, long long max, + long long step); +int snd_ctl_elem_add_boolean_set(snd_ctl_t *ctl, snd_ctl_elem_id_t *id, + unsigned int count, unsigned int channels); +int snd_ctl_elem_add_enumerated_set(snd_ctl_t *ctl, snd_ctl_elem_id_t *id, + unsigned int count, unsigned int channels, + unsigned int items, + const char *const names[]); +int snd_ctl_elem_add_bytes_set(snd_ctl_t *ctl, snd_ctl_elem_id_t *id, + unsigned int count, unsigned int channels); + +int snd_ctl_elem_add_integer(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, + unsigned int channels, + long min, long max, long step); +int snd_ctl_elem_add_integer64(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, + unsigned int channels, + long long min, long long max, long long step); +int snd_ctl_elem_add_boolean(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, + unsigned int channels); +int snd_ctl_elem_add_enumerated(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, + unsigned int channels, unsigned int items, + const char *const names[]); +int snd_ctl_elem_add_bytes(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, + unsigned int channels); 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);
size_t snd_ctl_elem_value_sizeof(void); diff --git a/src/control/control.c b/src/control/control.c index 38d66e8..1c20cd1 100644 --- a/src/control/control.c +++ b/src/control/control.c @@ -261,23 +261,25 @@ int snd_ctl_elem_info(snd_ctl_t *ctl, snd_ctl_elem_info_t *info) }
/** - * \brief Create and add an user-defined control element of integer type. + * \brief Create and add some user-defined control elements of integer type. * \param[in] ctl CTL handle * \param[in/out] id ID of the new control element. + * \param[in] count The number of control elements added by this operation. * \param[in] channels The number of channels which a control element includes. * \param[in] min Minimum value for the value of each channel. * \param[in] max Maximum value for the value of each channel. * \param[in] step The step of value for the value of each channel. * \return Zero on success, otherwise a negative error code. * - * This function creates a user control element. This control element is not - * controlled by device drivers in kernel, but can be handled by the same way as - * usual control elements added by the device drivers. + * This function creates some user control elements. These control elements are + * not controlled by device drivers in kernel, but can be handled by the same + * way as usual control elements added by the device drivers. * * The fields of \a id, except for numid, must be set with unique values to - * identify the new element. After returning, all fields of \a id are filled. + * identify the first new element. After returning, all fields of \a id are + * filled. * - * All of channels in the new element are locked. The value of each channel is + * All of channels in the new elements are locked. The value of each channel is * initialized with the minimum value. * * \par Errors: @@ -288,103 +290,145 @@ int snd_ctl_elem_info(snd_ctl_t *ctl, snd_ctl_elem_info_t *info) * <dt>-ENXIO<dd>This driver does not support (integer) user controls. * <dt>-ENODEV<dd>Device unplugged. * </dl> + * + * \par Compatibility: + * This function is added in ALSA 1.1.1. */ -int snd_ctl_elem_add_integer(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, - unsigned int channels, long min, long max, - long step) +int snd_ctl_elem_add_integer_set(snd_ctl_t *ctl, snd_ctl_elem_id_t *id, + unsigned int count, unsigned int channels, + long min, long max, long step) { snd_ctl_elem_info_t *info; snd_ctl_elem_value_t *val; unsigned int i; + unsigned int j; + unsigned int numid; int err;
assert(ctl && id && id->name[0]); + snd_ctl_elem_info_alloca(&info); info->id = *id; info->type = SND_CTL_ELEM_TYPE_INTEGER; info->access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE; + info->owner = count; info->count = channels; info->value.integer.min = min; info->value.integer.max = max; info->value.integer.step = step; + err = ctl->ops->element_add(ctl, info); if (err < 0) return err; + numid = snd_ctl_elem_id_get_numid(&info->id); + + /* Set initial value to all of chanenls in all of control elements. */ snd_ctl_elem_value_alloca(&val); val->id = info->id; - for (i = 0; i < channels; i++) - val->value.integer.value[i] = min; - err = ctl->ops->element_write(ctl, val); - return err; + for (i = 0; i < count; i++) { + snd_ctl_elem_id_set_numid(&val->id, numid + i); + + for (j = 0; j < channels; j++) + val->value.integer.value[j] = min; + + err = ctl->ops->element_write(ctl, val); + if (err < 0) + return err; + } + + *id = info->id; + return 0; }
/** - * \brief Create and add an user-defined control element of integer64 type. + * \brief Create and add some user-defined control elements of integer64 type. * \param[in] ctl CTL handle * \param[in/out] id ID of the new control element. + * \param[in] count The number of control elements added by this operation. * \param[in] channels The number of channels which a control element includes. * \param[in] min Minimum value for the value of each channel * \param[in] max Maximum value for the value of each channel * \param[in] step Step of value for the value of each channel * \return Zero on success, otherwise a negative error code. * - * This function creates a user control element. This control element is not - * controlled by device drivers in kernel, but can be handled by the same way as - * usual control elements added by the device drivers. + * This function creates some user control element. These control elements are + * not controlled by device drivers in kernel, but can be handled by the same + * way as usual control elements added by the device drivers. * * The fields of \a id, except for numid, must be set with unique values to * identify the new element. After returning, all fields of \a id are filled. * - * All of channels in the new element are locked. The value of each channel is + * All of channels in the new elements are locked. The value of each channel is * initialized with the minimum value. * * \par Errors: * <dl> * <dt>-EBUSY<dd>A control element with ID \a id already exists. - * <dt>-EINVAL<dd>ID has no name, or \a channels is not between 1 to 63. + * <dt>-EINVAL<dd>ID has no name, or \a channels is not between 1 to 127. * <dt>-ENOMEM<dd>Out of memory, or there are too many user control elements. - * <dt>-ENXIO<dd>This driver does not support (integer64) user controls. + * <dt>-ENXIO<dd>This driver does not support (integer) user controls. * <dt>-ENODEV<dd>Device unplugged. * </dl> + * + * \par Compatibility: + * This function is added in ALSA 1.1.1. */ -int snd_ctl_elem_add_integer64(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, - unsigned int channels, long long min, - long long max, long long step) +int snd_ctl_elem_add_integer64_set(snd_ctl_t *ctl, snd_ctl_elem_id_t *id, + unsigned int count, unsigned int channels, + long long min, long long max, long long step) { snd_ctl_elem_info_t *info; snd_ctl_elem_value_t *val; unsigned int i; + unsigned int j; + unsigned int numid; int err;
assert(ctl && id && id->name[0]); + snd_ctl_elem_info_alloca(&info); info->id = *id; info->type = SND_CTL_ELEM_TYPE_INTEGER64; + info->owner = count; info->count = channels; info->value.integer64.min = min; info->value.integer64.max = max; info->value.integer64.step = step; + err = ctl->ops->element_add(ctl, info); if (err < 0) return err; + numid = snd_ctl_elem_id_get_numid(&info->id); + + /* Set initial value to all of chanenls in all of control elements. */ snd_ctl_elem_value_alloca(&val); val->id = info->id; - for (i = 0; i < channels; i++) - val->value.integer64.value[i] = min; - err = ctl->ops->element_write(ctl, val); - return err; + for (i = 0; i < count; i++) { + snd_ctl_elem_id_set_numid(&val->id, numid + i); + + for (j = 0; j < channels; j++) + val->value.integer64.value[i] = min; + + err = ctl->ops->element_write(ctl, val); + if (err < 0) + return err; + } + + *id = info->id; + return 0; }
/** - * \brief Create and add an user-defined control element of boolean type. + * \brief Create and add some user-defined control elements of boolean type. * \param[in] ctl CTL handle * \param[in/out] id ID of the new control element. + * \param[in] count The number of control elements added by this operation. * \param[in] channels The number of channels which a control element includes. * - * This function creates a user control element. This control element is not - * controlled by device drivers in kernel, but can be handled by the same way as - * usual control elements added by the device drivers. + * This function creates some user control elements. These control elements are + * not controlled by device drivers in kernel, but can be handled by the same + * way as usual control elements added by the device drivers. * * The fields of \a id, except for numid, must be set with unique values to * identify the new element. After returning, all fields of \a id are filled. @@ -400,34 +444,46 @@ int snd_ctl_elem_add_integer64(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, * <dt>-ENXIO<dd>This driver does not support (boolean) user controls. * <dt>-ENODEV<dd>Device unplugged. * </dl> + * + * \par Compatibility: + * This function is added in ALSA 1.1.1. */ -int snd_ctl_elem_add_boolean(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, - unsigned int channels) +int snd_ctl_elem_add_boolean_set(snd_ctl_t *ctl, snd_ctl_elem_id_t *id, + unsigned int count, unsigned int channels) { snd_ctl_elem_info_t *info; + int err;
assert(ctl && id && id->name[0]); + snd_ctl_elem_info_alloca(&info); info->id = *id; info->type = SND_CTL_ELEM_TYPE_BOOLEAN; + info->owner = count; info->count = channels; info->value.integer.min = 0; info->value.integer.max = 1; - return ctl->ops->element_add(ctl, info); + + err = ctl->ops->element_add(ctl, info); + if (err >= 0) + *id = info->id; + + return err; }
/** - * \brief Create and add a user-defined control element of enumerated type. + * \brief Create and add some user-defined control elements of enumerated type. * \param[in] ctl CTL handle * \param[in/out] id ID of the new control element. + * \param[in] count The number of control elements added by this operation. * \param[in] channels The number of channels which a control element includes. * \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 control element. This control element is not - * controlled by device drivers in kernel, but can be handled by the same way as - * usual control elements added by the device drivers. + * This function creates some user control elements. These control elements are + * not controlled by device drivers in kernel, but can be handled by the same + * way as usual control elements added by the device drivers. * * The fields of \a id, except for numid, must be set to unique values that * identify the new element. @@ -447,11 +503,12 @@ int snd_ctl_elem_add_boolean(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, * </dl> * * \par Compatibility: - * This function is added in ALSA 1.0.25. + * This function is added in ALSA 1.1.1. */ -int snd_ctl_elem_add_enumerated(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, - unsigned int channels, unsigned int items, - const char *const names[]) +int snd_ctl_elem_add_enumerated_set(snd_ctl_t *ctl, snd_ctl_elem_id_t *id, + unsigned int count, unsigned int channels, + unsigned int items, + const char *const names[]) { snd_ctl_elem_info_t *info; unsigned int i, bytes; @@ -463,6 +520,7 @@ int snd_ctl_elem_add_enumerated(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, snd_ctl_elem_info_alloca(&info); info->id = *id; info->type = SND_CTL_ELEM_TYPE_ENUMERATED; + info->owner = count; info->count = channels; info->value.enumerated.items = items;
@@ -481,6 +539,8 @@ int snd_ctl_elem_add_enumerated(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, }
err = ctl->ops->element_add(ctl, info); + if (err >= 0) + *id = info->id;
free(buf);
@@ -488,20 +548,22 @@ int snd_ctl_elem_add_enumerated(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, }
/** - * \brief Create and add a user-defined control element of bytes type. + * \brief Create and add some user-defined control elements of bytes type. * \param[in] ctl Control device handle. * \param[in/out] id ID of the new control element. + * \param[in] count The number of control elements added by this operation. * \param[in] channels The number of channels which one control element includes * \return Zero on success, otherwise a negative error code. * - * This function creates a user control element, This control element is not - * controlled by device drivers in kernel but that is handled by the same way as - * the control elements added by the device drivers. + * This function creates some user control elements, These control elements are + * not controlled by device drivers in kernel but that is handled by the same + * way as the control elements added by the device drivers. * * The fields of \a id, except numid, must be set with unique values to identify - * the new element. After returning, all fields of \a id are filled. + * first element of the new control elements. After returning, all fields of \a + * id are filled for the first element. * - * All of channels in the new element are locked; these values are initialized + * All of channels in the new elements are locked; these values are initialized * with the minimum value. * * \par Errors: @@ -516,20 +578,119 @@ int snd_ctl_elem_add_enumerated(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, * \par Compatibility: * This function is added in ALSA 1.1.1. */ -int snd_ctl_elem_add_bytes(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, - unsigned int channels) +int snd_ctl_elem_add_bytes_set(snd_ctl_t *ctl, snd_ctl_elem_id_t *id, + unsigned int count, unsigned int channels) { snd_ctl_elem_info_t *info; + int err;
assert(ctl && id && id->name[0]);
snd_ctl_elem_info_alloca(&info); info->id = *id; info->type = SND_CTL_ELEM_TYPE_BYTES; - info->owner = 1; + info->owner = count; info->count = channels;
- return ctl->ops->element_add(ctl, info); + err = ctl->ops->element_add(ctl, info); + if (err >= 0) + *id = info->id; + + return err; +} + +/** + * \brief Create and add an user-defined control element of integer type. + * + * This function is a wrapper function to snd_ctl_elem_add_integer_set() for + * single control element. + */ +int snd_ctl_elem_add_integer(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, + unsigned int channels, + long min, long max, long step) +{ + snd_ctl_elem_id_t *local_id; + + snd_ctl_elem_id_alloca(&local_id); + *local_id = *id; + + return snd_ctl_elem_add_integer_set(ctl, local_id, 1, channels, + min, max, step); +} + +/** + * \brief Create and add an user-defined control element of integer64 type. + * + * This function is a wrapper function to snd_ctl_elem_add_integer64_set() for + * single control element. + */ +int snd_ctl_elem_add_integer64(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, + unsigned int channels, + long long min, long long max, long long step) +{ + snd_ctl_elem_id_t *local_id; + + snd_ctl_elem_id_alloca(&local_id); + *local_id = *id; + + return snd_ctl_elem_add_integer64_set(ctl, local_id, 1, channels, + min, max, step); +} + +/** + * \brief Create and add an user-defined control element of boolean type. + * + * This function is a wrapper function to snd_ctl_elem_add_boolean_set() for + * single control element. + */ +int snd_ctl_elem_add_boolean(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, + unsigned int channels) +{ + snd_ctl_elem_id_t *local_id; + + snd_ctl_elem_id_alloca(&local_id); + *local_id = *id; + + return snd_ctl_elem_add_boolean_set(ctl, local_id, 1, channels); +} + +/** + * \brief Create and add a user-defined control element of enumerated type. + * + * This function is a wrapper function to snd_ctl_elem_add_enumerated_set() for + * single control element. + */ +int snd_ctl_elem_add_enumerated(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, + unsigned int channels, unsigned int items, + const char *const names[]) +{ + snd_ctl_elem_id_t *local_id; + + snd_ctl_elem_id_alloca(&local_id); + *local_id = *id; + + return snd_ctl_elem_add_enumerated_set(ctl, local_id, 1, channels, + items, names); +} + +/** + * \brief Create and add a user-defined control element of bytes type. + * + * This function is a wrapper function to snd_ctl_elem_add_bytes_set() for + * single control element. + * + * \par Compatibility: + * This function is added in ALSA 1.1.1. + */ +int snd_ctl_elem_add_bytes(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, + unsigned int channels) +{ + snd_ctl_elem_id_t *local_id; + + snd_ctl_elem_id_alloca(&local_id); + *local_id = *id; + + return snd_ctl_elem_add_bytes_set(ctl, local_id, 1, channels); }
/**
participants (1)
-
Takashi Sakamoto