This diff makes gqmpeg use sndio to display and control the
volume. This fixes the crash when the volume slider is touched. As a
side effect, this makes gqmpeg use the right device (one that's
playing) and nicely updates the slider position when other programs
change the master volume.

OK?

Index: Makefile
===================================================================
RCS file: /cvs/ports/audio/gqmpeg/Makefile,v
retrieving revision 1.64
diff -u -p -r1.64 Makefile
--- Makefile    12 Jul 2019 20:43:33 -0000      1.64
+++ Makefile    8 Mar 2020 15:39:53 -0000
@@ -3,7 +3,7 @@
 COMMENT=               front-end to various audio players
 
 DISTNAME=              gqmpeg-0.91.1
-REVISION=              14
+REVISION=              15
 CATEGORIES=            audio
 
 HOMEPAGE=              http://gqmpeg.sourceforge.net/
Index: patches/patch-src_Makefile_in
===================================================================
RCS file: patches/patch-src_Makefile_in
diff -N patches/patch-src_Makefile_in
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ patches/patch-src_Makefile_in       8 Mar 2020 15:39:53 -0000
@@ -0,0 +1,14 @@
+$OpenBSD$
+
+Index: src/Makefile.in
+--- src/Makefile.in.orig
++++ src/Makefile.in
+@@ -342,7 +342,7 @@ gqmpeg_SOURCES = \
+       $(module_mpg123) $(module_xmp) $(module_ogg123) $(module_radio)
+ 
+ 
+-gqmpeg_LDADD = $(GTK_LIBS) $(LIBPNG)
++gqmpeg_LDADD = $(GTK_LIBS) $(LIBPNG) -lsndio
+ 
+ EXTRA_DIST = \
+       $(extra_SLIK)   \
Index: patches/patch-src_mixer_c
===================================================================
RCS file: /cvs/ports/audio/gqmpeg/patches/patch-src_mixer_c,v
retrieving revision 1.2
diff -u -p -r1.2 patch-src_mixer_c
--- patches/patch-src_mixer_c   14 Oct 2007 14:12:42 -0000      1.2
+++ patches/patch-src_mixer_c   8 Mar 2020 15:39:53 -0000
@@ -1,39 +1,288 @@
 $OpenBSD: patch-src_mixer_c,v 1.2 2007/10/14 14:12:42 jasper Exp $
---- src/mixer.c.orig   Tue Sep 10 16:16:26 2002
-+++ src/mixer.c        Sun Oct 14 15:47:27 2007
-@@ -285,7 +285,11 @@ void mixer_init(gint init_device_id)
- 
-   mixer_device = getenv("MIXERDEVICE");
-   if (mixer_device == NULL)
-+#ifdef __OpenBSD__
-+    mixer_device = "/dev/mixer";
-+#else
-     mixer_device = "/dev/mixer0";
-+#endif
+Index: src/mixer.c
+--- src/mixer.c.orig
++++ src/mixer.c
+@@ -39,10 +39,16 @@
+ #include <sys/soundcard.h>
+ #endif
  
