Use the new sioctl_open(3) API to display current audio level.
Now the programm displays the current sndiod master volume level, which is present on any device and always corresponds to the device programs are playing on.
This commit is contained in:
parent
7bf463e958
commit
9f385cbca0
@ -1,11 +1,11 @@
|
||||
# $OpenBSD: Makefile,v 1.58 2019/09/27 20:33:22 jasper Exp $
|
||||
# $OpenBSD: Makefile,v 1.59 2020/03/16 14:54:45 ratchov Exp $
|
||||
|
||||
ONLY_FOR_ARCHS= ${APM_ARCHS}
|
||||
|
||||
COMMENT= generate a statusbar for use with i3/xmobar/dzen2
|
||||
|
||||
DISTNAME= i3status-2.13
|
||||
REVISION= 1
|
||||
REVISION= 2
|
||||
CATEGORIES= x11 sysutils
|
||||
|
||||
HOMEPAGE= https://i3wm.org/i3status/
|
||||
@ -28,7 +28,9 @@ BUILD_DEPENDS= textproc/asciidoc>=8.6.8 \
|
||||
LIB_DEPENDS= devel/libconfuse \
|
||||
devel/libyajl
|
||||
|
||||
CONFIGURE_STYLE = gnu
|
||||
AUTOCONF_VERSION = 2.69
|
||||
AUTOMAKE_VERSION = 1.16
|
||||
CONFIGURE_STYLE = autoreconf
|
||||
SEPARATE_BUILD = Yes
|
||||
|
||||
FAKE_FLAGS += sysconfdir=${PREFIX}/share/examples/i3status/
|
||||
|
37
x11/i3status/patches/patch-Makefile_am
Normal file
37
x11/i3status/patches/patch-Makefile_am
Normal file
@ -0,0 +1,37 @@
|
||||
$OpenBSD: patch-Makefile_am,v 1.1 2020/03/16 14:54:45 ratchov Exp $
|
||||
|
||||
Index: Makefile.am
|
||||
--- Makefile.am.orig
|
||||
+++ Makefile.am
|
||||
@@ -1,5 +1,3 @@
|
||||
-@CODE_COVERAGE_RULES@
|
||||
-
|
||||
echo-version:
|
||||
@echo "@I3STATUS_VERSION@"
|
||||
|
||||
@@ -30,6 +28,7 @@ i3status_CFLAGS = \
|
||||
$(PULSE_CFLAGS) \
|
||||
$(NLGENL_CFLAGS) \
|
||||
$(ALSA_CFLAGS) \
|
||||
+ $(SNDIO_CFLAGS) \
|
||||
$(PTHREAD_CFLAGS)
|
||||
|
||||
i3status_CPPFLAGS = \
|
||||
@@ -42,6 +41,7 @@ i3status_LDADD = \
|
||||
$(PULSE_LIBS) \
|
||||
$(NLGENL_LIBS) \
|
||||
$(ALSA_LIBS) \
|
||||
+ $(SNDIO_LIBS) \
|
||||
$(PTHREAD_LIBS)
|
||||
|
||||
i3status_SOURCES = \
|
||||
@@ -69,7 +69,8 @@ i3status_SOURCES = \
|
||||
src/print_wireless_info.c \
|
||||
src/print_file_contents.c \
|
||||
src/process_runs.c \
|
||||
- src/pulse.c
|
||||
+ src/pulse.c \
|
||||
+ src/sndio.c
|
||||
|
||||
dist_sysconf_DATA = \
|
||||
i3status.conf
|
@ -1,15 +0,0 @@
|
||||
$OpenBSD: patch-Makefile_in,v 1.1 2019/07/06 20:20:27 jasper Exp $
|
||||
|
||||
The CODE_COVERAGE_RULES fragment contains an unmatched "if" clause.
|
||||
|
||||
Index: Makefile.in
|
||||
--- Makefile.in.orig
|
||||
+++ Makefile.in
|
||||
@@ -1851,7 +1851,6 @@ uninstall-man: uninstall-man1
|
||||
|
||||
.PRECIOUS: Makefile
|
||||
|
||||
-@CODE_COVERAGE_RULES@
|
||||
|
||||
echo-version:
|
||||
@echo "@I3STATUS_VERSION@"
|
19
x11/i3status/patches/patch-configure_ac
Normal file
19
x11/i3status/patches/patch-configure_ac
Normal file
@ -0,0 +1,19 @@
|
||||
$OpenBSD: patch-configure_ac,v 1.1 2020/03/16 14:54:45 ratchov Exp $
|
||||
|
||||
Index: configure.ac
|
||||
--- configure.ac.orig
|
||||
+++ configure.ac
|
||||
@@ -91,6 +91,13 @@ case $host_os in
|
||||
;;
|
||||
esac
|
||||
|
||||
+# if sndio is available, define USE_SNDIO
|
||||
+AC_CHECK_HEADER(sndio.h,
|
||||
+ [AC_CHECK_LIB([sndio], [sio_open], [
|
||||
+ AC_SUBST(SNDIO_LIBS, "-lsndio")
|
||||
+ AC_DEFINE([USE_SNDIO], [], [Use sndio])
|
||||
+ ], [])], [])
|
||||
+
|
||||
dnl TODO: check for libbsd for GNU/kFreeBSD
|
||||
|
||||
# Checks for programs.
|
13
x11/i3status/patches/patch-include_i3status_h
Normal file
13
x11/i3status/patches/patch-include_i3status_h
Normal file
@ -0,0 +1,13 @@
|
||||
$OpenBSD: patch-include_i3status_h,v 1.10 2020/03/16 14:54:45 ratchov Exp $
|
||||
|
||||
Index: include/i3status.h
|
||||
--- include/i3status.h.orig
|
||||
+++ include/i3status.h
|
||||
@@ -232,6 +232,7 @@ int volume_pulseaudio(uint32_t sink_idx, const char *s
|
||||
bool description_pulseaudio(uint32_t sink_idx, const char *sink_name, char buffer[MAX_SINK_DESCRIPTION_LEN]);
|
||||
bool pulse_initialize(void);
|
||||
void print_file_contents(yajl_gen json_gen, char *buffer, const char *title, const char *path, const char *format, const char *format_bad, const int max_chars);
|
||||
+int volume_sndio(void);
|
||||
|
||||
/* socket file descriptor for general purposes */
|
||||
extern int general_socket;
|
144
x11/i3status/patches/patch-src_print_volume_c
Normal file
144
x11/i3status/patches/patch-src_print_volume_c
Normal file
@ -0,0 +1,144 @@
|
||||
$OpenBSD: patch-src_print_volume_c,v 1.12 2020/03/16 14:54:45 ratchov Exp $
|
||||
|
||||
Index: src/print_volume.c
|
||||
--- src/print_volume.c.orig
|
||||
+++ src/print_volume.c
|
||||
@@ -21,13 +21,6 @@
|
||||
#include <sys/soundcard.h>
|
||||
#endif
|
||||
|
||||
-#ifdef __OpenBSD__
|
||||
-#include <fcntl.h>
|
||||
-#include <unistd.h>
|
||||
-#include <sys/audioio.h>
|
||||
-#include <sys/ioctl.h>
|
||||
-#endif
|
||||
-
|
||||
#include "i3status.h"
|
||||
#include "queue.h"
|
||||
|
||||
@@ -145,9 +138,20 @@ void print_volume(yajl_gen json_gen, char *buffer, con
|
||||
/* negative result or NULL description means error, fail PulseAudio attempt */
|
||||
}
|
||||
/* If some other device was specified or PulseAudio is not detected,
|
||||
- * proceed to ALSA / OSS */
|
||||
+ * proceed to sndio / ALSA / OSS */
|
||||
#endif
|
||||
|
||||
+#ifdef USE_SNDIO
|
||||
+ int vol;
|
||||
+
|
||||
+ vol = volume_sndio();
|
||||
+ if (vol != -1) {
|
||||
+ outwalk = apply_volume_format(fmt, outwalk, vol & 0x7f, "sndio");
|
||||
+ goto out;
|
||||
+ }
|
||||
+/* If sndio is not detected, proceed to ALSA / OSS */
|
||||
+#endif
|
||||
+
|
||||
#ifdef __linux__
|
||||
const long MAX_LINEAR_DB_SCALE = 24;
|
||||
int err;
|
||||
@@ -248,7 +252,8 @@ void print_volume(yajl_gen json_gen, char *buffer, con
|
||||
snd_mixer_selem_id_free(sid);
|
||||
|
||||
#endif
|
||||
-#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
|
||||
+
|
||||
+#if defined(__FreeBSD__) || defined(__DragonFly__)
|
||||
char *mixerpath;
|
||||
char defaultmixer[] = "/dev/mixer";
|
||||
int mixfd, vol, devmask = 0;
|
||||
@@ -261,84 +266,13 @@ void print_volume(yajl_gen json_gen, char *buffer, con
|
||||
mixerpath = defaultmixer;
|
||||
|
||||
if ((mixfd = open(mixerpath, O_RDWR)) < 0) {
|
||||
-#if defined(__OpenBSD__)
|
||||
- warn("audioio: Cannot open mixer");
|
||||
-#else
|
||||
warn("OSS: Cannot open mixer");
|
||||
-#endif
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (mixer_idx > 0)
|
||||
free(mixerpath);
|
||||
|
||||
-#if defined(__OpenBSD__)
|
||||
- int oclass_idx = -1, master_idx = -1, master_mute_idx = -1;
|
||||
- int master_next = AUDIO_MIXER_LAST;
|
||||
- mixer_devinfo_t devinfo, devinfo2;
|
||||
- mixer_ctrl_t vinfo;
|
||||
-
|
||||
- devinfo.index = 0;
|
||||
- while (ioctl(mixfd, AUDIO_MIXER_DEVINFO, &devinfo) >= 0) {
|
||||
- if (devinfo.type != AUDIO_MIXER_CLASS) {
|
||||
- devinfo.index++;
|
||||
- continue;
|
||||
- }
|
||||
- if (strncmp(devinfo.label.name, AudioCoutputs, MAX_AUDIO_DEV_LEN) == 0)
|
||||
- oclass_idx = devinfo.index;
|
||||
-
|
||||
- devinfo.index++;
|
||||
- }
|
||||
-
|
||||
- devinfo2.index = 0;
|
||||
- while (ioctl(mixfd, AUDIO_MIXER_DEVINFO, &devinfo2) >= 0) {
|
||||
- if ((devinfo2.type == AUDIO_MIXER_VALUE) && (devinfo2.mixer_class == oclass_idx) && (strncmp(devinfo2.label.name, AudioNmaster, MAX_AUDIO_DEV_LEN) == 0)) {
|
||||
- master_idx = devinfo2.index;
|
||||
- master_next = devinfo2.next;
|
||||
- }
|
||||
-
|
||||
- if ((devinfo2.type == AUDIO_MIXER_ENUM) && (devinfo2.mixer_class == oclass_idx) && (strncmp(devinfo2.label.name, AudioNmute, MAX_AUDIO_DEV_LEN) == 0))
|
||||
- if (master_next == devinfo2.index)
|
||||
- master_mute_idx = devinfo2.index;
|
||||
-
|
||||
- if (master_next != AUDIO_MIXER_LAST)
|
||||
- master_next = devinfo2.next;
|
||||
- devinfo2.index++;
|
||||
- }
|
||||
-
|
||||
- if (master_idx == -1)
|
||||
- goto out;
|
||||
-
|
||||
- devinfo.index = master_idx;
|
||||
- if (ioctl(mixfd, AUDIO_MIXER_DEVINFO, &devinfo) == -1)
|
||||
- goto out;
|
||||
-
|
||||
- vinfo.dev = master_idx;
|
||||
- vinfo.type = AUDIO_MIXER_VALUE;
|
||||
- vinfo.un.value.num_channels = devinfo.un.v.num_channels;
|
||||
- if (ioctl(mixfd, AUDIO_MIXER_READ, &vinfo) == -1)
|
||||
- goto out;
|
||||
-
|
||||
- if (AUDIO_MAX_GAIN != 100) {
|
||||
- float avgf = ((float)vinfo.un.value.level[AUDIO_MIXER_LEVEL_MONO] / AUDIO_MAX_GAIN) * 100;
|
||||
- vol = (int)avgf;
|
||||
- vol = (avgf - vol < 0.5 ? vol : (vol + 1));
|
||||
- } else {
|
||||
- vol = (int)vinfo.un.value.level[AUDIO_MIXER_LEVEL_MONO];
|
||||
- }
|
||||
-
|
||||
- vinfo.dev = master_mute_idx;
|
||||
- vinfo.type = AUDIO_MIXER_ENUM;
|
||||
- if (ioctl(mixfd, AUDIO_MIXER_READ, &vinfo) == -1)
|
||||
- goto out;
|
||||
-
|
||||
- if (master_mute_idx != -1 && vinfo.un.ord) {
|
||||
- START_COLOR("color_degraded");
|
||||
- fmt = fmt_muted;
|
||||
- pbval = 0;
|
||||
- }
|
||||
-
|
||||
-#else
|
||||
if (ioctl(mixfd, SOUND_MIXER_READ_DEVMASK, &devmask) == -1) {
|
||||
warn("OSS: Cannot read mixer information");
|
||||
goto out;
|
||||
@@ -353,7 +287,6 @@ void print_volume(yajl_gen json_gen, char *buffer, con
|
||||
pbval = 0;
|
||||
}
|
||||
|
||||
-#endif
|
||||
outwalk = apply_volume_format(fmt, outwalk, vol & 0x7f, devicename);
|
||||
close(mixfd);
|
||||
#endif
|
176
x11/i3status/patches/patch-src_sndio_c
Normal file
176
x11/i3status/patches/patch-src_sndio_c
Normal file
@ -0,0 +1,176 @@
|
||||
$OpenBSD: patch-src_sndio_c,v 1.1 2020/03/16 14:54:45 ratchov Exp $
|
||||
|
||||
Add sndio volume backend.
|
||||
|
||||
Index: src/sndio.c
|
||||
--- src/sndio.c.orig
|
||||
+++ src/sndio.c
|
||||
@@ -0,0 +1,168 @@
|
||||
+#include <poll.h>
|
||||
+#include <sndio.h>
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+#include "i3status.h"
|
||||
+
|
||||
+struct control {
|
||||
+ struct control *next;
|
||||
+ unsigned int addr;
|
||||
+ unsigned int max;
|
||||
+ unsigned int value;
|
||||
+};
|
||||
+
|
||||
+static int initialized;
|
||||
+static struct sioctl_hdl *hdl;
|
||||
+static struct control *controls;
|
||||
+static struct pollfd *pfds;
|
||||
+
|
||||
+/*
|
||||
+ * new control registered or control changed
|
||||
+ */
|
||||
+static void ondesc(void *unused, struct sioctl_desc *d, int val)
|
||||
+{
|
||||
+ struct control *i, **pi;
|
||||
+
|
||||
+ if (d == NULL)
|
||||
+ return;
|
||||
+
|
||||
+ /*
|
||||
+ * delete existing control with the same address
|
||||
+ */
|
||||
+ for (pi = &controls; (i = *pi) != NULL; pi = &i->next) {
|
||||
+ if (d->addr == i->addr) {
|
||||
+ *pi = i->next;
|
||||
+ free(i);
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * we're interested in top-level output.level controls only
|
||||
+ */
|
||||
+ if (d->type != SIOCTL_NUM ||
|
||||
+ d->group[0] != 0 ||
|
||||
+ strcmp(d->node0.name, "output") != 0 ||
|
||||
+ strcmp(d->func, "level") != 0)
|
||||
+ return;
|
||||
+
|
||||
+ i = malloc(sizeof(struct control));
|
||||
+ if (i == NULL) {
|
||||
+ fprintf(stderr, "sndio: failed to allocate control\n");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ i->addr = d->addr;
|
||||
+ i->max = d->maxval;
|
||||
+ i->value = val;
|
||||
+ i->next = controls;
|
||||
+ controls = i;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * control value changed
|
||||
+ */
|
||||
+static void onval(void *unused, unsigned int addr, unsigned int value)
|
||||
+{
|
||||
+ struct control *c;
|
||||
+
|
||||
+ for (c = controls; ; c = c->next) {
|
||||
+ if (c == NULL)
|
||||
+ return;
|
||||
+ if (c->addr == addr)
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ c->value = value;
|
||||
+}
|
||||
+
|
||||
+static void cleanup(void)
|
||||
+{
|
||||
+ struct control *c;
|
||||
+
|
||||
+ if (hdl) {
|
||||
+ sioctl_close(hdl);
|
||||
+ hdl = NULL;
|
||||
+ }
|
||||
+ if (pfds) {
|
||||
+ free(pfds);
|
||||
+ pfds = NULL;
|
||||
+ }
|
||||
+ while ((c = controls) != NULL) {
|
||||
+ controls = c->next;
|
||||
+ free(c);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int init(void)
|
||||
+{
|
||||
+ /* open device */
|
||||
+ hdl = sioctl_open(SIO_DEVANY, SIOCTL_READ, 0);
|
||||
+ if (hdl == NULL) {
|
||||
+ fprintf(stderr, "sndio: cannot open device\n");
|
||||
+ goto failed;
|
||||
+ }
|
||||
+
|
||||
+ /* register call-back for control description changes */
|
||||
+ if (!sioctl_ondesc(hdl, ondesc, NULL)) {
|
||||
+ fprintf(stderr, "sndio: cannot get description\n");
|
||||
+ goto failed;
|
||||
+ }
|
||||
+
|
||||
+ /* register call-back for volume changes */
|
||||
+ if (!sioctl_onval(hdl, onval, NULL)) {
|
||||
+ fprintf(stderr, "sndio: cannot get values\n");
|
||||
+ goto failed;
|
||||
+ }
|
||||
+
|
||||
+ /* allocate structures for poll() syscall */
|
||||
+ pfds = calloc(sioctl_nfds(hdl), sizeof(struct pollfd));
|
||||
+ if (pfds == NULL) {
|
||||
+ fprintf(stderr, "sndio: cannot allocate pollfd structures\n");
|
||||
+ goto failed;
|
||||
+ }
|
||||
+ return 1;
|
||||
+failed:
|
||||
+ cleanup();
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int volume_sndio(void)
|
||||
+{
|
||||
+ struct control *c;
|
||||
+ int n, v, value;
|
||||
+
|
||||
+ if (!initialized) {
|
||||
+ initialized = 1;
|
||||
+ init();
|
||||
+ }
|
||||
+ if (hdl == NULL)
|
||||
+ return -1;
|
||||
+
|
||||
+ /* check if controls changed */
|
||||
+ n = sioctl_pollfd(hdl, pfds, POLLIN);
|
||||
+ if (n > 0) {
|
||||
+ n = poll(pfds, n, 0);
|
||||
+ if (n > 0) {
|
||||
+ if (sioctl_revents(hdl, pfds) & POLLHUP) {
|
||||
+ fprintf(stderr, "sndio: disconnected\n");
|
||||
+ cleanup();
|
||||
+ return -1;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * get control value: as there may be multiple
|
||||
+ * channels, return the minimum
|
||||
+ */
|
||||
+ value = 100;
|
||||
+ for (c = controls; c != NULL; c = c->next) {
|
||||
+ v = (c->value * 100 + c->max / 2) / c->max;
|
||||
+ if (v < value)
|
||||
+ value = v;
|
||||
+ }
|
||||
+
|
||||
+ return value;
|
||||
+}
|
Loading…
x
Reference in New Issue
Block a user