diff options
-rw-r--r-- | include/tinyalsa/mixer.h | 5 | ||||
-rw-r--r-- | src/mixer.c | 72 | ||||
-rw-r--r-- | src/mixer_hw.c | 9 | ||||
-rw-r--r-- | src/mixer_plugin.c | 2 |
4 files changed, 77 insertions, 11 deletions
diff --git a/include/tinyalsa/mixer.h b/include/tinyalsa/mixer.h index faeb957..7f0f022 100644 --- a/include/tinyalsa/mixer.h +++ b/include/tinyalsa/mixer.h @@ -35,7 +35,9 @@ #ifndef TINYALSA_MIXER_H #define TINYALSA_MIXER_H +#include <sys/time.h> #include <stddef.h> +#include <sound/asound.h> #if defined(__cplusplus) extern "C" { @@ -136,6 +138,9 @@ int mixer_ctl_get_range_min(const struct mixer_ctl *ctl); int mixer_ctl_get_range_max(const struct mixer_ctl *ctl); +int mixer_read_event(struct mixer *mixer, struct snd_ctl_event *ev); + +int mixer_consume_event(struct mixer *mixer); #if defined(__cplusplus) } /* extern "C" */ #endif diff --git a/src/mixer.c b/src/mixer.c index 1c9e63b..c8480d7 100644 --- a/src/mixer.c +++ b/src/mixer.c @@ -475,7 +475,7 @@ int mixer_wait_event(struct mixer *mixer, int timeout) { struct pollfd *pfd; struct mixer_ctl_group *grp; - int count = 0, num_fds = 0, i; + int count = 0, num_fds = 0, i, ret = 0; if (mixer->fd >= 0) num_fds++; @@ -485,7 +485,7 @@ int mixer_wait_event(struct mixer *mixer, int timeout) num_fds++; #endif - pfd = (struct pollfd *)calloc(sizeof(struct pollfd), num_fds); + pfd = (struct pollfd *)calloc(num_fds, sizeof(struct pollfd)); if (!pfd) return -ENOMEM; @@ -506,33 +506,85 @@ int mixer_wait_event(struct mixer *mixer, int timeout) #endif if (!count) - return 0; + goto exit; for (;;) { int err; err = poll(pfd, count, timeout); - if (err < 0) - return -errno; + if (err < 0) { + ret = -errno; + goto exit; + } if (!err) - return 0; + goto exit; + for (i = 0; i < count; i++) { - if (pfd[i].revents & (POLLERR | POLLNVAL)) - return -EIO; + if (pfd[i].revents & (POLLERR | POLLNVAL)) { + ret = -EIO; + goto exit; + } if (pfd[i].revents & (POLLIN | POLLOUT)) { if ((i == 0) && mixer->fd >= 0) { grp = mixer->h_grp; grp->event_cnt++; } #ifdef TINYALSA_USES_PLUGINS - else { + else { grp = mixer->v_grp; grp->event_cnt++; } #endif - return 1; + ret = 1; + goto exit; } } } +exit: + free(pfd); + return ret; +} + +/** 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; + + return mixer_read_event(mixer, &ev); +} + +int mixer_read_event(struct mixer *mixer, struct snd_ctl_event *ev) +{ + struct mixer_ctl_group *grp; + ssize_t count = 0; + + if (mixer->h_grp) { + grp = mixer->h_grp; + if (grp->event_cnt) { + grp->event_cnt--; + count = grp->ops->read_event(grp->data, ev, sizeof(*ev)); + return (count >= 0) ? 0 : -errno; + } + } +#ifdef TINYALSA_USES_PLUGINS + if (mixer->v_grp) { + grp = mixer->v_grp; + if (grp->event_cnt) { + grp->event_cnt--; + count = grp->ops->read_event(grp->data, ev, sizeof(*ev)); + return (count >= 0) ? 0 : -errno; + } + } +#endif + return 0; } static unsigned int mixer_grp_get_count(struct mixer_ctl_group *grp) diff --git a/src/mixer_hw.c b/src/mixer_hw.c index 2e86dfa..da5a390 100644 --- a/src/mixer_hw.c +++ b/src/mixer_hw.c @@ -82,9 +82,18 @@ static int mixer_hw_ioctl(void *data, unsigned int cmd, ...) return ioctl(hw_data->fd, cmd, arg); } +static ssize_t mixer_hw_read_event(void *data, struct snd_ctl_event *ev, + size_t size) +{ + struct mixer_hw_data *hw_data = data; + + return read(hw_data->fd, ev, size); +} + static const struct mixer_ops mixer_hw_ops = { .close = mixer_hw_close, .ioctl = mixer_hw_ioctl, + .read_event = mixer_hw_read_event, }; int mixer_hw_open(unsigned int card, void **data, diff --git a/src/mixer_plugin.c b/src/mixer_plugin.c index 389003e..9f22b7e 100644 --- a/src/mixer_plugin.c +++ b/src/mixer_plugin.c @@ -137,8 +137,8 @@ static int mixer_plug_info_integer(struct snd_control *ctl, void mixer_plug_notifier_cb(struct mixer_plugin *plugin) { - eventfd_write(plugin->eventfd, 1); plugin->event_cnt++; + eventfd_write(plugin->eventfd, 1); } /* In consume_event/read, do not call eventfd_read until all events are read from list. |