Commit Diff


commit - 069e653bc1e64578b0a97465a2016b7dc0bf3f56
commit + 06ceb3767eb7e480de05cd50f4fbaf75fb3322a2
blob - 7b9eb922ca793410bf8c7c3ef53d5387f0cf41dd
blob + ed6eac93eeae2b298b126764266afb1ebaf7ca0e
--- Makefile
+++ Makefile
@@ -5,6 +5,7 @@ PROG =		amused
 DISTNAME =	${PROG}-${VERSION}
 
 SOURCES =	amused.c \
+		audio_sndio.c \
 		compats.c \
 		control.c \
 		ctl.c \
@@ -93,6 +94,7 @@ ${DISTNAME}.tar.gz: ${DISTFILES}
 # supports it.
 
 -include amused.d
+-include audio_sndio.d
 -include compats.d
 -include control.d
 -include ctl.d
blob - fc49a771a10bbb1a9f2e3fa8767085c0d51fe99b
blob + 8e43ca26a080662b1a3be57c37217cdb5ac8953d
--- amused.h
+++ amused.h
@@ -138,6 +138,7 @@ struct ctl_command {
 };
 
 struct playlist;
+struct pollfd;
 
 /* amused.c */
 void		spawn_daemon(void);
@@ -156,6 +157,17 @@ void		main_send_playlist(struct imsgev *);
 void		main_send_status(struct imsgev *);
 void		main_seek(struct player_seek *);
 
+/* audio_*.c */
+int		audio_open(void (*)(void *, int));
+int		audio_setup(unsigned int, unsigned int, unsigned int,
+		    struct pollfd *);
+int		audio_nfds(void);
+int		audio_pollfd(struct pollfd *, int);
+int		audio_revents(struct pollfd *);
+size_t		audio_write(const void *, size_t);
+int		audio_flush(void);
+int		audio_stop(void);
+
 /* ctl.c */
 __dead void	usage(void);
 __dead void	ctl(int, char **);
blob - /dev/null
blob + 3a44d164a81a7d7317f6284e0b8c84aad10e3e30 (mode 644)
--- /dev/null
+++ audio_sndio.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2023 Omar Polo <op@omarpolo.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "config.h"
+
+#include <errno.h>
+#include <limits.h>
+#include <poll.h>
+#include <sndio.h>
+#include <stdio.h>
+
+#include "amused.h"
+#include "log.h"
+
+static struct sio_hdl		*hdl;
+static struct sio_par		 par;
+static int			 stopped = 1;
+
+int
+audio_open(void (*onmove_cb)(void *, int))
+{
+	if ((hdl = sio_open(SIO_DEVANY, SIO_PLAY, 1)) == NULL)
+		return -1;
+
+	sio_onmove(hdl, onmove_cb, NULL);
+	return 0;
+}
+
+int
+audio_setup(unsigned int bits, unsigned int rate, unsigned int channels,
+    struct pollfd *pfds)
+{
+	int		 nfds, fpct;
+
+	fpct = (rate * 5) / 100;
+
+	/* don't stop if the parameters are the same */
+	if (bits == par.bits && channels == par.pchan &&
+	    par.rate - fpct <= rate && rate <= par.rate + fpct) {
+		if (stopped)
+			goto start;
+		return 0;
+	}
+
+ again:
+	if (!stopped) {
+		sio_stop(hdl);
+		stopped = 1;
+	}
+
+	sio_initpar(&par);
+	par.bits = bits;
+	par.rate = rate;
+	par.pchan = channels;
+	if (!sio_setpar(hdl, &par)) {
+		if (errno == EAGAIN) {
+			nfds = sio_pollfd(hdl, pfds, POLLOUT);
+			if (poll(pfds, nfds, INFTIM) == -1)
+				fatal("poll");
+			goto again;
+		}
+		log_warnx("invalid params (bits=%u, rate=%u, channels=%u)",
+		    bits, rate, channels);
+		return -1;
+	}
+	if (!sio_getpar(hdl, &par)) {
+		log_warnx("can't get params");
+		return -1;
+	}
+
+	if (par.bits != bits || par.pchan != channels) {
+		log_warnx("failed to set params");
+		return -1;
+	}
+
+	/* TODO: check sample rate? */
+
+ start:
+	if (!sio_start(hdl)) {
+		log_warn("sio_start");
+		return -1;
+	}
+	stopped = 0;
+	return 0;
+}
+
+int
+audio_nfds(void)
+{
+	return sio_nfds(hdl);
+}
+
+int
+audio_pollfd(struct pollfd *pfds, int events)
+{
+	return sio_pollfd(hdl, pfds, events);
+}
+
+int
+audio_revents(struct pollfd *pfds)
+{
+	return sio_revents(hdl, pfds);
+}
+
+size_t
+audio_write(const void *buf, size_t len)
+{
+	return sio_write(hdl, buf, len);
+}
+
+int
+audio_flush(void)
+{
+	stopped = 1;
+	return sio_flush(hdl);
+}
+
+int
+audio_stop(void)
+{
+	stopped = 1;
+	return sio_stop(hdl);
+}
blob - a20334041994cda28a95a0e42e2bc12e2877b478
blob + 1bdef9ba7768c972ef5db3b2676830406134982e
--- player.c
+++ player.c
@@ -22,7 +22,6 @@
 #include <errno.h>
 #include <poll.h>
 #include <signal.h>
