ctl: change former APIs as wrapper functions of element set APIs

In former commit, userspace library gets some APIs for element set. Some
existed functions can be simple wrappers of them.

This commit changes these APIs as wrapper functions. Additionally, this
commit also adds local variables for identical information of elements.
This modification is important to keep API consistency.

Some old APIs to add an element have id variables with const type
qualifier, while some new APIs to add element set changes the content of
given parameters. This comes from a change in Linux kernel 4.1.

In this commit [1], in-kernel implementation fills all fields of identical
data in userspace. As a result, when adding a new element set, userspace
applications can get an identical data for the first element in the set.
This lost the semantics of const type qualifier in userspace.

[1] http://git.kernel.org/cgit/linux/kernel/git/tiwai/sound.git/commit/sound/core?id=cab2ed7474bffafd2a68a885e03b85526194abcd

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
Takashi Sakamoto 2016-06-15 23:57:41 +09:00 committed by Takashi Iwai
parent de23b0e6e6
commit 1680ea4768

View file

@ -673,172 +673,83 @@ int snd_ctl_elem_add_bytes_set(snd_ctl_t *ctl, snd_ctl_elem_id_t *id,
} }
/** /**
* \brief Create and add an user INTEGER CTL element * \brief Create and add an user-defined control element of integer type.
* \param ctl CTL handle *
* \param id CTL element id to add * This is a wrapper function to snd_ctl_elem_add_integer_set() for a control
* \param count number of elements * element. This doesn't fill the id data with full information, thus it's
* \param min minimum value * recommended to use snd_ctl_elem_add_integer_set(), instead.
* \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, 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 member_count,
long min, long max, long step)
{ {
snd_ctl_elem_info_t *info; snd_ctl_elem_id_t *local_id;
snd_ctl_elem_value_t *val;
unsigned int i;
int err;
assert(ctl && id && id->name[0]); snd_ctl_elem_id_alloca(&local_id);
snd_ctl_elem_info_alloca(&info); *local_id = *id;
info->id = *id;
info->type = SND_CTL_ELEM_TYPE_INTEGER; return snd_ctl_elem_add_integer_set(ctl, local_id, 1, member_count,
info->access = SNDRV_CTL_ELEM_ACCESS_READWRITE | min, max, step);
SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE;
info->count = count;
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;
snd_ctl_elem_value_alloca(&val);
val->id = info->id;
for (i = 0; i < count; i++)
val->value.integer.value[i] = min;
err = ctl->ops->element_write(ctl, val);
return err;
} }
/** /**
* \brief Create and add an user INTEGER64 CTL element * \brief Create and add an user-defined control element of integer64 type.
* \param ctl CTL handle *
* \param id CTL element id to add * This is a wrapper function to snd_ctl_elem_add_integer64_set() for a single
* \param count number of elements * control element. This doesn't fill the id data with full information, thus
* \param min minimum value * it's recommended to use snd_ctl_elem_add_integer64_set(), instead.
* \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, 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, unsigned int member_count,
long long step) long long min, long long max, long long step)
{ {
snd_ctl_elem_info_t *info; snd_ctl_elem_id_t *local_id;
snd_ctl_elem_value_t *val;
unsigned int i;
int err;
assert(ctl && id && id->name[0]); snd_ctl_elem_id_alloca(&local_id);
snd_ctl_elem_info_alloca(&info); *local_id = *id;
info->id = *id;
info->type = SND_CTL_ELEM_TYPE_INTEGER64; return snd_ctl_elem_add_integer64_set(ctl, local_id, 1, member_count,
info->count = count; min, max, step);
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;
snd_ctl_elem_value_alloca(&val);
val->id = info->id;
for (i = 0; i < count; i++)
val->value.integer64.value[i] = min;
err = ctl->ops->element_write(ctl, val);
return err;
} }
/** /**
* \brief Create and add an user BOOLEAN CTL element * \brief Create and add an user-defined control element of boolean type.
* \param ctl CTL handle *
* \param id CTL element id to add * This is a wrapper function to snd_ctl_elem_add_boolean_set() for a single
* \param count number of elements * control element. This doesn't fill the id data with full information, thus
* \return 0 on success otherwise a negative error code * it's recommended to use snd_ctl_elem_add_boolean_set(), instead.
*/ */
int snd_ctl_elem_add_boolean(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, int snd_ctl_elem_add_boolean(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id,
unsigned int count) unsigned int member_count)
{ {
snd_ctl_elem_info_t *info; snd_ctl_elem_id_t *local_id;
assert(ctl && id && id->name[0]); snd_ctl_elem_id_alloca(&local_id);
snd_ctl_elem_info_alloca(&info); *local_id = *id;
info->id = *id;
info->type = SND_CTL_ELEM_TYPE_BOOLEAN; return snd_ctl_elem_add_boolean_set(ctl, local_id, 1, member_count);
info->count = count;
info->value.integer.min = 0;
info->value.integer.max = 1;
return ctl->ops->element_add(ctl, info);
} }
/** /**
* \brief Create and add a user-defined control element of type enumerated. * \brief Create and add a user-defined control element of enumerated type.
* \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 * This is a wrapper function to snd_ctl_elem_add_enumerated_set() for a single
* controlled by the control device's driver but that is just stored together * control element. This doesn't fill the id data with full information, thus
* with the other elements of \a ctl. * it's recommended to use snd_ctl_elem_add_enumerated_set(), instead.
* *
* The fields of \a id, except numid, must be set to unique values that * This function is added in version 1.0.25.
* 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, 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 member_count, unsigned int items,
const char *const names[]) const char *const labels[])
{ {
snd_ctl_elem_info_t *info; snd_ctl_elem_id_t *local_id;
unsigned int i, bytes;
char *buf, *p;
int err;
assert(ctl && id && id->name[0] && names); snd_ctl_elem_id_alloca(&local_id);
*local_id = *id;
snd_ctl_elem_info_alloca(&info); return snd_ctl_elem_add_enumerated_set(ctl, local_id, 1, member_count,
info->id = *id; items, labels);
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 = bytes ? malloc(bytes) : NULL;
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) {
strcpy(p, names[i]);
p += strlen(names[i]) + 1;
}
err = ctl->ops->element_add(ctl, info);
free(buf);
return err;
} }
/** /**