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:
M | Makefile | | | 1 | + |
M | mix.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>