Recently Written · git

sad

sad (2f30.org simple audio daemon) with a Cygwin/OSS port on branch cygwin

git clone https://github.com/equwal/sad

Log | Files | Refs


commit 45deefea71b908e2a0019b5b1fff34a89d80bb22
Spenser Truex <truex@equwal.com>
2021-01-20 13:02:28 -0800

Add support for the 'status volume' PROTOCOL

Previously this was documented in the PROTOCOL document, though never
implemented, and it is a very useful command.

The other unimplemented parts of the PROTOCOL are
status elapsed: total time elapsed within current song in seconds (not implemented)
status duration: total song duration in seconds (not implemented)

I tested the alsa and sndio variants. The FIFO variant is just always
100.

Test case (alsa or sndio):
$ echo 'status volume' | nc -NU $SOCK
volume: 100
OK
$ echo 'volume 10' | nc -NU $SOCK
volume: 10
OK
$ echo 'status volume' | nc -NU $SOCK
volume: 10
OK
$

Test case (FIFO):
$ echo 'status volume' | nc -NU $SOCK
volume: 100
OK
$ echo 'volume 10' | nc -NU $SOCK
volume: 100                             <----- 100
OK
$ echo 'status volume' | nc -NU $SOCK
volume: 100                             <----- 100
OK
$

 PROTOCOL |  4 ++--
 alsa.c   |  4 ++++
 cmd.c    |  5 ++++-
 fifo.c   |  3 +++
 output.c | 18 +++++++++++++++++-
 sad.h    |  3 +++
 sndio.c  |  4 ++++
 7 files changed, 37 insertions(+), 4 deletions(-)
diff --git a/PROTOCOL b/PROTOCOL
index c702799..3373665 100644
--- a/PROTOCOL
+++ b/PROTOCOL
@@ -78,8 +78,8 @@ Possible states:
 	songid: songid of the current song stopped on or playing
 	playback: either play, stop or pause
 	volume: 0-100
-	elapsed: total time elapsed within current song in seconds
-	duration: total song duration in seconds
+	elapsed: total time elapsed within current song in seconds (not implemented)
+	duration: total song duration in seconds (not implemented)
 
 wait event-name
 Subscribe to the provided event.  When the event triggers, a reply will
diff --git a/alsa.c b/alsa.c
index f349c55..e06ddd7 100644
--- a/alsa.c
+++ b/alsa.c
@@ -10,6 +10,7 @@
 static snd_pcm_t *hdl;
 static int framesize;
 static const char *device = "default"; /* TODO: make configurable? */
+int alsavolstatus = DEFAULTVOL;
 
 static int
 alsavol(int vol)
@@ -51,6 +52,7 @@ alsavol(int vol)
 
 	snd_mixer_selem_get_playback_volume_range(elem, &min, &max);
 	snd_mixer_selem_set_playback_volume_all(elem, vol * max / 100);
+    alsavolstatus = vol;
 
 	snd_mixer_close(mixerhdl);
 	return 0;
@@ -115,8 +117,10 @@ alsaclose(void)
 }
 
 Output alsaoutput = {
+    .volstatus = &alsavolstatus,
 	.vol = alsavol,
 	.open = alsaopen,
 	.play = alsaplay,
 	.close = alsaclose,
 };
+
diff --git a/cmd.c b/cmd.c
index a8528df..3d673f1 100644
--- a/cmd.c
+++ b/cmd.c
@@ -32,7 +32,10 @@ cmdstatus(int fd, char *arg)
 	} else if (!strncmp(arg, "single", 7)) {
 		r = 1;
 		dprintf(fd, "single: %d\n", (getplaylistmode() & SINGLE) == 1);
-	} else if (!strncmp(arg, "songid", 7)) {
+	} else if (!strncmp(arg, "volume", 7)) {
+        r = 1;
+        dprintf(fd, "volume: %d\n", getvol());
+    } else if (!strncmp(arg, "songid", 7)) {
 		r = 1;
 		s = getcursong();
 
diff --git a/fifo.c b/fifo.c
index 6331ebc..a41558b 100644
--- a/fifo.c
+++ b/fifo.c
@@ -12,6 +12,8 @@
 
 static int fifofd = -1;
 
+int fifovolstatus = DEFAULTVOL;
+
 static int
 fifovol(int vol)
 {
@@ -69,6 +71,7 @@ fifoclose(void)
 }
 
 Output fifooutput = {
+    .volstatus = &fifovolstatus,
 	.vol = fifovol,
 	.open = fifoopen,
 	.play = fifoplay,
diff --git a/output.c b/output.c
index 9a1937e..ceb3e11 100644
--- a/output.c
+++ b/output.c
@@ -119,6 +119,20 @@ openoutputs(void)
 	return r;
 }
 
+int
+getvol(void)
+{
+    Outputdesc *desc;
+	size_t i;
+	for (i = 0; i < LEN(outputdescs); i++) {
+		desc = &outputdescs[i];
+		if (!desc->enabled)
+			continue;
+		return *desc->output->volstatus;
+	}
+	return -1;
+}
+
 static int
 closeoutput(Outputdesc *desc)
 {
@@ -245,8 +259,10 @@ setvol(int vol)
 		desc = &outputdescs[i];
 		if (!desc->enabled)
 			continue;
-		if (desc->output->vol(vol) < 0)
+		if (desc->output->vol(vol) < 0) {
 			r = -1;
+            *desc->output->volstatus = vol;
+        }
 	}
 	return r;
 }
diff --git a/sad.h b/sad.h
index 38f7e5f..3d18866 100644
--- a/sad.h
+++ b/sad.h
@@ -4,6 +4,7 @@
 
 #define LEN(x) (sizeof (x) / sizeof *(x))
 #define PROTOCOLVERSION "0.0"
+#define DEFAULTVOL 100
 
 typedef struct {
 	char  *name;
@@ -40,6 +41,7 @@ typedef struct {
 } Decoder;
 
 typedef struct {
+    int *volstatus;
 	int (*vol)(int);
 	int (*open)(Format *);
 	int (*play)(void *, size_t);
@@ -127,6 +129,7 @@ int enableoutput(const char *);
 int disableoutput(const char *);
 int playoutputs(Format *, void *, size_t);
 int setvol(int);
+int getvol(void);
 
 /* notify.c */
 extern Eventdesc Eventmap[];
diff --git a/sndio.c b/sndio.c
index 803fd8e..0b370f2 100644
--- a/sndio.c
+++ b/sndio.c
@@ -8,6 +8,7 @@
 #include "sad.h"
 
 static struct sio_hdl *hdl;
+int sndiovolstatus = DEFAULTVOL;
 
 static int
 sndiovol(int vol)
@@ -16,6 +17,7 @@ sndiovol(int vol)
 		warnx("sio_setvol: failed");
 		return -1;
 	}
+    sndiovolstatus = vol;
 	return 0;
 }
 
@@ -78,8 +80,10 @@ sndioclose(void)
 }
 
 Output sndiooutput = {
+    .volstatus = &sndiovolstatus,
 	.vol = sndiovol,
 	.open = sndioopen,
 	.play = sndioplay,
 	.close = sndioclose,
 };
+