Index | Thread | Search

From:
Alexandre Ratchov <alex@caoua.org>
Subject:
gstreamer: Add sndio device monitor (fixes audio in dino, maybe others)
To:
ports@openbsd.org
Cc:
kirill@korins.ky
Date:
Sun, 13 Jul 2025 16:48:36 +0200

Download raw body.

Thread
Few programs enumerate the audio devices at audio initialization and
abort if this fails. The net/dino port is one of them, which explains
why audio phone calls dont work.

This was discussed in this thread:

https://marc.info/?l=openbsd-misc&m=173183259932223&w=4

This diff adds the missing "device provider" class to the sndio
plugin. It just returns the defaut device, so programs that need to
enumerate the audio devices dont fail.

OK?

Index: Makefile
===================================================================
RCS file: /cvs/ports/multimedia/gstreamer1/plugins-base/Makefile,v
diff -u -p -u -p -r1.122 Makefile
--- Makefile	27 Jun 2025 10:12:15 -0000	1.122
+++ Makefile	13 Jul 2025 14:25:14 -0000
@@ -1,6 +1,7 @@
 COMMENT=		base elements for GStreamer
 
 DISTNAME=		gst-plugins-base-${V}
+REVISION=		0
 
 SHARED_LIBS += gsttag-1.0                7.3 # 0.2603.0
 SHARED_LIBS += gstfft-1.0                7.3 # 0.2603.0
Index: files/gstsndio.c
===================================================================
RCS file: /cvs/ports/multimedia/gstreamer1/plugins-base/files/gstsndio.c,v
diff -u -p -u -p -r1.4 gstsndio.c
--- files/gstsndio.c	21 Apr 2019 08:49:42 -0000	1.4
+++ files/gstsndio.c	13 Jul 2025 14:25:14 -0000
@@ -21,6 +21,7 @@
 
 #include <stdio.h>
 #include "gstsndio.h"
+#include "sndiodeviceprovider.h"
 
 GST_DEBUG_CATEGORY (gst_sndio_debug);
 #define GST_CAT_DEFAULT gst_sndio_debug
@@ -40,6 +41,9 @@ plugin_init (GstPlugin * plugin)
   /* prefer sndiosink over pulsesink (GST_RANK_PRIMARY + 10) */
   if (!gst_element_register (plugin, "sndiosink", GST_RANK_PRIMARY + 20,
           gst_sndiosink_get_type()))
+    return FALSE;
+  if (!gst_device_provider_register (plugin, "sndiodeviceprovider", GST_RANK_PRIMARY + 20,
+          gst_sndio_device_provider_get_type()))
     return FALSE;
   return TRUE;
 }
Index: files/meson.build
===================================================================
RCS file: /cvs/ports/multimedia/gstreamer1/plugins-base/files/meson.build,v
diff -u -p -u -p -r1.3 meson.build
--- files/meson.build	25 Jan 2023 08:31:52 -0000	1.3
+++ files/meson.build	13 Jul 2025 14:25:14 -0000
@@ -1,5 +1,7 @@
 sndio_sources = [
   'gstsndio.c',
+  'sndiodevice.c',
+  'sndiodeviceprovider.c',
   'sndiosink.c',
   'sndiosrc.c',
 ]
