diff options
author | Xin Li <delphij@google.com> | 2018-08-07 16:51:26 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2018-08-07 16:51:26 +0000 |
commit | 4bd87c6f19a20f8ce4be65575bfdd41a6495ae92 (patch) | |
tree | 12b062657b9bff1e8714bf1226ca9819273d55db | |
parent | ce0616534e7fcfd9ba4857075a08e54e0c32424e (diff) | |
parent | b2ad60dac46080f3c778a50ff2468871b8b07f5e (diff) | |
download | tinyalsa-4bd87c6f19a20f8ce4be65575bfdd41a6495ae92.tar.gz |
Merge "Merge Android Pie into master"android-o-mr1-iot-release-smart-display-r3android-o-mr1-iot-release-1.0.5android-o-mr1-iot-release-1.0.4android-o-mr1-iot-release-1.0.3oreo-mr1-1.2-iot-releasemaster-cuttlefish-testing-release
-rw-r--r-- | include/tinyalsa/asoundlib.h | 1 | ||||
-rw-r--r-- | mixer.c | 108 |
2 files changed, 81 insertions, 28 deletions
diff --git a/include/tinyalsa/asoundlib.h b/include/tinyalsa/asoundlib.h index dc71d37..935c8d0 100644 --- a/include/tinyalsa/asoundlib.h +++ b/include/tinyalsa/asoundlib.h @@ -316,6 +316,7 @@ int mixer_ctl_get_range_max(struct mixer_ctl *ctl); int mixer_subscribe_events(struct mixer *mixer, int subscribe); int mixer_wait_event(struct mixer *mixer, int timeout); +int mixer_consume_event(struct mixer *mixer); #if defined(__cplusplus) } /* extern "C" */ @@ -26,6 +26,7 @@ ** DAMAGE. */ +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <stdint.h> @@ -44,12 +45,17 @@ #define __user #include <sound/asound.h> +#ifndef SNDRV_CTL_ELEM_ID_NAME_MAXLEN +#define SNDRV_CTL_ELEM_ID_NAME_MAXLEN 44 +#endif + #include <tinyalsa/asoundlib.h> struct mixer_ctl { struct mixer *mixer; struct snd_ctl_elem_info *info; char **ename; + bool info_retrieved; }; struct mixer { @@ -93,10 +99,9 @@ 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; + unsigned int n; int fd; char fn[256]; @@ -133,28 +138,14 @@ 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; - 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*)); - 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; - } - } + struct mixer_ctl *ctl = mixer->ctl + n; + + ctl->mixer = mixer; + ctl->info = mixer->elem_info + n; + ctl->info->id.numid = eid[n].numid; + strncpy((char *)ctl->info->id.name, (char *)eid[n].name, + SNDRV_CTL_ELEM_ID_NAME_MAXLEN); + ctl->info->id.name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN - 1] = 0; } free(eid); @@ -171,6 +162,40 @@ fail: return 0; } +static bool mixer_ctl_get_elem_info(struct mixer_ctl* ctl) +{ + if (!ctl->info_retrieved) { + if (ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_INFO, ctl->info) < 0) + return false; + ctl->info_retrieved = true; + } + + if (ctl->info->type != SNDRV_CTL_ELEM_TYPE_ENUMERATED || ctl->ename) + return true; + + struct snd_ctl_elem_info tmp; + char** enames = calloc(ctl->info->value.enumerated.items, sizeof(char*)); + if (!enames) + return false; + + for (unsigned int i = 0; i < ctl->info->value.enumerated.items; i++) { + memset(&tmp, 0, sizeof(tmp)); + tmp.id.numid = ctl->info->id.numid; + tmp.value.enumerated.item = i; + if (ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_INFO, &tmp) < 0) + goto fail; + enames[i] = strdup(tmp.value.enumerated.name); + if (!enames[i]) + goto fail; + } + ctl->ename = enames; + return true; + +fail: + free(enames); + return false; +} + const char *mixer_get_name(struct mixer *mixer) { return (const char *)mixer->card_info.name; @@ -186,10 +211,16 @@ unsigned int mixer_get_num_ctls(struct mixer *mixer) struct mixer_ctl *mixer_get_ctl(struct mixer *mixer, unsigned int id) { - if (mixer && (id < mixer->count)) - return mixer->ctl + id; + struct mixer_ctl *ctl; - return NULL; + if (!mixer || (id >= mixer->count)) + return NULL; + + ctl = mixer->ctl + id; + if (!mixer_ctl_get_elem_info(ctl)) + return NULL; + + return ctl; } struct mixer_ctl *mixer_get_ctl_by_name(struct mixer *mixer, const char *name) @@ -201,7 +232,7 @@ struct mixer_ctl *mixer_get_ctl_by_name(struct mixer *mixer, const char *name) for (n = 0; n < mixer->count; n++) if (!strcmp(name, (char*) mixer->elem_info[n].id.name)) - return mixer->ctl + n; + return mixer_get_ctl(mixer, n); return NULL; } @@ -626,3 +657,24 @@ int mixer_wait_event(struct mixer *mixer, int timeout) return 1; } } + +/** Consume a mixer event. + * If mixer_subscribe_events has been called, + * mixer_wait_event will identify when a control value has changed. + * This function will clear a single event from the mixer so that + * further events can be alerted. + * + * @param mixer A mixer handle. + * @returns 0 on success. -errno on failure. + * @ingroup libtinyalsa-mixer + */ +int mixer_consume_event(struct mixer *mixer) { + struct snd_ctl_event ev; + ssize_t count = read(mixer->fd, &ev, sizeof(ev)); + // Exporting the actual event would require exposing snd_ctl_event + // via the header file, and all associated structs. + // The events generally tell you exactly which value changed, + // but reading values you're interested isn't hard and simplifies + // the interface greatly. + return (count >= 0) ? 0 : -errno; +} |