aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid.Coutherut <davidx.coutherut@intel.com>2013-06-03 13:45:51 +0200
committerDavid Wagner <david.wagner@intel.com>2014-09-24 13:54:42 +0200
commit9b42396aa0713be3435e30362bcb6ca52e544bf0 (patch)
tree4f487ce16c511d06ebe3d2e396372f45348f29f5
parent867920ca46cc8ddc726bc0d406c454c17b7b9262 (diff)
Defer filling enum-type mixers information
Currently, all information about all mixers are fetched during mixer_open(). For enum mixers, an additional step gets the string for each enumerated value - this can lead to a lot of ioctls and take time even when these mixers aren't used afterward. Defer fetching integer/string mapping values when needed (when getting/setting a enum mixer). Change-Id: I3681699eb55631a2bc7a1e66bf08aff3a845534f Signed-off-by: David Coutherut <davidx.coutherut@intel.com> Signed-off-by: David Wagner <david.wagner@intel.com> Author-Tracking-BZ: 113043
-rw-r--r--mixer.c61
1 files changed, 42 insertions, 19 deletions
diff --git a/mixer.c b/mixer.c
index 8e99fad..a14a2ed 100644
--- a/mixer.c
+++ b/mixer.c
@@ -91,7 +91,6 @@ void mixer_close(struct mixer *mixer)
struct mixer *mixer_open(unsigned int card)
{
struct snd_ctl_elem_list elist;
- struct snd_ctl_elem_info tmp;
struct snd_ctl_elem_id *eid = NULL;
struct mixer *mixer = NULL;
unsigned int n, m;
@@ -137,22 +136,6 @@ struct mixer *mixer_open(unsigned int card)
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*));
- if (!enames)
- goto fail;
- mixer->ctl[n].ename = enames;
- for (m = 0; m < ei->value.enumerated.items; m++) {
- memset(&tmp, 0, sizeof(tmp));
- tmp.id.numid = ei->id.numid;
- tmp.value.enumerated.item = m;
- if (ioctl(fd, SNDRV_CTL_IOCTL_ELEM_INFO, &tmp) < 0)
- goto fail;
- enames[m] = strdup(tmp.value.enumerated.name);
- if (!enames[m])
- goto fail;
- }
- }
}
free(eid);
@@ -463,11 +446,50 @@ unsigned int mixer_ctl_get_num_enums(struct mixer_ctl *ctl)
return ctl->info->value.enumerated.items;
}
+int mixer_ctl_fill_enum_string(struct mixer_ctl *ctl)
+{
+ struct snd_ctl_elem_info tmp;
+ unsigned int m;
+ char **enames;
+
+ if (ctl->ename) {
+ return 0;
+ }
+
+ enames = calloc(ctl->info->value.enumerated.items, sizeof(char*));
+ if (!enames)
+ goto fail;
+ for (m = 0; m < ctl->info->value.enumerated.items; m++) {
+ memset(&tmp, 0, sizeof(tmp));
+ tmp.id.numid = ctl->info->id.numid;
+ tmp.value.enumerated.item = m;
+ if (ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_INFO, &tmp) < 0)
+ goto fail;
+ enames[m] = strdup(tmp.value.enumerated.name);
+ if (!enames[m])
+ goto fail;
+ }
+ ctl->ename = enames;
+ return 0;
+
+fail:
+ if (enames) {
+ for (m = 0; m < ctl->info->value.enumerated.items; m++) {
+ if (enames[m]) {
+ free(enames[m]);
+ }
+ }
+ free(enames);
+ }
+ return -1;
+}
+
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))
+ (enum_id >= ctl->info->value.enumerated.items) ||
+ mixer_ctl_fill_enum_string(ctl) != 0)
return NULL;
return (const char *)ctl->ename[enum_id];
@@ -479,7 +501,8 @@ 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) ||
+ mixer_ctl_fill_enum_string(ctl) != 0)
return -EINVAL;
num_enums = ctl->info->value.enumerated.items;