Index: files/sndiodevice.c
===================================================================
RCS file: files/sndiodevice.c
diff -N files/sndiodevice.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ files/sndiodevice.c	13 Jul 2025 14:25:14 -0000
@@ -0,0 +1,79 @@
+#include <string.h>
+#include <gst/gst.h>
+#include <sndio.h>
+#include <stdio.h>
+#include "gstsndio.h"
+#include "sndiodevice.h"
+
+G_DEFINE_TYPE (GstSndioDevice, gst_sndio_device, GST_TYPE_DEVICE);
+
+GstDevice *
+gst_sndio_device_new (const gchar *name, int mode)
+{
+  static GstStaticCaps sndio_caps = GST_STATIC_CAPS (GST_SNDIO_CAPS_STRING);
+  GstSndioDevice *sndio_device;
+  GstCaps *caps;
+  GstStructure *props;
+  const gchar *klass;
+
+  klass = (mode == SIO_REC) ? "Audio/Source" : "Audio/Sink";
+
+  caps = gst_static_caps_get (&sndio_caps);
+
+  props = gst_structure_new ("sndio-proplist",
+      "device.api", G_TYPE_STRING, "sndio",
+      "device.class", G_TYPE_STRING, "sound",
+      NULL);
+
+  sndio_device = g_object_new (GST_TYPE_SNDIO_DEVICE,
+      "display-name", name,
+      "caps", caps,
+      "device-class", klass,
+      "properties", props,
+      NULL);
+
+  sndio_device->mode = mode;
+
+  /* sndio_device owns 'caps' and 'props', so free ours */
+
+  gst_structure_free (props);
+  gst_caps_unref (caps);
+
+  return GST_DEVICE (sndio_device);
+}
+
+static GstElement *
+gst_sndio_device_create_element (GstDevice *device, const gchar *name)
+{
+  GstSndioDevice *sndio_device = GST_SNDIO_DEVICE (device);
+  GstElement *element;
+  const char *element_name;
+
+  element_name = (sndio_device->mode == SIO_REC) ? "sndiosrc" : "sndiosink";
+
+  element = gst_element_factory_make (element_name, name);
+  g_object_set (element, "device", gst_device_get_display_name(device), NULL);
+
+  return element;
+}
+
+static void
+gst_sndio_device_finalize (GObject *object)
+{
+  G_OBJECT_CLASS (gst_sndio_device_parent_class)->finalize (object);
+}
+
+static void
+gst_sndio_device_class_init (GstSndioDeviceClass *klass)
+{
+  GstDeviceClass *dev_class = GST_DEVICE_CLASS (klass);
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  dev_class->create_element = gst_sndio_device_create_element;
+  object_class->finalize = gst_sndio_device_finalize;
+}
+
+static void
+gst_sndio_device_init (GstSndioDevice *device)
+{
+}
Index: files/sndiodevice.h
===================================================================
RCS file: files/sndiodevice.h
diff -N files/sndiodevice.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ files/sndiodevice.h	13 Jul 2025 14:25:14 -0000
@@ -0,0 +1,40 @@
+#ifndef __GST_SNDIODEVICE_H__
+#define __GST_SNDIODEVICE_H__
+
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GstSndioDevice GstSndioDevice;
+typedef struct _GstSndioDeviceClass GstSndioDeviceClass;
+
+#define GST_TYPE_SNDIO_DEVICE \
+	(gst_sndio_device_get_type())
+#define GST_IS_SNDIO_DEVICE(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_SNDIO_DEVICE))
+#define GST_IS_SNDIO_DEVICE_CLASS(klass) \
+	(G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_SNDIO_DEVICE))
+#define GST_SNDIO_DEVICE_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_SNDIO_DEVICE, GstSndioDeviceClass))
+#define GST_SNDIO_DEVICE(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_SNDIO_DEVICE, GstSndioDevice))
+#define GST_SNDIO_DEVICE_CLASS(klass) \
+	(G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DEVICE, GstSndioDeviceClass))
+#define GST_SNDIO_DEVICE_CAST(obj) \
+	((GstSndioDevice *)(obj))
+
+struct _GstSndioDevice {
+  GstDevice parent;
+  int mode;
+};
+
+struct _GstSndioDeviceClass {
+  GstDeviceClass parent_class;
+};
+
+GstDevice *gst_sndio_device_new (const gchar *, int);
+GType gst_sndio_device_get_type (void);
+
+G_END_DECLS
+
+#endif
Index: files/sndiodeviceprovider.c
===================================================================
RCS file: files/sndiodeviceprovider.c
diff -N files/sndiodeviceprovider.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ files/sndiodeviceprovider.c	13 Jul 2025 14:25:14 -0000
@@ -0,0 +1,50 @@
+#include <string.h>
+#include <gst/gst.h>
+#include <sndio.h>
+#include <stdio.h>
+#include "sndiodeviceprovider.h"
+#include "sndiodevice.h"
+
+G_DEFINE_TYPE (GstSndioDeviceProvider, gst_sndio_device_provider, GST_TYPE_DEVICE_PROVIDER);
+
+static GList *
+gst_sndio_device_provider_probe (GstDeviceProvider *provider)
+{
+  GList *list = NULL;
+  GstDevice *device;
+  struct sio_hdl *hdl;
+
+  /*
+   * There's no way to discover all devices on the network, so
+   * just return the default device. The user can point it to
+   * any device.
+   */
+
+  device = gst_sndio_device_new (SIO_DEVANY, SIO_PLAY);
+  if (device)
+    list = g_list_prepend (list, device);
+
+  device = gst_sndio_device_new (SIO_DEVANY, SIO_REC);
+  if (device)
+    list = g_list_prepend (list, device);
+
+  return list;
+}
+
+static void
+gst_sndio_device_provider_class_init (GstSndioDeviceProviderClass *klass)
+{
+  GstDeviceProviderClass *dm_class = GST_DEVICE_PROVIDER_CLASS (klass);
+
+  dm_class->probe = gst_sndio_device_provider_probe;
+
+  gst_device_provider_class_set_static_metadata (dm_class,
+      "Sndio Device Provider", "Sink/Source/Audio",
+      "List and provide sndio source and sink devices",
+      "Alexandre Ratchov <alex@caoua.com>");
+}
+
+static void
+gst_sndio_device_provider_init (GstSndioDeviceProvider *self)
+{
+}
Index: files/sndiodeviceprovider.h
===================================================================
RCS file: files/sndiodeviceprovider.h
diff -N files/sndiodeviceprovider.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ files/sndiodeviceprovider.h	13 Jul 2025 14:25:14 -0000
@@ -0,0 +1,38 @@
+#ifndef __GST_SNDIODEVICEPROVIDER_H__
+#define __GST_SNDIODEVICEPROVIDER_H__
+
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GstSndioDeviceProvider GstSndioDeviceProvider;
+typedef struct _GstSndioDeviceProviderClass GstSndioDeviceProviderClass;
+
+#define GST_TYPE_SNDIO_DEVICE_PROVIDER \
+	(gst_sndio_device_provider_get_type())
+#define GST_IS_SNDIO_DEVICE_PROVIDER(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_SNDIO_DEVICE_PROVIDER))
+#define GST_IS_SNDIO_DEVICE_PROVIDER_CLASS(klass) \
+	(G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_SNDIO_DEVICE_PROVIDER))
+#define GST_SNDIO_DEVICE_PROVIDER_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_SNDIO_DEVICE_PROVIDER, GstSndioDeviceProviderClass))
+#define GST_SNDIO_DEVICE_PROVIDER(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_SNDIO_DEVICE_PROVIDER, GstSndioDeviceProvider))
+#define GST_SNDIO_DEVICE_PROVIDER_CLASS(klass) \
+	(G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DEVICE_PROVIDER, GstSndioDeviceProviderClass))
+#define GST_SNDIO_DEVICE_PROVIDER_CAST(obj) \
+	((GstSndioDeviceProvider *)(obj))
+
+struct _GstSndioDeviceProvider {
+  GstDeviceProvider parent;
+};
+
+struct _GstSndioDeviceProviderClass {
+  GstDeviceProviderClass parent_class;
+};
+
+GType gst_sndio_device_provider_get_type (void);
+
+G_END_DECLS
+
+#endif