5e6179159d
- Added (hopefully future upstream) patch for PipeWire support
1231 lines
31 KiB
Diff
1231 lines
31 KiB
Diff
From 5c473db1b9606134b400c0b1622df8740b16a0fc Mon Sep 17 00:00:00 2001
|
|
From: Christian Spielberger <c.spielberger@commend.com>
|
|
Date: Thu, 2 Feb 2023 08:52:54 +0100
|
|
Subject: [PATCH 01/10] pipewire: add pipewire module
|
|
|
|
---
|
|
cmake/FindPIPEWIRE.cmake | 10 ++
|
|
cmake/modules.cmake | 4 +
|
|
modules/pipewire/CMakeLists.txt | 17 ++++
|
|
modules/pipewire/capture.c | 163 ++++++++++++++++++++++++++++++++
|
|
modules/pipewire/pipewire.c | 161 +++++++++++++++++++++++++++++++
|
|
modules/pipewire/pipewire.h | 17 ++++
|
|
modules/pipewire/playback.c | 163 ++++++++++++++++++++++++++++++++
|
|
7 files changed, 535 insertions(+)
|
|
create mode 100644 cmake/FindPIPEWIRE.cmake
|
|
create mode 100644 modules/pipewire/CMakeLists.txt
|
|
create mode 100644 modules/pipewire/capture.c
|
|
create mode 100644 modules/pipewire/pipewire.c
|
|
create mode 100644 modules/pipewire/pipewire.h
|
|
create mode 100644 modules/pipewire/playback.c
|
|
|
|
diff --git a/cmake/FindPIPEWIRE.cmake b/cmake/FindPIPEWIRE.cmake
|
|
new file mode 100644
|
|
index 000000000..bd9b90181
|
|
--- /dev/null
|
|
+++ b/cmake/FindPIPEWIRE.cmake
|
|
@@ -0,0 +1,10 @@
|
|
+# Find the system's pipewire includes and library
|
|
+#
|
|
+# PIPEWIRE_INCLUDE_DIRS - where to find pipewire.h
|
|
+# PIPEWIRE_LIBRARIES - List of libraries when using pipewire
|
|
+# PIPEWIRE_FOUND - True if pipewire found
|
|
+
|
|
+if(NOT WIN32)
|
|
+ find_package(PkgConfig)
|
|
+ pkg_search_module(PIPEWIRE libpipewire-0.3)
|
|
+endif()
|
|
diff --git a/cmake/modules.cmake b/cmake/modules.cmake
|
|
index ed99bf835..e68835595 100644
|
|
--- a/cmake/modules.cmake
|
|
+++ b/cmake/modules.cmake
|
|
@@ -20,6 +20,7 @@ find_package(OPUS)
|
|
find_package(PNG)
|
|
find_package(PORTAUDIO)
|
|
find_package(PULSE)
|
|
+find_package(PIPEWIRE)
|
|
find_package(SDL)
|
|
find_package(SNDFILE)
|
|
find_package(SPANDSP)
|
|
@@ -140,6 +141,9 @@ endif()
|
|
if(PULSE_FOUND)
|
|
list(APPEND MODULES pulse)
|
|
endif()
|
|
+if(PIPEWIRE_FOUND)
|
|
+ list(APPEND MODULES pipewire)
|
|
+endif()
|
|
if(SDL_FOUND)
|
|
list(APPEND MODULES sdl)
|
|
endif()
|
|
diff --git a/modules/pipewire/CMakeLists.txt b/modules/pipewire/CMakeLists.txt
|
|
new file mode 100644
|
|
index 000000000..8673873af
|
|
--- /dev/null
|
|
+++ b/modules/pipewire/CMakeLists.txt
|
|
@@ -0,0 +1,17 @@
|
|
+project(pipewire)
|
|
+
|
|
+set(SRCS pipewire.c playback.c capture.c)
|
|
+
|
|
+if(STATIC)
|
|
+ add_library(${PROJECT_NAME} OBJECT ${SRCS})
|
|
+else()
|
|
+ add_library(${PROJECT_NAME} MODULE ${SRCS})
|
|
+endif()
|
|
+
|
|
+target_include_directories(${PROJECT_NAME} PRIVATE ${PIPEWIRE_INCLUDE_DIRS})
|
|
+target_link_directories(${PROJECT_NAME} PRIVATE ${PIPEWIRE_LIBRARY_DIRS})
|
|
+target_link_libraries(${PROJECT_NAME} PRIVATE ${PIPEWIRE_LIBRARIES})
|
|
+target_compile_options(${PROJECT_NAME} PRIVATE
|
|
+ -Wno-pedantic
|
|
+ -Wno-bad-function-cast
|
|
+)
|
|
diff --git a/modules/pipewire/capture.c b/modules/pipewire/capture.c
|
|
new file mode 100644
|
|
index 000000000..3e92d131c
|
|
--- /dev/null
|
|
+++ b/modules/pipewire/capture.c
|
|
@@ -0,0 +1,163 @@
|
|
+/**
|
|
+ * @file capture.c Pipewire sound driver - capture
|
|
+ *
|
|
+ * Copyright (C) 2023 Commend.com - c.spielberger@commend.com
|
|
+ */
|
|
+
|
|
+#include <string.h>
|
|
+#include <errno.h>
|
|
+#include <re.h>
|
|
+#include <rem.h>
|
|
+#include <baresip.h>
|
|
+#include <spa/param/audio/format-utils.h>
|
|
+#include <pipewire/pipewire.h>
|
|
+
|
|
+#include "pipewire.h"
|
|
+
|
|
+
|
|
+struct ausrc_st {
|
|
+ struct pw_stream *stream;
|
|
+
|
|
+ struct ausrc_prm prm;
|
|
+ ausrc_read_h *rh;
|
|
+ struct spa_hook listener;
|
|
+ ausrc_error_h *errh;
|
|
+
|
|
+ size_t sampsz;
|
|
+ uint64_t samps;
|
|
+
|
|
+ void *arg;
|
|
+};
|
|
+
|
|
+
|
|
+static void on_process(void *arg);
|
|
+
|
|
+static const struct pw_stream_events stream_events = {
|
|
+ PW_VERSION_STREAM_EVENTS,
|
|
+ .process = on_process,
|
|
+};
|
|
+
|
|
+
|
|
+static void ausrc_destructor(void *arg)
|
|
+{
|
|
+ struct ausrc_st *st = arg;
|
|
+
|
|
+ st->rh = NULL;
|
|
+ st->errh = NULL;
|
|
+ pw_stream_destroy(st->stream);
|
|
+}
|
|
+
|
|
+
|
|
+int pw_capture_alloc(struct ausrc_st **stp, const struct ausrc *as,
|
|
+ struct ausrc_prm *prm, const char *dev, ausrc_read_h *rh,
|
|
+ ausrc_error_h *errh, void *arg)
|
|
+{
|
|
+ struct ausrc_st *st;
|
|
+ const struct spa_pod *params[1];
|
|
+ uint8_t buffer[1024];
|
|
+ struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer,
|
|
+ sizeof(buffer));
|
|
+ const char name[] = "baresip-capture";
|
|
+ int err = 0;
|
|
+
|
|
+ if (!stp || !as || !prm || !rh)
|
|
+ return EINVAL;
|
|
+
|
|
+ info ("pipewire: opening capture(%u Hz, %d channels,"
|
|
+ "device '%s')\n", prm->srate, prm->ch, dev);
|
|
+
|
|
+ st = mem_zalloc(sizeof(*st), ausrc_destructor);
|
|
+ if (!st)
|
|
+ return ENOMEM;
|
|
+
|
|
+ st->prm.srate = prm->srate;
|
|
+ st->prm.ch = prm->ch;
|
|
+ st->prm.ptime = prm->ptime;
|
|
+ st->prm.fmt = prm->fmt;
|
|
+
|
|
+ st->sampsz = aufmt_sample_size(prm->fmt);
|
|
+ st->samps = 0;
|
|
+
|
|
+ st->rh = rh;
|
|
+ st->errh = errh;
|
|
+ st->arg = arg;
|
|
+
|
|
+ pw_thread_loop_lock (pw_loop_instance());
|
|
+ st->stream = pw_stream_new(pw_core_instance(), name,
|
|
+ pw_properties_new(
|
|
+ PW_KEY_MEDIA_TYPE, "Audio",
|
|
+ PW_KEY_MEDIA_CATEGORY, "Capture",
|
|
+ PW_KEY_MEDIA_ROLE, "Communication",
|
|
+ NULL));
|
|
+ if (!st->stream) {
|
|
+ err = errno;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ pw_stream_add_listener(st->stream, &st->listener, &stream_events, st);
|
|
+ params[0] = spa_format_audio_raw_build(&b, SPA_PARAM_EnumFormat,
|
|
+ &SPA_AUDIO_INFO_RAW_INIT(
|
|
+ .format = aufmt_to_pw_format(prm->fmt),
|
|
+ .channels = prm->ch,
|
|
+ .rate = prm->srate ));
|
|
+ if (!params[0])
|
|
+ goto out;
|
|
+
|
|
+ err = pw_stream_connect(st->stream,
|
|
+ PW_DIRECTION_INPUT,
|
|
+ PW_ID_ANY,
|
|
+ PW_STREAM_FLAG_AUTOCONNECT |
|
|
+ PW_STREAM_FLAG_MAP_BUFFERS |
|
|
+ PW_STREAM_FLAG_RT_PROCESS,
|
|
+ params, 1);
|
|
+
|
|
+ pw_thread_loop_unlock(pw_loop_instance());
|
|
+
|
|
+ info ("pipewire: stream %s started (%m)\n", name, err);
|
|
+
|
|
+ out:
|
|
+ if (err)
|
|
+ mem_deref(st);
|
|
+ else
|
|
+ *stp = st;
|
|
+
|
|
+ return err;
|
|
+}
|
|
+
|
|
+
|
|
+/**
|
|
+ * Pipewire process callback
|
|
+ *
|
|
+ * @param arg Argument (ausrc_st object)
|
|
+ */
|
|
+static void on_process(void *arg)
|
|
+{
|
|
+ struct ausrc_st *st = arg;
|
|
+ struct pw_buffer *b;
|
|
+ struct spa_buffer *buf;
|
|
+ struct auframe af;
|
|
+
|
|
+ void *sampv;
|
|
+ size_t sampc;
|
|
+
|
|
+ b = pw_stream_dequeue_buffer(st->stream);
|
|
+ if (!b)
|
|
+ warning("pipewire: out of buffers (%m)\n", errno);
|
|
+
|
|
+ buf = b->buffer;
|
|
+ sampv = buf->datas[0].data;
|
|
+ if (!sampv)
|
|
+ return;
|
|
+
|
|
+ sampc = buf->datas[0].chunk->size / st->sampsz;
|
|
+
|
|
+ auframe_init(&af, st->prm.fmt, sampv, sampc,
|
|
+ st->prm.srate, st->prm.ch);
|
|
+
|
|
+ af.timestamp = st->samps * AUDIO_TIMEBASE /
|
|
+ (st->prm.srate * st->prm.ch);
|
|
+ st->samps += sampc;
|
|
+ st->rh(&af, st->arg);
|
|
+
|
|
+ pw_stream_queue_buffer(st->stream, b);
|
|
+}
|
|
diff --git a/modules/pipewire/pipewire.c b/modules/pipewire/pipewire.c
|
|
new file mode 100644
|
|
index 000000000..c9e6aaff4
|
|
--- /dev/null
|
|
+++ b/modules/pipewire/pipewire.c
|
|
@@ -0,0 +1,161 @@
|
|
+/**
|
|
+ * @file pipewire.c Pipewire sound driver
|
|
+ *
|
|
+ * Copyright (C) 2023 Commend.com - c.spielberger@commend.com
|
|
+ */
|
|
+
|
|
+#include <string.h>
|
|
+#include <errno.h>
|
|
+#include <re.h>
|
|
+#include <rem.h>
|
|
+#include <baresip.h>
|
|
+#include <spa/param/audio/raw.h>
|
|
+#include <pipewire/pipewire.h>
|
|
+
|
|
+#include "pipewire.h"
|
|
+
|
|
+/**
|
|
+ * @defgroup pipewire pipewire
|
|
+ *
|
|
+ * Audio driver module for Pipewire
|
|
+ *
|
|
+ */
|
|
+
|
|
+enum {
|
|
+ RECONN_DELAY = 1500,
|
|
+};
|
|
+
|
|
+
|
|
+struct pw_stat {
|
|
+ struct pw_thread_loop *loop;
|
|
+ struct pw_context *context;
|
|
+ struct pw_core *core;
|
|
+};
|
|
+
|
|
+
|
|
+static struct pw_stat *d = NULL;
|
|
+
|
|
+static struct auplay *auplay = NULL;
|
|
+static struct ausrc *ausrc = NULL;
|
|
+
|
|
+
|
|
+static void destructor(void *arg)
|
|
+{
|
|
+ struct pw_stat *pw = arg;
|
|
+
|
|
+ if (pw->core)
|
|
+ pw_core_disconnect(pw->core);
|
|
+
|
|
+ if (pw->context)
|
|
+ pw_context_destroy(pw->context);
|
|
+
|
|
+ if (pw->loop) {
|
|
+ pw_thread_loop_stop(pw->loop);
|
|
+ pw_thread_loop_destroy(pw->loop);
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
+static struct pw_stat *pw_stat_alloc(void)
|
|
+{
|
|
+ struct pw_stat *pw;
|
|
+ int err;
|
|
+
|
|
+ pw = mem_zalloc(sizeof(*pw), destructor);
|
|
+
|
|
+ pw->loop = pw_thread_loop_new("baresip pipewire", NULL);
|
|
+ if (!pw->loop)
|
|
+ goto errout;
|
|
+
|
|
+ err = pw_thread_loop_start(pw->loop);
|
|
+ if (err)
|
|
+ goto errout;
|
|
+
|
|
+ pw->context = pw_context_new(pw_thread_loop_get_loop(pw->loop),
|
|
+ NULL /* properties */,
|
|
+ 0 /* user_data size */);
|
|
+ if (!pw->context)
|
|
+ goto errout;
|
|
+
|
|
+ pw->core = pw_context_connect(pw->context,
|
|
+ NULL /* properties */,
|
|
+ 0 /* user_data size */);
|
|
+ if (!pw->core)
|
|
+ goto errout;
|
|
+
|
|
+ info("pipewire: connected to pipewire\n");
|
|
+ return pw;
|
|
+
|
|
+errout:
|
|
+ warning("pipewire: could not connect to pipewire\n");
|
|
+ mem_deref(pw);
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+
|
|
+struct pw_core *pw_core_instance(void)
|
|
+{
|
|
+ if (!d)
|
|
+ return NULL;
|
|
+
|
|
+ return d->core;
|
|
+}
|
|
+
|
|
+
|
|
+struct pw_thread_loop *pw_loop_instance(void)
|
|
+{
|
|
+ if (!d)
|
|
+ return NULL;
|
|
+
|
|
+ return d->loop;
|
|
+}
|
|
+
|
|
+
|
|
+int aufmt_to_pw_format(enum aufmt fmt)
|
|
+{
|
|
+ switch (fmt) {
|
|
+ case AUFMT_S16LE: return SPA_AUDIO_FORMAT_S16_LE;
|
|
+ case AUFMT_FLOAT: return SPA_AUDIO_FORMAT_F32;
|
|
+ default: return 0;
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
+static int module_init(void)
|
|
+{
|
|
+ int err = 0;
|
|
+
|
|
+ pw_init(NULL, NULL);
|
|
+ info("pipewire: headers %s library %s \n",
|
|
+ pw_get_headers_version(), pw_get_library_version());
|
|
+
|
|
+ d = pw_stat_alloc();
|
|
+ if (!d)
|
|
+ return errno;
|
|
+
|
|
+ err = auplay_register(&auplay, baresip_auplayl(),
|
|
+ "pipewire", pw_playback_alloc);
|
|
+ err |= ausrc_register(&ausrc, baresip_ausrcl(),
|
|
+ "pipewire", pw_capture_alloc);
|
|
+
|
|
+ return err;
|
|
+}
|
|
+
|
|
+
|
|
+static int module_close(void)
|
|
+{
|
|
+ auplay = mem_deref(auplay);
|
|
+ ausrc = mem_deref(ausrc);
|
|
+
|
|
+ d = mem_deref(d);
|
|
+ pw_deinit();
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+
|
|
+EXPORT_SYM const struct mod_export DECL_EXPORTS(pipewire) = {
|
|
+ "pipewire",
|
|
+ "audio",
|
|
+ module_init,
|
|
+ module_close,
|
|
+};
|
|
diff --git a/modules/pipewire/pipewire.h b/modules/pipewire/pipewire.h
|
|
new file mode 100644
|
|
index 000000000..0a93aaf52
|
|
--- /dev/null
|
|
+++ b/modules/pipewire/pipewire.h
|
|
@@ -0,0 +1,17 @@
|
|
+/**
|
|
+ * @file pipewire.h Pipewire sound driver - internal API
|
|
+ *
|
|
+ * Copyright (C) 2023 Commend.com - c.spielberger@commend.com
|
|
+ */
|
|
+
|
|
+int aufmt_to_pw_format(enum aufmt fmt);
|
|
+struct pw_core *pw_core_instance(void);
|
|
+struct pw_thread_loop *pw_loop_instance(void);
|
|
+
|
|
+int pw_playback_alloc(struct auplay_st **stp,
|
|
+ const struct auplay *ap,
|
|
+ struct auplay_prm *prm, const char *dev,
|
|
+ auplay_write_h *wh, void *arg);
|
|
+int pw_capture_alloc(struct ausrc_st **stp, const struct ausrc *as,
|
|
+ struct ausrc_prm *prm, const char *dev, ausrc_read_h *rh,
|
|
+ ausrc_error_h *errh, void *arg);
|
|
diff --git a/modules/pipewire/playback.c b/modules/pipewire/playback.c
|
|
new file mode 100644
|
|
index 000000000..94fceb1b0
|
|
--- /dev/null
|
|
+++ b/modules/pipewire/playback.c
|
|
@@ -0,0 +1,163 @@
|
|
+/**
|
|
+ * @file playback.c Pipewire sound driver - playback
|
|
+ *
|
|
+ * Copyright (C) 2023 Commend.com - c.spielberger@commend.com
|
|
+ */
|
|
+
|
|
+#include <string.h>
|
|
+#include <errno.h>
|
|
+#include <re.h>
|
|
+#include <rem.h>
|
|
+#include <baresip.h>
|
|
+#include <spa/param/audio/format-utils.h>
|
|
+#include <pipewire/pipewire.h>
|
|
+
|
|
+#include "pipewire.h"
|
|
+
|
|
+struct auplay_st {
|
|
+ struct pw_stream *stream;
|
|
+
|
|
+ struct auplay_prm prm;
|
|
+ auplay_write_h *wh;
|
|
+ struct spa_hook listener;
|
|
+
|
|
+ size_t sampc;
|
|
+ size_t nbytes;
|
|
+ int32_t stride;
|
|
+
|
|
+ void *arg;
|
|
+};
|
|
+
|
|
+static void on_process(void *arg);
|
|
+
|
|
+static const struct pw_stream_events stream_events = {
|
|
+ PW_VERSION_STREAM_EVENTS,
|
|
+ .process = on_process,
|
|
+};
|
|
+
|
|
+
|
|
+static void auplay_destructor(void *arg)
|
|
+{
|
|
+ struct auplay_st *st = arg;
|
|
+
|
|
+ st->wh = NULL;
|
|
+ pw_stream_destroy(st->stream);
|
|
+}
|
|
+
|
|
+
|
|
+int pw_playback_alloc(struct auplay_st **stp, const struct auplay *ap,
|
|
+ struct auplay_prm *prm, const char *dev, auplay_write_h *wh, void *arg)
|
|
+{
|
|
+ struct auplay_st *st;
|
|
+ const struct spa_pod *params[1];
|
|
+ uint8_t buffer[1024];
|
|
+ struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer,
|
|
+ sizeof(buffer));
|
|
+ const char name[] = "baresip-playback";
|
|
+ size_t sampsz;
|
|
+ int err = 0;
|
|
+
|
|
+ if (!stp || !ap || !prm || !wh)
|
|
+ return EINVAL;
|
|
+
|
|
+ info ("pipewire: opening playback (%u Hz, %d channels, device %s, "
|
|
+ "ptime %u)\n", prm->srate, prm->ch, dev, prm->ptime);
|
|
+
|
|
+ st = mem_zalloc(sizeof(*st), auplay_destructor);
|
|
+ if (!st)
|
|
+ return ENOMEM;
|
|
+
|
|
+ st->prm.srate = prm->srate;
|
|
+ st->prm.ch = prm->ch;
|
|
+ st->prm.ptime = prm->ptime;
|
|
+ st->prm.fmt = prm->fmt;
|
|
+
|
|
+ sampsz = aufmt_sample_size(prm->fmt);
|
|
+ st->sampc = st->prm.ptime * st->prm.ch * st->prm.srate / 1000;
|
|
+ st->nbytes = st->sampc * sampsz;
|
|
+ st->stride = sampsz * prm->ch;
|
|
+
|
|
+ st->wh = wh;
|
|
+ st->arg = arg;
|
|
+
|
|
+ pw_thread_loop_lock (pw_loop_instance());
|
|
+ st->stream = pw_stream_new(pw_core_instance(), name,
|
|
+ pw_properties_new(
|
|
+ PW_KEY_MEDIA_TYPE, "Audio",
|
|
+ PW_KEY_MEDIA_CATEGORY, "Playback",
|
|
+ PW_KEY_MEDIA_ROLE, "Communication",
|
|
+ NULL));
|
|
+ if (!st->stream) {
|
|
+ err = errno;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ pw_stream_add_listener(st->stream, &st->listener, &stream_events, st);
|
|
+ params[0] = spa_format_audio_raw_build(&b, SPA_PARAM_EnumFormat,
|
|
+ &SPA_AUDIO_INFO_RAW_INIT(
|
|
+ .format = aufmt_to_pw_format(prm->fmt),
|
|
+ .channels = prm->ch,
|
|
+ .rate = prm->srate ));
|
|
+ if (!params[0])
|
|
+ goto out;
|
|
+
|
|
+ err = pw_stream_connect(st->stream,
|
|
+ PW_DIRECTION_OUTPUT,
|
|
+ PW_ID_ANY,
|
|
+ PW_STREAM_FLAG_AUTOCONNECT |
|
|
+ PW_STREAM_FLAG_MAP_BUFFERS |
|
|
+ PW_STREAM_FLAG_RT_PROCESS,
|
|
+ params, 1);
|
|
+
|
|
+ pw_thread_loop_unlock(pw_loop_instance());
|
|
+
|
|
+ info ("pipewire: stream %s started (%m)\n", name, err);
|
|
+
|
|
+ out:
|
|
+ if (err)
|
|
+ mem_deref(st);
|
|
+ else
|
|
+ *stp = st;
|
|
+
|
|
+ return err;
|
|
+}
|
|
+
|
|
+
|
|
+/**
|
|
+ * Pipewire process callback
|
|
+ *
|
|
+ * @param arg Argument (auplay_st object)
|
|
+ */
|
|
+static void on_process(void *arg)
|
|
+{
|
|
+ struct auplay_st *st = arg;
|
|
+ struct pw_buffer *b;
|
|
+ struct spa_buffer *buf;
|
|
+ struct auframe af;
|
|
+ void *sampv;
|
|
+
|
|
+ b = pw_stream_dequeue_buffer(st->stream);
|
|
+ if (!b)
|
|
+ warning("pipewire: out of buffers (%m)\n", errno);
|
|
+
|
|
+ buf = b->buffer;
|
|
+ sampv = buf->datas[0].data;
|
|
+ if (!sampv)
|
|
+ return;
|
|
+
|
|
+ if (buf->datas[0].maxsize < st->nbytes) {
|
|
+ warning("pipewire: buffer to small\n");
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ auframe_init(&af, st->prm.fmt, sampv, st->sampc,
|
|
+ st->prm.srate, st->prm.ch);
|
|
+
|
|
+ st->wh(&af, st->arg);
|
|
+
|
|
+ buf->datas[0].chunk->offset = 0;
|
|
+ buf->datas[0].chunk->stride = st->stride;
|
|
+ buf->datas[0].chunk->size = auframe_size(&af);
|
|
+
|
|
+ pw_stream_queue_buffer(st->stream, b);
|
|
+}
|
|
|
|
From 2c17a323ec53a9512ea2374e86b73057cecff9c5 Mon Sep 17 00:00:00 2001
|
|
From: Christian Spielberger <c.spielberger@commend.com>
|
|
Date: Thu, 2 Feb 2023 10:57:15 +0100
|
|
Subject: [PATCH 02/10] cmake: repair FindPIPEWIRE.cmake
|
|
|
|
---
|
|
cmake/FindPIPEWIRE.cmake | 4 ++++
|
|
1 file changed, 4 insertions(+)
|
|
|
|
diff --git a/cmake/FindPIPEWIRE.cmake b/cmake/FindPIPEWIRE.cmake
|
|
index bd9b90181..20fa46a6f 100644
|
|
--- a/cmake/FindPIPEWIRE.cmake
|
|
+++ b/cmake/FindPIPEWIRE.cmake
|
|
@@ -8,3 +8,7 @@ if(NOT WIN32)
|
|
find_package(PkgConfig)
|
|
pkg_search_module(PIPEWIRE libpipewire-0.3)
|
|
endif()
|
|
+
|
|
+include(FindPackageHandleStandardArgs)
|
|
+find_package_handle_standard_args(PIPEWIRE DEFAULT_MSG PIPEWIRE_INCLUDE_DIRS
|
|
+ PIPEWIRE_LIBRARIES)
|
|
|
|
From fc4496f2b527a9216b59a2c2a1d2938b3eedef9f Mon Sep 17 00:00:00 2001
|
|
From: Christian Spielberger <c.spielberger@commend.com>
|
|
Date: Thu, 2 Feb 2023 14:19:41 +0100
|
|
Subject: [PATCH 03/10] pipewire: set node latency and use chunk offset
|
|
|
|
---
|
|
modules/pipewire/capture.c | 16 +++++++++++++---
|
|
1 file changed, 13 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/modules/pipewire/capture.c b/modules/pipewire/capture.c
|
|
index 3e92d131c..697845e7d 100644
|
|
--- a/modules/pipewire/capture.c
|
|
+++ b/modules/pipewire/capture.c
|
|
@@ -58,6 +58,7 @@ int pw_capture_alloc(struct ausrc_st **stp, const struct ausrc *as,
|
|
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer,
|
|
sizeof(buffer));
|
|
const char name[] = "baresip-capture";
|
|
+ char nlat[10];
|
|
int err = 0;
|
|
|
|
if (!stp || !as || !prm || !rh)
|
|
@@ -81,6 +82,7 @@ int pw_capture_alloc(struct ausrc_st **stp, const struct ausrc *as,
|
|
st->rh = rh;
|
|
st->errh = errh;
|
|
st->arg = arg;
|
|
+ re_snprintf(nlat, sizeof(nlat), "%u/1000", prm->ptime);
|
|
|
|
pw_thread_loop_lock (pw_loop_instance());
|
|
st->stream = pw_stream_new(pw_core_instance(), name,
|
|
@@ -88,6 +90,7 @@ int pw_capture_alloc(struct ausrc_st **stp, const struct ausrc *as,
|
|
PW_KEY_MEDIA_TYPE, "Audio",
|
|
PW_KEY_MEDIA_CATEGORY, "Capture",
|
|
PW_KEY_MEDIA_ROLE, "Communication",
|
|
+ PW_KEY_NODE_LATENCY, nlat,
|
|
NULL));
|
|
if (!st->stream) {
|
|
err = errno;
|
|
@@ -135,7 +138,10 @@ static void on_process(void *arg)
|
|
struct ausrc_st *st = arg;
|
|
struct pw_buffer *b;
|
|
struct spa_buffer *buf;
|
|
+ struct spa_data *d;
|
|
struct auframe af;
|
|
+ uint32_t offs;
|
|
+ uint32_t size;
|
|
|
|
void *sampv;
|
|
size_t sampc;
|
|
@@ -145,11 +151,15 @@ static void on_process(void *arg)
|
|
warning("pipewire: out of buffers (%m)\n", errno);
|
|
|
|
buf = b->buffer;
|
|
- sampv = buf->datas[0].data;
|
|
- if (!sampv)
|
|
+ d = &buf->datas[0];
|
|
+
|
|
+ if (!d->data)
|
|
return;
|
|
|
|
- sampc = buf->datas[0].chunk->size / st->sampsz;
|
|
+ offs = SPA_MIN(d->chunk->offset, d->maxsize);
|
|
+ size = SPA_MIN(d->chunk->size, d->maxsize - offs);
|
|
+ sampv = SPA_PTROFF(d->data, offs, void);
|
|
+ sampc = size / st->sampsz;
|
|
|
|
auframe_init(&af, st->prm.fmt, sampv, sampc,
|
|
st->prm.srate, st->prm.ch);
|
|
|
|
From 6dd765174f55bb05ad9e4a339ab8f9b5d9ad4806 Mon Sep 17 00:00:00 2001
|
|
From: Christian Spielberger <c.spielberger@commend.com>
|
|
Date: Thu, 2 Feb 2023 14:20:30 +0100
|
|
Subject: [PATCH 04/10] pipewire: playback cleanup
|
|
|
|
---
|
|
modules/pipewire/playback.c | 15 +++++++++------
|
|
1 file changed, 9 insertions(+), 6 deletions(-)
|
|
|
|
diff --git a/modules/pipewire/playback.c b/modules/pipewire/playback.c
|
|
index 94fceb1b0..012731570 100644
|
|
--- a/modules/pipewire/playback.c
|
|
+++ b/modules/pipewire/playback.c
|
|
@@ -133,6 +133,7 @@ static void on_process(void *arg)
|
|
struct auplay_st *st = arg;
|
|
struct pw_buffer *b;
|
|
struct spa_buffer *buf;
|
|
+ struct spa_data *d;
|
|
struct auframe af;
|
|
void *sampv;
|
|
|
|
@@ -141,11 +142,13 @@ static void on_process(void *arg)
|
|
warning("pipewire: out of buffers (%m)\n", errno);
|
|
|
|
buf = b->buffer;
|
|
- sampv = buf->datas[0].data;
|
|
- if (!sampv)
|
|
+ d = &buf->datas[0];
|
|
+
|
|
+ if (!d->data)
|
|
return;
|
|
|
|
- if (buf->datas[0].maxsize < st->nbytes) {
|
|
+ sampv = d->data;
|
|
+ if (d->maxsize < st->nbytes) {
|
|
warning("pipewire: buffer to small\n");
|
|
return;
|
|
}
|
|
@@ -155,9 +158,9 @@ static void on_process(void *arg)
|
|
|
|
st->wh(&af, st->arg);
|
|
|
|
- buf->datas[0].chunk->offset = 0;
|
|
- buf->datas[0].chunk->stride = st->stride;
|
|
- buf->datas[0].chunk->size = auframe_size(&af);
|
|
+ d->chunk->offset = 0;
|
|
+ d->chunk->stride = st->stride;
|
|
+ d->chunk->size = auframe_size(&af);
|
|
|
|
pw_stream_queue_buffer(st->stream, b);
|
|
}
|
|
|
|
From d08fcfe3cf2eb5cbc2f29958f9d1aff3ce1ecb66 Mon Sep 17 00:00:00 2001
|
|
From: Christian Spielberger <c.spielberger@commend.com>
|
|
Date: Fri, 3 Feb 2023 08:19:30 +0100
|
|
Subject: [PATCH 05/10] pipewire: device selection
|
|
|
|
---
|
|
modules/pipewire/capture.c | 3 +-
|
|
modules/pipewire/pipewire.c | 155 +++++++++++++++++++++++++++++++++---
|
|
modules/pipewire/pipewire.h | 1 +
|
|
modules/pipewire/playback.c | 3 +-
|
|
4 files changed, 151 insertions(+), 11 deletions(-)
|
|
|
|
diff --git a/modules/pipewire/capture.c b/modules/pipewire/capture.c
|
|
index 697845e7d..36f6d5d90 100644
|
|
--- a/modules/pipewire/capture.c
|
|
+++ b/modules/pipewire/capture.c
|
|
@@ -90,6 +90,7 @@ int pw_capture_alloc(struct ausrc_st **stp, const struct ausrc *as,
|
|
PW_KEY_MEDIA_TYPE, "Audio",
|
|
PW_KEY_MEDIA_CATEGORY, "Capture",
|
|
PW_KEY_MEDIA_ROLE, "Communication",
|
|
+ PW_KEY_TARGET_OBJECT, dev,
|
|
PW_KEY_NODE_LATENCY, nlat,
|
|
NULL));
|
|
if (!st->stream) {
|
|
@@ -108,7 +109,7 @@ int pw_capture_alloc(struct ausrc_st **stp, const struct ausrc *as,
|
|
|
|
err = pw_stream_connect(st->stream,
|
|
PW_DIRECTION_INPUT,
|
|
- PW_ID_ANY,
|
|
+ pw_device_id(dev),
|
|
PW_STREAM_FLAG_AUTOCONNECT |
|
|
PW_STREAM_FLAG_MAP_BUFFERS |
|
|
PW_STREAM_FLAG_RT_PROCESS,
|
|
diff --git a/modules/pipewire/pipewire.c b/modules/pipewire/pipewire.c
|
|
index c9e6aaff4..182420f8e 100644
|
|
--- a/modules/pipewire/pipewire.c
|
|
+++ b/modules/pipewire/pipewire.c
|
|
@@ -22,7 +22,16 @@
|
|
*/
|
|
|
|
enum {
|
|
- RECONN_DELAY = 1500,
|
|
+ RECONN_DELAY = 1500,
|
|
+ DEV_HASH_SIZE = 16,
|
|
+};
|
|
+
|
|
+
|
|
+struct pw_dev {
|
|
+ struct le he;
|
|
+
|
|
+ char *node_name;
|
|
+ uint32_t id;
|
|
};
|
|
|
|
|
|
@@ -30,19 +39,27 @@ struct pw_stat {
|
|
struct pw_thread_loop *loop;
|
|
struct pw_context *context;
|
|
struct pw_core *core;
|
|
+ struct pw_registry *registry;
|
|
+ struct spa_hook registry_listener;
|
|
+
|
|
+ struct auplay *auplay;
|
|
+ struct ausrc *ausrc;
|
|
+ struct hash *devices;
|
|
};
|
|
|
|
|
|
static struct pw_stat *d = NULL;
|
|
|
|
-static struct auplay *auplay = NULL;
|
|
-static struct ausrc *ausrc = NULL;
|
|
-
|
|
|
|
static void destructor(void *arg)
|
|
{
|
|
struct pw_stat *pw = arg;
|
|
|
|
+ mem_deref(pw->auplay);
|
|
+ mem_deref(pw->ausrc);
|
|
+ hash_flush(pw->devices);
|
|
+ mem_deref(pw->devices);
|
|
+
|
|
if (pw->core)
|
|
pw_core_disconnect(pw->core);
|
|
|
|
@@ -56,6 +73,105 @@ static void destructor(void *arg)
|
|
}
|
|
|
|
|
|
+static void pw_dev_destructor(void *arg)
|
|
+{
|
|
+ struct pw_dev *pwd = arg;
|
|
+
|
|
+ mem_deref(pwd->node_name);
|
|
+}
|
|
+
|
|
+
|
|
+static int pw_dev_add(uint32_t id, const char *node_name)
|
|
+{
|
|
+ struct pw_dev *pwd;
|
|
+ int err;
|
|
+
|
|
+ pwd = mem_zalloc(sizeof(*pwd), pw_dev_destructor);
|
|
+ if (!pwd)
|
|
+ return ENOMEM;
|
|
+
|
|
+ pwd->id = id;
|
|
+ err = str_dup(&pwd->node_name, node_name);
|
|
+ if (err) {
|
|
+ mem_deref(pwd);
|
|
+ return ENOMEM;
|
|
+ }
|
|
+
|
|
+ hash_append(d->devices, hash_joaat_str(node_name), &pwd->he, pwd);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+
|
|
+static void registry_event_global(void *arg, uint32_t id,
|
|
+ uint32_t permissions, const char *type, uint32_t version,
|
|
+ const struct spa_dict *props)
|
|
+{
|
|
+ struct pw_stat *pw = arg;
|
|
+ const char *media_class;
|
|
+ const char *node_name;
|
|
+ (void)permissions;
|
|
+ (void)version;
|
|
+
|
|
+ if (str_cmp(type, PW_TYPE_INTERFACE_Node))
|
|
+ return;
|
|
+
|
|
+ media_class = spa_dict_lookup(props, PW_KEY_MEDIA_CLASS);
|
|
+ node_name = spa_dict_lookup(props, PW_KEY_NODE_NAME);
|
|
+ if (!str_cmp(media_class, "Audio/Source") && str_isset(node_name)) {
|
|
+ debug("pipewire: adding (%u) %s: \"%s\"\n",
|
|
+ id, media_class, node_name);
|
|
+ mediadev_add(&pw->ausrc->dev_list, node_name);
|
|
+ (void)pw_dev_add(id, node_name);
|
|
+ }
|
|
+
|
|
+ if (!str_cmp(media_class, "Audio/Sink") && str_isset(node_name)) {
|
|
+ debug("pipewire: adding (%u) %s: \"%s\"\n",
|
|
+ id, media_class, node_name);
|
|
+ mediadev_add(&pw->auplay->dev_list, node_name);
|
|
+ (void)pw_dev_add(id, node_name);
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
+static const struct pw_registry_events registry_events = {
|
|
+ PW_VERSION_REGISTRY_EVENTS,
|
|
+ .global = registry_event_global,
|
|
+};
|
|
+
|
|
+
|
|
+struct pwd_cmp {
|
|
+ const char *node_name;
|
|
+};
|
|
+
|
|
+
|
|
+static bool pw_dev_cmp(struct le *le, void *arg)
|
|
+{
|
|
+ const struct pwd_cmp *cmp = arg;
|
|
+ const struct pw_dev *pwd = le->data;
|
|
+
|
|
+ return !str_cmp(pwd->node_name, cmp->node_name);
|
|
+}
|
|
+
|
|
+
|
|
+int pw_device_id(const char *node_name)
|
|
+{
|
|
+ struct le *le;
|
|
+ struct pw_dev *pwd;
|
|
+ struct pwd_cmp cmp;
|
|
+
|
|
+ cmp.node_name = node_name;
|
|
+
|
|
+ le = hash_lookup(d->devices, hash_joaat_str(node_name),
|
|
+ pw_dev_cmp, &cmp);
|
|
+
|
|
+ if (!le || !le->data)
|
|
+ return PW_ID_ANY;
|
|
+
|
|
+ pwd = le->data;
|
|
+ return pwd->id;
|
|
+}
|
|
+
|
|
+
|
|
static struct pw_stat *pw_stat_alloc(void)
|
|
{
|
|
struct pw_stat *pw;
|
|
@@ -93,6 +209,29 @@ static struct pw_stat *pw_stat_alloc(void)
|
|
}
|
|
|
|
|
|
+static int pw_start_registry_scan(struct pw_stat *pw)
|
|
+{
|
|
+ int err;
|
|
+
|
|
+ pw->registry = pw_core_get_registry(pw->core, PW_VERSION_REGISTRY,
|
|
+ 0 /* user_data size */);
|
|
+
|
|
+ if (!pw->registry)
|
|
+ return errno;
|
|
+
|
|
+ err = hash_alloc(&pw->devices, DEV_HASH_SIZE);
|
|
+ if (err)
|
|
+ return err;
|
|
+
|
|
+ pw_thread_loop_lock (pw_loop_instance());
|
|
+ spa_zero(pw->registry_listener);
|
|
+ pw_registry_add_listener(pw->registry, &pw->registry_listener,
|
|
+ ®istry_events, pw);
|
|
+ pw_thread_loop_unlock(pw_loop_instance());
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+
|
|
struct pw_core *pw_core_instance(void)
|
|
{
|
|
if (!d)
|
|
@@ -133,20 +272,18 @@ static int module_init(void)
|
|
if (!d)
|
|
return errno;
|
|
|
|
- err = auplay_register(&auplay, baresip_auplayl(),
|
|
+ err = auplay_register(&d->auplay, baresip_auplayl(),
|
|
"pipewire", pw_playback_alloc);
|
|
- err |= ausrc_register(&ausrc, baresip_ausrcl(),
|
|
+ err |= ausrc_register(&d->ausrc, baresip_ausrcl(),
|
|
"pipewire", pw_capture_alloc);
|
|
|
|
+ err |= pw_start_registry_scan(d);
|
|
return err;
|
|
}
|
|
|
|
|
|
static int module_close(void)
|
|
{
|
|
- auplay = mem_deref(auplay);
|
|
- ausrc = mem_deref(ausrc);
|
|
-
|
|
d = mem_deref(d);
|
|
pw_deinit();
|
|
return 0;
|
|
diff --git a/modules/pipewire/pipewire.h b/modules/pipewire/pipewire.h
|
|
index 0a93aaf52..4d4c9787b 100644
|
|
--- a/modules/pipewire/pipewire.h
|
|
+++ b/modules/pipewire/pipewire.h
|
|
@@ -7,6 +7,7 @@
|
|
int aufmt_to_pw_format(enum aufmt fmt);
|
|
struct pw_core *pw_core_instance(void);
|
|
struct pw_thread_loop *pw_loop_instance(void);
|
|
+int pw_device_id(const char *node_name);
|
|
|
|
int pw_playback_alloc(struct auplay_st **stp,
|
|
const struct auplay *ap,
|
|
diff --git a/modules/pipewire/playback.c b/modules/pipewire/playback.c
|
|
index 012731570..24b4f2c3a 100644
|
|
--- a/modules/pipewire/playback.c
|
|
+++ b/modules/pipewire/playback.c
|
|
@@ -86,6 +86,7 @@ int pw_playback_alloc(struct auplay_st **stp, const struct auplay *ap,
|
|
PW_KEY_MEDIA_TYPE, "Audio",
|
|
PW_KEY_MEDIA_CATEGORY, "Playback",
|
|
PW_KEY_MEDIA_ROLE, "Communication",
|
|
+ PW_KEY_TARGET_OBJECT, dev,
|
|
NULL));
|
|
if (!st->stream) {
|
|
err = errno;
|
|
@@ -103,7 +104,7 @@ int pw_playback_alloc(struct auplay_st **stp, const struct auplay *ap,
|
|
|
|
err = pw_stream_connect(st->stream,
|
|
PW_DIRECTION_OUTPUT,
|
|
- PW_ID_ANY,
|
|
+ pw_device_id(dev),
|
|
PW_STREAM_FLAG_AUTOCONNECT |
|
|
PW_STREAM_FLAG_MAP_BUFFERS |
|
|
PW_STREAM_FLAG_RT_PROCESS,
|
|
|
|
From 86e4a4fd4e0ec7723b7e3129e868f5dd599c5e2f Mon Sep 17 00:00:00 2001
|
|
From: Christian Spielberger <c.spielberger@commend.com>
|
|
Date: Wed, 1 Mar 2023 09:30:21 +0100
|
|
Subject: [PATCH 06/10] pipewire: set _XOPEN_SOURCE=700
|
|
|
|
---
|
|
modules/pipewire/CMakeLists.txt | 1 +
|
|
1 file changed, 1 insertion(+)
|
|
|
|
diff --git a/modules/pipewire/CMakeLists.txt b/modules/pipewire/CMakeLists.txt
|
|
index 8673873af..bb2ad8f2a 100644
|
|
--- a/modules/pipewire/CMakeLists.txt
|
|
+++ b/modules/pipewire/CMakeLists.txt
|
|
@@ -14,4 +14,5 @@ target_link_libraries(${PROJECT_NAME} PRIVATE ${PIPEWIRE_LIBRARIES})
|
|
target_compile_options(${PROJECT_NAME} PRIVATE
|
|
-Wno-pedantic
|
|
-Wno-bad-function-cast
|
|
+ -D_XOPEN_SOURCE=700
|
|
)
|
|
|
|
From 63f9a8a2afad5eff06f6fc55b87276a881f25c08 Mon Sep 17 00:00:00 2001
|
|
From: Christian Spielberger <c.spielberger@commend.com>
|
|
Date: Wed, 1 Mar 2023 09:34:19 +0100
|
|
Subject: [PATCH 07/10] pipewire: replace _XOPEN_SOURCE by _GNU_SOURCE
|
|
|
|
---
|
|
modules/pipewire/CMakeLists.txt | 2 +-
|
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
|
|
diff --git a/modules/pipewire/CMakeLists.txt b/modules/pipewire/CMakeLists.txt
|
|
index bb2ad8f2a..50a4befef 100644
|
|
--- a/modules/pipewire/CMakeLists.txt
|
|
+++ b/modules/pipewire/CMakeLists.txt
|
|
@@ -14,5 +14,5 @@ target_link_libraries(${PROJECT_NAME} PRIVATE ${PIPEWIRE_LIBRARIES})
|
|
target_compile_options(${PROJECT_NAME} PRIVATE
|
|
-Wno-pedantic
|
|
-Wno-bad-function-cast
|
|
- -D_XOPEN_SOURCE=700
|
|
+ -D_GNU_SOURCE
|
|
)
|
|
|
|
From 572d69b24917e66a76015b8605eb58b8e5377969 Mon Sep 17 00:00:00 2001
|
|
From: Christian Spielberger <c.spielberger@commend.com>
|
|
Date: Wed, 1 Mar 2023 10:28:30 +0100
|
|
Subject: [PATCH 08/10] pipewire: thread safe stream termination
|
|
|
|
---
|
|
modules/pipewire/capture.c | 5 ++++-
|
|
modules/pipewire/playback.c | 5 ++++-
|
|
2 files changed, 8 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/modules/pipewire/capture.c b/modules/pipewire/capture.c
|
|
index 36f6d5d90..8d20eec52 100644
|
|
--- a/modules/pipewire/capture.c
|
|
+++ b/modules/pipewire/capture.c
|
|
@@ -42,9 +42,11 @@ static void ausrc_destructor(void *arg)
|
|
{
|
|
struct ausrc_st *st = arg;
|
|
|
|
+ pw_thread_loop_lock (pw_loop_instance());
|
|
st->rh = NULL;
|
|
st->errh = NULL;
|
|
pw_stream_destroy(st->stream);
|
|
+ pw_thread_loop_unlock(pw_loop_instance());
|
|
}
|
|
|
|
|
|
@@ -168,7 +170,8 @@ static void on_process(void *arg)
|
|
af.timestamp = st->samps * AUDIO_TIMEBASE /
|
|
(st->prm.srate * st->prm.ch);
|
|
st->samps += sampc;
|
|
- st->rh(&af, st->arg);
|
|
+ if (st->rh)
|
|
+ st->rh(&af, st->arg);
|
|
|
|
pw_stream_queue_buffer(st->stream, b);
|
|
}
|
|
diff --git a/modules/pipewire/playback.c b/modules/pipewire/playback.c
|
|
index 24b4f2c3a..55aff42c6 100644
|
|
--- a/modules/pipewire/playback.c
|
|
+++ b/modules/pipewire/playback.c
|
|
@@ -40,8 +40,10 @@ static void auplay_destructor(void *arg)
|
|
{
|
|
struct auplay_st *st = arg;
|
|
|
|
+ pw_thread_loop_lock (pw_loop_instance());
|
|
st->wh = NULL;
|
|
pw_stream_destroy(st->stream);
|
|
+ pw_thread_loop_unlock(pw_loop_instance());
|
|
}
|
|
|
|
|
|
@@ -157,7 +159,8 @@ static void on_process(void *arg)
|
|
auframe_init(&af, st->prm.fmt, sampv, st->sampc,
|
|
st->prm.srate, st->prm.ch);
|
|
|
|
- st->wh(&af, st->arg);
|
|
+ if (st->wh)
|
|
+ st->wh(&af, st->arg);
|
|
|
|
d->chunk->offset = 0;
|
|
d->chunk->stride = st->stride;
|
|
|
|
From dd142036ac430c8905ef90b1f73da7fe742b7a41 Mon Sep 17 00:00:00 2001
|
|
From: Christian Spielberger <c.spielberger@commend.com>
|
|
Date: Wed, 1 Mar 2023 10:29:15 +0100
|
|
Subject: [PATCH 09/10] pipewire: remove unused errh
|
|
|
|
---
|
|
modules/pipewire/capture.c | 4 +---
|
|
1 file changed, 1 insertion(+), 3 deletions(-)
|
|
|
|
diff --git a/modules/pipewire/capture.c b/modules/pipewire/capture.c
|
|
index 8d20eec52..00f6f5e99 100644
|
|
--- a/modules/pipewire/capture.c
|
|
+++ b/modules/pipewire/capture.c
|
|
@@ -21,7 +21,6 @@ struct ausrc_st {
|
|
struct ausrc_prm prm;
|
|
ausrc_read_h *rh;
|
|
struct spa_hook listener;
|
|
- ausrc_error_h *errh;
|
|
|
|
size_t sampsz;
|
|
uint64_t samps;
|
|
@@ -44,7 +43,6 @@ static void ausrc_destructor(void *arg)
|
|
|
|
pw_thread_loop_lock (pw_loop_instance());
|
|
st->rh = NULL;
|
|
- st->errh = NULL;
|
|
pw_stream_destroy(st->stream);
|
|
pw_thread_loop_unlock(pw_loop_instance());
|
|
}
|
|
@@ -62,6 +60,7 @@ int pw_capture_alloc(struct ausrc_st **stp, const struct ausrc *as,
|
|
const char name[] = "baresip-capture";
|
|
char nlat[10];
|
|
int err = 0;
|
|
+ (void)errh;
|
|
|
|
if (!stp || !as || !prm || !rh)
|
|
return EINVAL;
|
|
@@ -82,7 +81,6 @@ int pw_capture_alloc(struct ausrc_st **stp, const struct ausrc *as,
|
|
st->samps = 0;
|
|
|
|
st->rh = rh;
|
|
- st->errh = errh;
|
|
st->arg = arg;
|
|
re_snprintf(nlat, sizeof(nlat), "%u/1000", prm->ptime);
|
|
|
|
|
|
From b3a65e2ddb353aeb28f45daad5e7bb575bb17ee0 Mon Sep 17 00:00:00 2001
|
|
From: Christian Spielberger <c.spielberger@commend.com>
|
|
Date: Thu, 2 Mar 2023 07:18:30 +0100
|
|
Subject: [PATCH 10/10] config: add pipewire as option for DEFAULT_AUDIO_DEVICE
|
|
|
|
---
|
|
docs/examples/config | 1 +
|
|
src/config.c | 9 ++++++++-
|
|
2 files changed, 9 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/docs/examples/config b/docs/examples/config
|
|
index 07a8c8920..ff5fbbe33 100644
|
|
--- a/docs/examples/config
|
|
+++ b/docs/examples/config
|
|
@@ -118,6 +118,7 @@ module auresamp.so
|
|
# Audio driver Modules
|
|
module alsa.so
|
|
#module pulse.so
|
|
+#module pipewire.so
|
|
#module jack.so
|
|
#module portaudio.so
|
|
#module aubridge.so
|
|
diff --git a/src/config.c b/src/config.c
|
|
index 7948215b3..37284966d 100644
|
|
--- a/src/config.c
|
|
+++ b/src/config.c
|
|
@@ -975,13 +975,20 @@ int config_write_template(const char *file, const struct config *cfg)
|
|
#elif defined (WIN32)
|
|
(void)re_fprintf(f, "module\t\t\t" "winwave" MOD_EXT "\n");
|
|
#else
|
|
- if (!strncmp(default_audio_device(), "pulse", 5)) {
|
|
+ if (!strncmp(default_audio_device(), "pipewire", 8)) {
|
|
+ (void)re_fprintf(f, "#module\t\t\t" "alsa" MOD_EXT "\n");
|
|
+ (void)re_fprintf(f, "#module\t\t\t" "pulse" MOD_EXT "\n");
|
|
+ (void)re_fprintf(f, "module\t\t\t" "pipewire" MOD_EXT "\n");
|
|
+ }
|
|
+ else if (!strncmp(default_audio_device(), "pulse", 5)) {
|
|
(void)re_fprintf(f, "#module\t\t\t" "alsa" MOD_EXT "\n");
|
|
(void)re_fprintf(f, "module\t\t\t" "pulse" MOD_EXT "\n");
|
|
+ (void)re_fprintf(f, "#module\t\t\t" "pipewire" MOD_EXT "\n");
|
|
}
|
|
else {
|
|
(void)re_fprintf(f, "module\t\t\t" "alsa" MOD_EXT "\n");
|
|
(void)re_fprintf(f, "#module\t\t\t" "pulse" MOD_EXT"\n");
|
|
+ (void)re_fprintf(f, "#module\t\t\t" "pipewire" MOD_EXT "\n");
|
|
}
|
|
#endif
|
|
(void)re_fprintf(f, "#module\t\t\t" "jack" MOD_EXT "\n");
|