-   if ((fd = open(mixer_device, O_RDWR)) == -1) {
-     perror(mixer_device);
-@@ -362,7 +366,11 @@ static void mixer_set_vol(DeviceData *device, gint vol
- 
-   mixer_device = getenv("MIXERDEVICE");
-   if (mixer_device == NULL)
-+#ifdef __OpenBSD__
-+    mixer_device = "/dev/mixer";
-+#else
-     mixer_device = "/dev/mixer0";
-+#endif
+-#if defined(__NetBSD__) || defined(__OpenBSD__)
++#if defined(__NetBSD__)
+ #include <sys/audioio.h>
+ #endif
  
-   if ((fd = open(mixer_device, O_RDWR)) == -1) {
-     perror(mixer_device);
-@@ -406,7 +414,11 @@ static gint mixer_get_vol(DeviceData *device)
- 
-   mixer_device = getenv("MIXERDEVICE");
-   if (mixer_device == NULL)
-+#ifdef __OpenBSD__
-+    mixer_device = "/dev/mixer";
-+#else
-     mixer_device = "/dev/mixer0";
++#if defined(__OpenBSD__)
++#include <poll.h>
++#include <sndio.h>
++#include "display.h"
 +#endif
++
+ #if defined(sun) && defined(__svr4__)
+ #include <sys/audioio.h>
+ #endif
+@@ -267,11 +273,11 @@ static gint mixer_get_vol(DeviceData *device)
+ 
+ /*
+  *--------------------------------------------------------------------
+- * NetBSD and OpenBSD
++ * NetBSD
+  *--------------------------------------------------------------------
+  */
+ 
+-#elif defined(__NetBSD__) || defined(__OpenBSD__)
++#elif defined(__NetBSD__)
+ 
+ mixer_devinfo_t *infos;
+ mixer_ctrl_t *values;
+@@ -442,6 +448,242 @@ static gint mixer_get_vol(DeviceData *device)
+ 
+ /*
+  *--------------------------------------------------------------------
++ * OpenBSD
++ *--------------------------------------------------------------------
++ */
++
++#elif defined(__OpenBSD__)
++
++struct control {
++      struct control *next;
++      unsigned int addr;
++      unsigned int max, value;
++};
++
++static struct control *controls;
++static struct sioctl_hdl *hdl;
++static struct pollfd *pfds;
++static int initialized;
++
++/*
++ * new control registered
++ */
++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;
++              }
++      }
++
++      /*
++       * SIOCTL_NONE means control was deleted from the device
++       */
++      if (d->type == SIOCTL_NONE)
++              return;
++
++      /*
++       * we're interested in top-level output.level controls only
++       */
++      if (d->group[0] != 0 ||
++          strcmp(d->node0.name, "output") != 0 ||
++          strcmp(d->func, "level") != 0)
++              return;
++
++      i = malloc(sizeof(struct control));
++      if (i == NULL) {
++              perror("malloc");
++              return;
++      }
++
++      i->addr = d->addr;
++      i->max = d->maxval;
++      i->value = val;
++      i->next = controls;
++      controls = i;
++
++      if (debug_mode)
++              fprintf(stderr, "found output.level at %d\n", i->addr);
++}
++
++/*
++ * control value changed
++ */
++static void onval(void *unused, unsigned int addr, unsigned int value)
++{
++      struct control *c;
++
++      if (debug_mode)
++              fprintf(stderr, "control %d changed to %d\n", addr, value);
++
++      for (c = controls; ; c = c->next) {
++              if (c == NULL)
++                      return;
++              if (c->addr == addr)
++                      break;
++      }
++
++      c->value = value;
++
++      if (debug_mode)
++              fprintf(stderr, "refreshing\n");
++      display_set_volume();
++}
++
++/*
++ * Call poll(2), for both gtk and sndio descriptors.
++ */
++int
++do_poll(GPollFD *gtk_pfds, guint gtk_nfds, gint timeout)
++{
++#define MAXFDS 64
++      struct pollfd pfds[MAXFDS], *sioctl_pfds;
++      unsigned int sioctl_nfds;
++      unsigned int i;
++      int revents;
++      int rc;
++
++      for (i = 0; i < gtk_nfds; i++) {
++              pfds[i].fd = gtk_pfds[i].fd;
++              pfds[i].events = gtk_pfds[i].events;
++      }
++      if (hdl != NULL) {
++              sioctl_pfds = pfds + gtk_nfds;
++              sioctl_nfds = sioctl_pollfd(hdl, sioctl_pfds, POLLIN);
++      } else
++              sioctl_nfds = 0;
++
++      rc = poll(pfds, gtk_nfds + sioctl_nfds, timeout);
++      if (rc > 0 && hdl != NULL) {
++              revents = sioctl_revents(hdl, sioctl_pfds);
++              if (revents & POLLHUP) {
++                      fprintf(stderr, "Device disconnected\n");
++                      sioctl_close(hdl);
++                      hdl = NULL;
++              }
++      }
++
++      for (i = 0; i < gtk_nfds; i++)
++              gtk_pfds[i].revents = pfds[i].revents;
++
++      return rc;
++}
++
++void mixer_init(gint init_device_id)
++{
++      if (debug_mode)
++              fprintf(stderr, "mixer, initializing...\n");
++
++      if (initialized) {
++              fprintf(stderr, "mixer, already initialized\n");
++              return;
++      }
++
++      initialized = 1;
++      
++      hdl = sioctl_open(SIO_DEVANY, SIOCTL_READ | SIOCTL_WRITE, 0);
++      if (hdl == NULL) {
++              fprintf(stderr, "Cannot open audio control device\n");
++              mixer_enabled = FALSE;
++              return;
++      }
++      if (!sioctl_ondesc(hdl, ondesc, NULL)) {
++              sioctl_close(hdl);
++              fprintf(stderr, "Cannot get mixer information\n");
++              mixer_enabled = FALSE;
++              return;
++      }
++
++      /* register call-back for external volume changes */
++      if (!sioctl_onval(hdl, onval, NULL)) {
++              sioctl_close(hdl);
++              fprintf(stderr, "Cannot get mixer values\n");
++              mixer_enabled = FALSE;
++              return;
++      }
++
++      pfds = malloc(sizeof(struct pollfd) * sioctl_nfds(hdl));
++      if (pfds == NULL) {
++              sioctl_close(hdl);
++              fprintf(stderr, "Cannot allocate pollfd structures\n");
++              mixer_enabled = FALSE;
++              return;
++      }
++
++      if (controls != NULL) {
++              DeviceData *device = g_new0(DeviceData, 1);
++              device->device_id = 0;
++              device->device_name = "output.level";
++              device->stereo = (controls->next != NULL);
++              device->recordable = 0;
++              device_list = g_list_append(device_list, device);
++              current_device = device_list->data;
++              current_vol = mixer_get_vol(current_device);
++              mixer_enabled = TRUE;
++      } else
++              mixer_enabled = FALSE;
++
++      if (debug_mode)
++              fprintf(stderr, "setting gtk poll function\n");
++      g_main_context_set_poll_func(g_main_context_default(), do_poll);
++
++}
++
++static void mixer_poll(void)
++{
++      int n, nfds;
++
++      nfds = sioctl_pollfd(hdl, pfds, 0);
++      if (nfds > 0) {
++              n = poll(pfds, nfds, 0);
++              if (n >= 0)
++                      sioctl_revents(hdl, pfds);
++      }
++}
++
++static void mixer_set_vol(DeviceData *device, gint vol)
++{
++      struct control *c;
++
++      if (hdl == NULL)
++              return;
++
++      for (c = controls; c != NULL; c = c->next) {
++              sioctl_setval(hdl, c->addr, (vol * c->max + 50) / 100);
++              if (debug_mode)
++                      fprintf(stderr, "setting %d to %d%%\n", c->addr, vol);
++      }
++}
++
++static gint mixer_get_vol(DeviceData *device)
++{
++      struct control *c;
++      int vol, minvol = 100;
++
++      for (c = controls; c != NULL; c = c->next) {
++              vol = (c->value * 100 + c->max / 2) / c->max;
++              if (vol < minvol)
++                      minvol = vol;
++      }
++
++      if (debug_mode)
++              fprintf(stderr, "get volume: %d\n", minvol);
++
++      return minvol;
++}
++
++/*
++ *--------------------------------------------------------------------
+  * Sun (svr4)
+  *--------------------------------------------------------------------
+  */
+@@ -1266,7 +1508,7 @@ gint get_volume(void)
+  * but some platforms did not have it update the volume (mixer_get_vol),
+  * and I am not going to mess with it.
+  */
+-#if defined (linux) || defined (__FreeBSD__)
++#if defined (linux) || defined (__FreeBSD__) || defined (__OpenBSD__)
+       current_vol = mixer_get_vol(current_device);
+ #endif
  
-   if ((fd = open(mixer_device, O_RDWR)) == -1) {
-     perror(mixer_device);

Reply via email to