-#include <sndio.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdint.h>
@@ -34,15 +33,13 @@
 #include "log.h"
 #include "xmalloc.h"
 
-struct sio_hdl		*hdl;
-struct sio_par		 par;
 struct pollfd		*player_pfds;
 static struct imsgbuf	*ibuf;
 
-static int stopped = 1;
 static int nextfd = -1;
 static int64_t samples;
 static int64_t duration;
+static unsigned int current_rate;
 
 volatile sig_atomic_t halted;
 
@@ -55,61 +52,11 @@ player_signal_handler(int signo)
 int
 player_setup(unsigned int bits, unsigned int rate, unsigned int channels)
 {
-	int nfds, fpct;
-
 	log_debug("%s: bits=%u, rate=%u, channels=%u", __func__,
 	    bits, rate, channels);
 
-	fpct = (rate*5)/100;
-
-	/* don't stop if the parameters are the same */
-	if (bits == par.bits && channels == par.pchan &&
-	    par.rate - fpct <= rate && rate <= par.rate + fpct) {
-		if (stopped)
-			goto start;
-		return 0;
-	}
-
-again:
-	if (!stopped) {
-		sio_stop(hdl);
-		stopped = 1;
-	}
-
-	sio_initpar(&par);
-	par.bits = bits;
-	par.rate = rate;
-	par.pchan = channels;
-	if (!sio_setpar(hdl, &par)) {
-		if (errno == EAGAIN) {
-			nfds = sio_pollfd(hdl, player_pfds + 1, POLLOUT);
-			if (poll(player_pfds + 1, nfds, INFTIM) == -1)
-				fatal("poll");
-			goto again;
-		}
-		log_warnx("invalid params (bits=%d, rate=%d, channels=%d",
-		    bits, rate, channels);
-		return -1;
-	}
-	if (!sio_getpar(hdl, &par)) {
-		log_warnx("can't get params");
-		return -1;
-	}
-
-	if (par.bits != bits || par.pchan != channels) {
-		log_warnx("failed to set params");
-		return -1;
-	}
-
-	/* TODO: check the sample rate? */
-
-start:
-	if (!sio_start(hdl)) {
-		log_warn("sio_start");
-		return -1;
-	}
-	stopped = 0;
-	return 0;
+	current_rate = rate;
+	return audio_setup(bits, rate, channels, player_pfds + 1);
 }
 
 void
@@ -118,7 +65,7 @@ player_setduration(int64_t d)
 	int64_t seconds;
 
 	duration = d;
-	seconds = duration / par.rate;
+	seconds = duration / current_rate;
 	imsg_compose(ibuf, IMSG_LEN, 0, 0, -1, &seconds, sizeof(seconds));
 	imsg_flush(ibuf);
 }
@@ -130,9 +77,9 @@ player_onmove(void *arg, int delta)
 	int64_t sec;
 
 	samples += delta;
-	if (llabs(samples - reported) >= par.rate) {
+	if (llabs(samples - reported) >= current_rate) {
 		reported = samples;
-		sec = samples / par.rate;
+		sec = samples / current_rate;
 
 		imsg_compose(ibuf, IMSG_POS, 0, 0, -1, &sec, sizeof(sec));
 		imsg_flush(ibuf);
@@ -200,7 +147,7 @@ again:
 		if (seek.percent) {
 			*s = (double)seek.offset * (double)duration / 100.0;
 		} else {
-			*s = seek.offset * par.rate;
+			*s = seek.offset * current_rate;
 			if (seek.relative)
 				*s += samples;
 		}
@@ -310,26 +257,25 @@ play(const void *buf, size_t len, int64_t *s)
 
 	*s = -1;
 	while (len != 0) {
-		nfds = sio_pollfd(hdl, player_pfds + 1, POLLOUT);
+		nfds = audio_pollfd(player_pfds + 1, POLLOUT);
 		r = poll(player_pfds, nfds + 1, INFTIM);
 		if (r == -1)
 			fatal("poll");
 
 		wait = player_pfds[0].revents & (POLLHUP|POLLIN);
 		if (player_shouldstop(s, wait)) {
-			sio_flush(hdl);
-			stopped = 1;
+			audio_flush();
 			return 0;
 		}
 
-		revents = sio_revents(hdl, player_pfds + 1);
+		revents = audio_revents(player_pfds + 1);
 		if (revents & POLLHUP) {
 			if (errno == EAGAIN)
 				continue;
-			fatal("sndio hang-up");
+			fatal("audio hang-up");
 		}
 		if (revents & POLLOUT) {
-			w = sio_write(hdl, buf, len);
+			w = audio_write(buf, len);
 			len -= w;
 			buf += w;
 		}
@@ -358,13 +304,11 @@ player(int debug, int verbose)
 	}
 #endif
 
-	if ((hdl = sio_open(SIO_DEVANY, SIO_PLAY, 1)) == NULL)
-		fatal("sio_open");
+	if (audio_open(player_onmove) == -1)
+		fatal("audio_open");
 
-	sio_onmove(hdl, player_onmove, NULL);
-
 	/* allocate one extra for imsg */
-	player_pfds = calloc(sio_nfds(hdl) + 1, sizeof(*player_pfds));
+	player_pfds = calloc(audio_nfds() + 1, sizeof(*player_pfds));
 	if (player_pfds == NULL)
 		fatal("calloc");