mirror of
https://gitee.com/openharmony/third_party_alsa-lib
synced 2024-11-23 07:30:32 +00:00
added the handling of enum controls to simple mixer API.
the following functions are added: int snd_mixer_selem_is_enumerated() int snd_mixer_selem_get_enum_items() int snd_mixer_selem_get_enum_item_name() int snd_mixer_selem_get_enum_item() int snd_mixer_selem_set_enum_item()
This commit is contained in:
parent
52237f3542
commit
c25879f9d9
@ -192,6 +192,12 @@ void snd_mixer_selem_get_capture_volume_range(snd_mixer_elem_t *elem,
|
||||
void snd_mixer_selem_set_capture_volume_range(snd_mixer_elem_t *elem,
|
||||
long min, long max);
|
||||
|
||||
int snd_mixer_selem_is_enumerated(snd_mixer_elem_t *elem);
|
||||
int snd_mixer_selem_get_enum_items(snd_mixer_elem_t *elem);
|
||||
int snd_mixer_selem_get_enum_item_name(snd_mixer_elem_t *elem, unsigned int idx, size_t maxlen, char *str);
|
||||
int snd_mixer_selem_get_enum_item(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, unsigned int *idxp);
|
||||
int snd_mixer_selem_set_enum_item(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, unsigned int idx);
|
||||
|
||||
size_t snd_mixer_selem_id_sizeof(void);
|
||||
/** \hideinitializer
|
||||
* \brief allocate an invalid #snd_mixer_selem_id_t using standard alloca
|
||||
|
@ -51,6 +51,7 @@
|
||||
#define CAP_CSWITCH (1<<9)
|
||||
#define CAP_CSWITCH_JOIN (1<<10)
|
||||
#define CAP_CSWITCH_EXCL (1<<11)
|
||||
#define CAP_ENUM (1<<12)
|
||||
|
||||
typedef struct _mixer_simple mixer_simple_t;
|
||||
|
||||
@ -59,6 +60,7 @@ typedef struct _mixer_simple mixer_simple_t;
|
||||
|
||||
typedef enum _selem_ctl_type {
|
||||
CTL_SINGLE,
|
||||
CTL_ENUMLIST,
|
||||
CTL_GLOBAL_SWITCH,
|
||||
CTL_GLOBAL_VOLUME,
|
||||
CTL_GLOBAL_ROUTE,
|
||||
@ -289,6 +291,24 @@ static int elem_read_route(selem_t *s, int dir, selem_ctl_type_t type)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int elem_read_enum(selem_t *s)
|
||||
{
|
||||
snd_ctl_elem_value_t ctl;
|
||||
unsigned int idx;
|
||||
int err;
|
||||
selem_ctl_t *c = &s->ctls[CTL_ENUMLIST];
|
||||
memset(&ctl, 0, sizeof(ctl));
|
||||
if ((err = snd_hctl_elem_read(c->elem, &ctl)) < 0)
|
||||
return err;
|
||||
for (idx = 0; idx < s->str[0].channels; idx++) {
|
||||
unsigned int idx1 = idx;
|
||||
if (idx >= c->values)
|
||||
idx1 = 0;
|
||||
s->str[0].vol[idx] = ctl.value.enumerated.item[idx1];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int selem_read(snd_mixer_elem_t *elem)
|
||||
{
|
||||
selem_t *s;
|
||||
@ -309,6 +329,9 @@ static int selem_read(snd_mixer_elem_t *elem)
|
||||
csw = s->str[CAPT].sw;
|
||||
s->str[CAPT].sw = ~0U;
|
||||
|
||||
if (s->ctls[CTL_ENUMLIST].elem)
|
||||
return elem_read_enum(s);
|
||||
|
||||
if (s->ctls[CTL_PLAYBACK_VOLUME].elem)
|
||||
err = elem_read_volume(s, PLAY, CTL_PLAYBACK_VOLUME);
|
||||
else if (s->ctls[CTL_GLOBAL_VOLUME].elem)
|
||||
@ -482,6 +505,22 @@ static int elem_write_route(selem_t *s, int dir, selem_ctl_type_t type)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int elem_write_enum(selem_t *s)
|
||||
{
|
||||
snd_ctl_elem_value_t ctl;
|
||||
unsigned int idx;
|
||||
int err;
|
||||
selem_ctl_t *c = &s->ctls[CTL_ENUMLIST];
|
||||
memset(&ctl, 0, sizeof(ctl));
|
||||
if ((err = snd_hctl_elem_read(c->elem, &ctl)) < 0)
|
||||
return err;
|
||||
for (idx = 0; idx < c->values; idx++)
|
||||
ctl.value.enumerated.item[idx] = (unsigned int)s->str[0].vol[idx];
|
||||
if ((err = snd_hctl_elem_write(c->elem, &ctl)) < 0)
|
||||
return err;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int selem_write(snd_mixer_elem_t *elem)
|
||||
{
|
||||
selem_t *s;
|
||||
@ -491,6 +530,9 @@ static int selem_write(snd_mixer_elem_t *elem)
|
||||
assert(elem->type == SND_MIXER_ELEM_SIMPLE);
|
||||
s = elem->private_data;
|
||||
|
||||
if (s->ctls[CTL_ENUMLIST].elem)
|
||||
return elem_write_enum(s);
|
||||
|
||||
if (s->ctls[CTL_SINGLE].elem) {
|
||||
if (s->ctls[CTL_SINGLE].type == SND_CTL_ELEM_TYPE_INTEGER)
|
||||
err = elem_write_volume(s, PLAY, CTL_SINGLE);
|
||||
@ -682,6 +724,12 @@ static int simple_update(snd_mixer_elem_t *melem)
|
||||
caps |= CAP_CSWITCH | CAP_CSWITCH_EXCL;
|
||||
caps &= ~CAP_GSWITCH;
|
||||
}
|
||||
ctl = &simple->ctls[CTL_ENUMLIST];
|
||||
if (ctl->elem) {
|
||||
if (pchannels < ctl->values)
|
||||
pchannels = ctl->values;
|
||||
caps |= CAP_ENUM;
|
||||
}
|
||||
if (pchannels > 32)
|
||||
pchannels = 32;
|
||||
if (cchannels > 32)
|
||||
@ -813,7 +861,9 @@ static int simple_add1(snd_mixer_class_t *class, const char *name,
|
||||
return err;
|
||||
switch (type) {
|
||||
case CTL_SINGLE:
|
||||
if (info.type != SND_CTL_ELEM_TYPE_BOOLEAN &&
|
||||
if (info.type == SND_CTL_ELEM_TYPE_ENUMERATED)
|
||||
type = CTL_ENUMLIST;
|
||||
else if (info.type != SND_CTL_ELEM_TYPE_BOOLEAN &&
|
||||
info.type != SND_CTL_ELEM_TYPE_INTEGER)
|
||||
return 0;
|
||||
break;
|
||||
@ -886,8 +936,13 @@ static int simple_add1(snd_mixer_class_t *class, const char *name,
|
||||
simple->ctls[type].type = info.type;
|
||||
simple->ctls[type].access = info.access;
|
||||
simple->ctls[type].values = info.count;
|
||||
simple->ctls[type].min = info.value.integer.min;
|
||||
simple->ctls[type].max = info.value.integer.max;
|
||||
if (type == CTL_ENUMLIST) {
|
||||
simple->ctls[type].min = 0;
|
||||
simple->ctls[type].max = info.value.enumerated.items;
|
||||
} else {
|
||||
simple->ctls[type].min = info.value.integer.min;
|
||||
simple->ctls[type].max = info.value.integer.max;
|
||||
}
|
||||
switch (type) {
|
||||
case CTL_CAPTURE_SOURCE:
|
||||
simple->capture_item = value;
|
||||
@ -1811,6 +1866,125 @@ int snd_mixer_selem_set_capture_switch_all(snd_mixer_elem_t *elem, int value)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return true if mixer simple element is an enumerated control
|
||||
* \param elem Mixer simple element handle
|
||||
* \return 0 normal volume/switch control, 1 enumerated control
|
||||
*/
|
||||
int snd_mixer_selem_is_enumerated(snd_mixer_elem_t *elem)
|
||||
{
|
||||
selem_t *s;
|
||||
assert(elem);
|
||||
assert(elem->type == SND_MIXER_ELEM_SIMPLE);
|
||||
s = elem->private_data;
|
||||
return s->ctls[CTL_ENUMLIST].elem != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return the number of enumerated items of the given mixer simple element
|
||||
* \param elem Mixer simple element handle
|
||||
* \return the number of enumerated items, otherwise a negative error code
|
||||
*/
|
||||
int snd_mixer_selem_get_enum_items(snd_mixer_elem_t *elem)
|
||||
{
|
||||
selem_t *s;
|
||||
assert(elem);
|
||||
assert(elem->type == SND_MIXER_ELEM_SIMPLE);
|
||||
s = elem->private_data;
|
||||
if (! s->ctls[CTL_ENUMLIST].elem)
|
||||
return -EINVAL;
|
||||
return s->ctls[CTL_ENUMLIST].max;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief get the enumerated item string for the given mixer simple element
|
||||
* \param elem Mixer simple element handle
|
||||
* \param item the index of the enumerated item to query
|
||||
* \param maxlen the maximal length to be stored
|
||||
* \param buf the buffer to store the name string
|
||||
* \return 0 if successful, otherwise a negative error code
|
||||
*/
|
||||
int snd_mixer_selem_get_enum_item_name(snd_mixer_elem_t *elem,
|
||||
unsigned int item,
|
||||
size_t maxlen, char *buf)
|
||||
{
|
||||
selem_t *s;
|
||||
snd_ctl_elem_info_t *info;
|
||||
snd_hctl_elem_t *helem;
|
||||
assert(elem);
|
||||
assert(elem->type == SND_MIXER_ELEM_SIMPLE);
|
||||
s = elem->private_data;
|
||||
helem = s->ctls[CTL_ENUMLIST].elem;
|
||||
assert(helem);
|
||||
if (item >= (unsigned int)s->ctls[CTL_ENUMLIST].max)
|
||||
return -EINVAL;
|
||||
snd_ctl_elem_info_alloca(&info);
|
||||
snd_hctl_elem_info(helem, info);
|
||||
snd_ctl_elem_info_set_item(info, item);
|
||||
snd_hctl_elem_info(helem, info);
|
||||
strncpy(buf, snd_ctl_elem_info_get_item_name(info), maxlen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief get the current selected enumerated item for the given mixer simple element
|
||||
* \param elem Mixer simple element handle
|
||||
* \param channel mixer simple element channel identifier
|
||||
* \param itemp the pointer to store the index of the enumerated item
|
||||
* \return 0 if successful, otherwise a negative error code
|
||||
*/
|
||||
int snd_mixer_selem_get_enum_item(snd_mixer_elem_t *elem,
|
||||
snd_mixer_selem_channel_id_t channel,
|
||||
unsigned int *itemp)
|
||||
{
|
||||
selem_t *s;
|
||||
snd_ctl_elem_value_t ctl;
|
||||
snd_hctl_elem_t *helem;
|
||||
int err;
|
||||
assert(elem);
|
||||
assert(elem->type == SND_MIXER_ELEM_SIMPLE);
|
||||
s = elem->private_data;
|
||||
if ((unsigned int) channel >= s->str[0].channels)
|
||||
return -EINVAL;
|
||||
helem = s->ctls[CTL_ENUMLIST].elem;
|
||||
assert(helem);
|
||||
memset(&ctl, 0, sizeof(ctl));
|
||||
err = snd_hctl_elem_read(helem, &ctl);
|
||||
if (! err)
|
||||
*itemp = ctl.value.enumerated.item[channel];
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief set the current selected enumerated item for the given mixer simple element
|
||||
* \param elem Mixer simple element handle
|
||||
* \param channel mixer simple element channel identifier
|
||||
* \param item the enumerated item index
|
||||
* \return 0 if successful, otherwise a negative error code
|
||||
*/
|
||||
int snd_mixer_selem_set_enum_item(snd_mixer_elem_t *elem,
|
||||
snd_mixer_selem_channel_id_t channel,
|
||||
unsigned int item)
|
||||
{
|
||||
selem_t *s;
|
||||
snd_ctl_elem_value_t ctl;
|
||||
snd_hctl_elem_t *helem;
|
||||
int err;
|
||||
assert(elem);
|
||||
assert(elem->type == SND_MIXER_ELEM_SIMPLE);
|
||||
s = elem->private_data;
|
||||
if ((unsigned int) channel >= s->str[0].channels)
|
||||
return -EINVAL;
|
||||
helem = s->ctls[CTL_ENUMLIST].elem;
|
||||
assert(helem);
|
||||
if (item >= (unsigned int)s->ctls[CTL_ENUMLIST].max)
|
||||
return -EINVAL;
|
||||
memset(&ctl, 0, sizeof(ctl));
|
||||
err = snd_hctl_elem_read(helem, &ctl);
|
||||
ctl.value.enumerated.item[channel] = item;
|
||||
return snd_hctl_elem_write(helem, &ctl);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief get size of #snd_mixer_selem_id_t
|
||||
* \return size in bytes
|
||||
|
Loading…
Reference in New Issue
Block a user