aboutsummaryrefslogtreecommitdiff
path: root/mixer.c
diff options
context:
space:
mode:
authorRichard Fitzgerald <rf@opensource.wolfsonmicro.com>2014-09-09 17:03:21 +0100
committerRichard Fitzgerald <rf@opensource.wolfsonmicro.com>2015-10-20 14:23:28 +0100
commit899cecebd15a7d08781d5f9362ec4bd7cc8863da (patch)
treee58b995c36c9b8185a9e1f98d07e7df13db77d1a /mixer.c
parent33fe27c809e0fa67e14db9fec37c5f2ef849aecb (diff)
mixer: remove separate info list
Each mixer_ctl has an associated snd_ctl_elem_info, which was kept in a separate array with pointers from the mixer_ctl to its corresponding snd_ctl_elem_info. This means double pointer dereferences when looking up the info. It also means extra work to add support for extending the arrays to include dynamically added controls because the pointers from the ctl array to the info array would have to be updated. This patch removes the info list and gives each mixer_ctl struct its own local snd_ctl_elem_info, removing the additional pointer dereferencing. Change-Id: I03f7d411afd9e37f58b984584712fee64d85ef4e Signed-off-by: Richard Fitzgerald <rf@opensource.wolfsonmicro.com>
Diffstat (limited to 'mixer.c')
-rw-r--r--mixer.c89
1 files changed, 42 insertions, 47 deletions
diff --git a/mixer.c b/mixer.c
index 113f11e..fc9123d 100644
--- a/mixer.c
+++ b/mixer.c
@@ -47,14 +47,13 @@
struct mixer_ctl {
struct mixer *mixer;
- struct snd_ctl_elem_info *info;
+ struct snd_ctl_elem_info info;
char **ename;
};
struct mixer {
int fd;
struct snd_ctl_card_info card_info;
- struct snd_ctl_elem_info *elem_info;
struct mixer_ctl *ctl;
unsigned int count;
};
@@ -72,7 +71,7 @@ void mixer_close(struct mixer *mixer)
if (mixer->ctl) {
for (n = 0; n < mixer->count; n++) {
if (mixer->ctl[n].ename) {
- unsigned int max = mixer->ctl[n].info->value.enumerated.items;
+ unsigned int max = mixer->ctl[n].info.value.enumerated.items;
for (m = 0; m < max; m++)
free(mixer->ctl[n].ename[m]);
free(mixer->ctl[n].ename);
@@ -81,9 +80,6 @@ void mixer_close(struct mixer *mixer)
free(mixer->ctl);
}
- if (mixer->elem_info)
- free(mixer->elem_info);
-
free(mixer);
/* TODO: verify frees */
@@ -113,8 +109,7 @@ struct mixer *mixer_open(unsigned int card)
goto fail;
mixer->ctl = calloc(elist.count, sizeof(struct mixer_ctl));
- mixer->elem_info = calloc(elist.count, sizeof(struct snd_ctl_elem_info));
- if (!mixer->ctl || !mixer->elem_info)
+ if (!mixer->ctl)
goto fail;
if (ioctl(fd, SNDRV_CTL_IOCTL_CARD_INFO, &mixer->card_info) < 0)
@@ -132,11 +127,10 @@ struct mixer *mixer_open(unsigned int card)
goto fail;
for (n = 0; n < mixer->count; n++) {
- struct snd_ctl_elem_info *ei = mixer->elem_info + n;
+ struct snd_ctl_elem_info *ei = &mixer->ctl[n].info;
ei->id.numid = eid[n].numid;
if (ioctl(fd, SNDRV_CTL_IOCTL_ELEM_INFO, ei) < 0)
goto fail;
- mixer->ctl[n].info = ei;
mixer->ctl[n].mixer = mixer;
if (ei->type == SNDRV_CTL_ELEM_TYPE_ENUMERATED) {
char **enames = calloc(ei->value.enumerated.items, sizeof(char*));
@@ -194,13 +188,14 @@ struct mixer_ctl *mixer_get_ctl(struct mixer *mixer, unsigned int id)
struct mixer_ctl *mixer_get_ctl_by_name(struct mixer *mixer, const char *name)
{
unsigned int n;
+ struct mixer_ctl *ctl = mixer->ctl;
if (!mixer)
return NULL;
for (n = 0; n < mixer->count; n++)
- if (!strcmp(name, (char*) mixer->elem_info[n].id.name))
- return mixer->ctl + n;
+ if (!strcmp(name, (char*) ctl[n].info.id.name))
+ return &ctl[n];
return NULL;
}
@@ -218,7 +213,7 @@ unsigned int mixer_ctl_get_id(struct mixer_ctl *ctl)
/* numid values start at 1, return a 0-base value that
* can be passed to mixer_get_ctl()
*/
- return ctl->info->id.numid - 1;
+ return ctl->info.id.numid - 1;
}
const char *mixer_ctl_get_name(struct mixer_ctl *ctl)
@@ -226,7 +221,7 @@ const char *mixer_ctl_get_name(struct mixer_ctl *ctl)
if (!ctl)
return NULL;
- return (const char *)ctl->info->id.name;
+ return (const char *)ctl->info.id.name;
}
enum mixer_ctl_type mixer_ctl_get_type(struct mixer_ctl *ctl)
@@ -234,7 +229,7 @@ enum mixer_ctl_type mixer_ctl_get_type(struct mixer_ctl *ctl)
if (!ctl)
return MIXER_CTL_TYPE_UNKNOWN;
- switch (ctl->info->type) {
+ switch (ctl->info.type) {
case SNDRV_CTL_ELEM_TYPE_BOOLEAN: return MIXER_CTL_TYPE_BOOL;
case SNDRV_CTL_ELEM_TYPE_INTEGER: return MIXER_CTL_TYPE_INT;
case SNDRV_CTL_ELEM_TYPE_ENUMERATED: return MIXER_CTL_TYPE_ENUM;
@@ -250,7 +245,7 @@ const char *mixer_ctl_get_type_string(struct mixer_ctl *ctl)
if (!ctl)
return "";
- switch (ctl->info->type) {
+ switch (ctl->info.type) {
case SNDRV_CTL_ELEM_TYPE_BOOLEAN: return "BOOL";
case SNDRV_CTL_ELEM_TYPE_INTEGER: return "INT";
case SNDRV_CTL_ELEM_TYPE_ENUMERATED: return "ENUM";
@@ -266,7 +261,7 @@ unsigned int mixer_ctl_get_num_values(struct mixer_ctl *ctl)
if (!ctl)
return 0;
- return ctl->info->count;
+ return ctl->info.count;
}
static int percent_to_int(struct snd_ctl_elem_info *ei, int percent)
@@ -292,18 +287,18 @@ static int int_to_percent(struct snd_ctl_elem_info *ei, int value)
int mixer_ctl_get_percent(struct mixer_ctl *ctl, unsigned int id)
{
- if (!ctl || (ctl->info->type != SNDRV_CTL_ELEM_TYPE_INTEGER))
+ if (!ctl || (ctl->info.type != SNDRV_CTL_ELEM_TYPE_INTEGER))
return -EINVAL;
- return int_to_percent(ctl->info, mixer_ctl_get_value(ctl, id));
+ return int_to_percent(&ctl->info, mixer_ctl_get_value(ctl, id));
}
int mixer_ctl_set_percent(struct mixer_ctl *ctl, unsigned int id, int percent)
{
- if (!ctl || (ctl->info->type != SNDRV_CTL_ELEM_TYPE_INTEGER))
+ if (!ctl || (ctl->info.type != SNDRV_CTL_ELEM_TYPE_INTEGER))
return -EINVAL;
- return mixer_ctl_set_value(ctl, id, percent_to_int(ctl->info, percent));
+ return mixer_ctl_set_value(ctl, id, percent_to_int(&ctl->info, percent));
}
int mixer_ctl_get_value(struct mixer_ctl *ctl, unsigned int id)
@@ -311,16 +306,16 @@ int mixer_ctl_get_value(struct mixer_ctl *ctl, unsigned int id)
struct snd_ctl_elem_value ev;
int ret;
- if (!ctl || (id >= ctl->info->count))
+ if (!ctl || (id >= ctl->info.count))
return -EINVAL;
memset(&ev, 0, sizeof(ev));
- ev.id.numid = ctl->info->id.numid;
+ ev.id.numid = ctl->info.id.numid;
ret = ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_READ, &ev);
if (ret < 0)
return ret;
- switch (ctl->info->type) {
+ switch (ctl->info.type) {
case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
return !!ev.value.integer.value[id];
@@ -347,13 +342,13 @@ int mixer_ctl_get_array(struct mixer_ctl *ctl, void *array, size_t count)
size_t size;
void *source;
- if (!ctl || (count > ctl->info->count) || !count || !array)
+ if (!ctl || (count > ctl->info.count) || !count || !array)
return -EINVAL;
memset(&ev, 0, sizeof(ev));
- ev.id.numid = ctl->info->id.numid;
+ ev.id.numid = ctl->info.id.numid;
- switch (ctl->info->type) {
+ switch (ctl->info.type) {
case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
case SNDRV_CTL_ELEM_TYPE_INTEGER:
ret = ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_READ, &ev);
@@ -365,12 +360,12 @@ int mixer_ctl_get_array(struct mixer_ctl *ctl, void *array, size_t count)
case SNDRV_CTL_ELEM_TYPE_BYTES:
/* check if this is new bytes TLV */
- if (ctl->info->access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE) {
+ if (ctl->info.access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE) {
struct snd_ctl_tlv *tlv;
int ret;
tlv = calloc(1, sizeof(*tlv) + count);
- tlv->numid = ctl->info->id.numid;
+ tlv->numid = ctl->info.id.numid;
tlv->length = count;
ret = ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_TLV_READ, tlv);
@@ -403,16 +398,16 @@ int mixer_ctl_set_value(struct mixer_ctl *ctl, unsigned int id, int value)
struct snd_ctl_elem_value ev;
int ret;
- if (!ctl || (id >= ctl->info->count))
+ if (!ctl || (id >= ctl->info.count))
return -EINVAL;
memset(&ev, 0, sizeof(ev));
- ev.id.numid = ctl->info->id.numid;
+ ev.id.numid = ctl->info.id.numid;
ret = ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_READ, &ev);
if (ret < 0)
return ret;
- switch (ctl->info->type) {
+ switch (ctl->info.type) {
case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
ev.value.integer.value[id] = !!value;
break;
@@ -447,13 +442,13 @@ int mixer_ctl_set_array(struct mixer_ctl *ctl, const void *array, size_t count)
size_t size;
void *dest;
- if (!ctl || (count > ctl->info->count) || !count || !array)
+ if (!ctl || (count > ctl->info.count) || !count || !array)
return -EINVAL;
memset(&ev, 0, sizeof(ev));
- ev.id.numid = ctl->info->id.numid;
+ ev.id.numid = ctl->info.id.numid;
- switch (ctl->info->type) {
+ switch (ctl->info.type) {
case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
case SNDRV_CTL_ELEM_TYPE_INTEGER:
size = sizeof(ev.value.integer.value[0]);
@@ -462,11 +457,11 @@ int mixer_ctl_set_array(struct mixer_ctl *ctl, const void *array, size_t count)
case SNDRV_CTL_ELEM_TYPE_BYTES:
/* check if this is new bytes TLV */
- if (ctl->info->access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE) {
+ if (ctl->info.access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE) {
struct snd_ctl_tlv *tlv;
int ret = 0;
tlv = calloc(1, sizeof(*tlv) + count);
- tlv->numid = ctl->info->id.numid;
+ tlv->numid = ctl->info.id.numid;
tlv->length = count;
memcpy(tlv->tlv, array, count);
@@ -491,18 +486,18 @@ int mixer_ctl_set_array(struct mixer_ctl *ctl, const void *array, size_t count)
int mixer_ctl_get_range_min(struct mixer_ctl *ctl)
{
- if (!ctl || (ctl->info->type != SNDRV_CTL_ELEM_TYPE_INTEGER))
+ if (!ctl || (ctl->info.type != SNDRV_CTL_ELEM_TYPE_INTEGER))
return -EINVAL;
- return ctl->info->value.integer.min;
+ return ctl->info.value.integer.min;
}
int mixer_ctl_get_range_max(struct mixer_ctl *ctl)
{
- if (!ctl || (ctl->info->type != SNDRV_CTL_ELEM_TYPE_INTEGER))
+ if (!ctl || (ctl->info.type != SNDRV_CTL_ELEM_TYPE_INTEGER))
return -EINVAL;
- return ctl->info->value.integer.max;
+ return ctl->info.value.integer.max;
}
unsigned int mixer_ctl_get_num_enums(struct mixer_ctl *ctl)
@@ -510,14 +505,14 @@ unsigned int mixer_ctl_get_num_enums(struct mixer_ctl *ctl)
if (!ctl)
return 0;
- return ctl->info->value.enumerated.items;
+ return ctl->info.value.enumerated.items;
}
const char *mixer_ctl_get_enum_string(struct mixer_ctl *ctl,
unsigned int enum_id)
{
- if (!ctl || (ctl->info->type != SNDRV_CTL_ELEM_TYPE_ENUMERATED) ||
- (enum_id >= ctl->info->value.enumerated.items))
+ if (!ctl || (ctl->info.type != SNDRV_CTL_ELEM_TYPE_ENUMERATED) ||
+ (enum_id >= ctl->info.value.enumerated.items))
return NULL;
return (const char *)ctl->ename[enum_id];
@@ -529,15 +524,15 @@ int mixer_ctl_set_enum_by_string(struct mixer_ctl *ctl, const char *string)
struct snd_ctl_elem_value ev;
int ret;
- if (!ctl || (ctl->info->type != SNDRV_CTL_ELEM_TYPE_ENUMERATED))
+ if (!ctl || (ctl->info.type != SNDRV_CTL_ELEM_TYPE_ENUMERATED))
return -EINVAL;
- num_enums = ctl->info->value.enumerated.items;
+ num_enums = ctl->info.value.enumerated.items;
for (i = 0; i < num_enums; i++) {
if (!strcmp(string, ctl->ename[i])) {
memset(&ev, 0, sizeof(ev));
ev.value.enumerated.item[0] = i;
- ev.id.numid = ctl->info->id.numid;
+ ev.id.numid = ctl->info.id.numid;
ret = ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_WRITE, &ev);
if (ret < 0)
return ret;