spoon

set dwm status
git clone git://git.2f30.org/spoon
Log | Files | Refs | LICENSE

commit a231da1528ee804fec2b6f7cb4d896bd81a4cf1a
parent 774975c0a33418ee74e7f215aa82c671334f514e
Author: Lucas <lucas@sexy.is>
Date:   Sun, 26 Apr 2020 15:33:17 +0000

Adapt mix.c to new sioctl interface in OpenBSD

Diffstat:
MMakefile | 1+
Mmix.c | 184+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------
2 files changed, 139 insertions(+), 46 deletions(-)

diff --git a/Makefile b/Makefile @@ -20,6 +20,7 @@ LDLIBS = -lX11 # comment out the following sections. The stub implementations # from stub.c will be used instead. OBJ += mix.o +LDLIBS_OpenBSD_mix = -lsndio # if ALSA LDLIBS_Linux_mix = -lasound CPPFLAGS += -DUSE_TINYALSA=0 diff --git a/mix.c b/mix.c @@ -4,67 +4,159 @@ #include "util.h" #ifdef __OpenBSD__ -#include <sys/ioctl.h> -#include <sys/audioio.h> - -#include <fcntl.h> +#include <errno.h> +#include <poll.h> +#include <sndio.h> +#include <stdlib.h> #include <string.h> -#include <unistd.h> -int -mixread(void *arg, char *buf, size_t len) +#define MAX_CHANNELS 16 + +static struct sioctl_hdl *hdl = NULL; +static struct pollfd *pfds = NULL; + +static struct { + unsigned int addr; + int val; +} channel[MAX_CHANNELS]; +static size_t nchannels = 0; +static int output = 0; + +static void +update_output_value(void) { - mixer_devinfo_t dinfo; - mixer_ctrl_t mctl; - int fd, master, ret = 0, i = -1; + size_t i; + int val; - fd = open("/dev/mixer", O_RDONLY); - if (fd == -1) { - warn("open %s", "/dev/mixer"); - return -1; + if (nchannels == 0) + return; + + val = 0; + for (i = 0; i < nchannels; i++) + val += channel[i].val; + output = 100 * ((val / (double)nchannels) / 255.0); +} + +static void +ondesc(void *arg, struct sioctl_desc *desc, int val) +{ + size_t i; + + if (desc == NULL) { + update_output_value(); + return; } - dinfo.index = 0; - /* outputs */ - for (; ; dinfo.index++) { - ret = ioctl(fd, AUDIO_MIXER_DEVINFO, &dinfo); - if (ret == -1) { - warn("AUDIO_MIXER_DEVINFO %s", "/dev/mixer"); - goto out; - } - if (dinfo.type == AUDIO_MIXER_CLASS && - strcmp(dinfo.label.name, AudioCoutputs) == 0) { - i = dinfo.index; + + if (desc->type != SIOCTL_NUM || + strcmp(desc->func, "level") != 0 || + strcmp(desc->node0.name, "output") != 0) + return; + + for (i = 0; i < nchannels; i++) + if (channel[i].addr == desc->addr) + break; + + if (i < nchannels) { + channel[i].val = val; + return; + } + + if (nchannels >= MAX_CHANNELS) { + warnx("too many channels"); + return; + } + channel[i].addr = desc->addr; + channel[i].val = val; + nchannels++; +} + +static void +onval(void *arg, unsigned int addr, unsigned int val) +{ + size_t i; + + for (i = 0; i < nchannels; i++) + if (channel[i].addr == addr) { + channel[i].val = val; break; } + + if (i < nchannels) + update_output_value(); +} + +static int +do_init(void) +{ + hdl = sioctl_open(SIO_DEVANY, SIOCTL_READ, 0); + if (hdl == NULL) { + warnx("sioctl_open %s", SIO_DEVANY); + return 0; } - if (i == -1) { - warnx("no outputs mixer class: %s", "/dev/mixer"); - goto out; + if (!sioctl_ondesc(hdl, ondesc, NULL)) { + warnx("sioctl_ondesc"); + sioctl_close(hdl); + return 0; } - /* outputs.master */ - for (; ; dinfo.index++) { - ret = ioctl(fd, AUDIO_MIXER_DEVINFO, &dinfo); - if (ret == -1) { - warn("AUDIO_MIXER_DEVINFO %s", "/dev/mixer"); + sioctl_onval(hdl, onval, NULL); + + return 1; +} + +static int +poll_peek(void) +{ + int nfds, revents; + + if (pfds == NULL) { + pfds = malloc(sizeof(struct pollfd) * sioctl_nfds(hdl)); + if (pfds == NULL) { + warnx("out of memory"); goto out; } - if (dinfo.type == AUDIO_MIXER_VALUE && - dinfo.prev == AUDIO_MIXER_LAST && - dinfo.mixer_class == i && - strcmp(dinfo.label.name, AudioNmaster) == 0) - break; } - mctl.dev = dinfo.index; - ret = ioctl(fd, AUDIO_MIXER_READ, &mctl); - if (ret == -1) { - warn("AUDIO_MIXER_READ %s", "/dev/mixer"); + + nfds = sioctl_pollfd(hdl, pfds, POLLIN); + if (nfds == 0) + return 1; + while (poll(pfds, nfds, 0) == -1) + if (errno != EINTR) { + warn("sioctl poll"); + goto out; + } + revents = sioctl_revents(hdl, pfds); + if (revents & POLLHUP) { + warnx("sioctl disconnected"); goto out; } - master = mctl.un.value.level[0] * 100 / 255; - snprintf(buf, len, "%d%%", master); + + return 1; + out: - close(fd); - return ret; + free(pfds); + pfds = NULL; + sioctl_close(hdl); + + return 0; +} + +int +mixread(void *arg, char *buf, size_t len) +{ + static int init_done = 0; + struct pollfd *pfds; + int nfds; + + if (!init_done) { + if (!do_init()) + return -1; + init_done = 1; + } + + init_done = poll_peek(); + snprintf(buf, len, "%d%%", output); + + return 0; } #elif __linux__ && !USE_TINYALSA #include <alsa/asoundlib.h>