From 66bce4a24048a7294e0a20b02d7ff1742d46560a Mon Sep 17 00:00:00 2001 From: Robert Scheck Date: May 31 2023 14:10:27 +0000 Subject: Upgrade to 3.2.0 (#2211408) --- diff --git a/baresip-3.0.0-pipewire.patch b/baresip-3.0.0-pipewire.patch deleted file mode 100644 index faee8b0..0000000 --- a/baresip-3.0.0-pipewire.patch +++ /dev/null @@ -1,1252 +0,0 @@ -From 8f9d27a2c48b8e913669344d2af59947357ba830 Mon Sep 17 00:00:00 2001 -From: Christian Spielberger -Date: Thu, 2 Feb 2023 08:52:54 +0100 -Subject: [PATCH 01/11] 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 -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#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 -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#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 -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#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 a1a3e596da6f4fc0e11a4de77f9bf468a7ccb351 Mon Sep 17 00:00:00 2001 -From: Christian Spielberger -Date: Thu, 2 Feb 2023 10:57:15 +0100 -Subject: [PATCH 02/11] 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 fe94c10108cb2beb9dbf72374ffbf9f7b6651907 Mon Sep 17 00:00:00 2001 -From: Christian Spielberger -Date: Thu, 2 Feb 2023 14:19:41 +0100 -Subject: [PATCH 03/11] 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 c3ae03b803a742d2816ab19825af578d2da7c290 Mon Sep 17 00:00:00 2001 -From: Christian Spielberger -Date: Thu, 2 Feb 2023 14:20:30 +0100 -Subject: [PATCH 04/11] 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 074b37357fbe98314094d2a37f226baa81e7d0b2 Mon Sep 17 00:00:00 2001 -From: Christian Spielberger -Date: Fri, 3 Feb 2023 08:19:30 +0100 -Subject: [PATCH 05/11] 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 018d8113bcc3029a7e0ec71a5c722c6d2e3b3615 Mon Sep 17 00:00:00 2001 -From: Christian Spielberger -Date: Wed, 1 Mar 2023 09:30:21 +0100 -Subject: [PATCH 06/11] 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 978787dee5b3fd8dc50100224ff0ef34a4ef7ce6 Mon Sep 17 00:00:00 2001 -From: Christian Spielberger -Date: Wed, 1 Mar 2023 09:34:19 +0100 -Subject: [PATCH 07/11] 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 87b11d9ba47832865d2fb906f50467d6c7ce75f4 Mon Sep 17 00:00:00 2001 -From: Christian Spielberger -Date: Wed, 1 Mar 2023 10:28:30 +0100 -Subject: [PATCH 08/11] 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 eab7291993107826adb4756b08009e0188a1d89a Mon Sep 17 00:00:00 2001 -From: Christian Spielberger -Date: Wed, 1 Mar 2023 10:29:15 +0100 -Subject: [PATCH 09/11] 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 62f397052a2da2c967cd9100e6df66bb34a68c25 Mon Sep 17 00:00:00 2001 -From: Christian Spielberger -Date: Thu, 2 Mar 2023 07:18:30 +0100 -Subject: [PATCH 10/11] 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 153dc81ec..19ab2174b 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 a9e332b9e..ca66fd880 100644 ---- a/src/config.c -+++ b/src/config.c -@@ -1001,13 +1001,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"); - -From 7a72698b35b97ddd78ed2370920b818fdddd2120 Mon Sep 17 00:00:00 2001 -From: Christian Spielberger -Date: Mon, 17 Apr 2023 16:09:15 +0200 -Subject: [PATCH 11/11] pipewire: disable stderr buffering after pw_init() - ---- - modules/pipewire/pipewire.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/modules/pipewire/pipewire.c b/modules/pipewire/pipewire.c -index 182420f8e..eb80ad16b 100644 ---- a/modules/pipewire/pipewire.c -+++ b/modules/pipewire/pipewire.c -@@ -265,6 +265,7 @@ static int module_init(void) - int err = 0; - - pw_init(NULL, NULL); -+ setvbuf(stderr, NULL, _IONBF, 0); - info("pipewire: headers %s library %s \n", - pw_get_headers_version(), pw_get_library_version()); - diff --git a/baresip.spec b/baresip.spec index 7617468..b249102 100644 --- a/baresip.spec +++ b/baresip.spec @@ -1,6 +1,6 @@ Summary: Modular SIP user-agent with audio and video support Name: baresip -Version: 3.1.0 +Version: 3.2.0 Release: 1%{?dist} License: BSD-3-Clause URL: https://github.com/baresip/baresip @@ -11,14 +11,13 @@ Source11: https://gitlab.gnome.org/GNOME/adwaita-icon-theme/-/raw/1e1d6921 Source12: https://gitlab.gnome.org/GNOME/adwaita-icon-theme/-/raw/master/COPYING#/COPYING.adwaita-icon-theme Source13: https://gitlab.gnome.org/GNOME/adwaita-icon-theme/-/raw/master/COPYING_CCBYSA3#/COPYING_CCBYSA3.adwaita-icon-theme Source14: https://gitlab.gnome.org/GNOME/adwaita-icon-theme/-/raw/master/COPYING_LGPL#/COPYING_LGPL.adwaita-icon-theme -Patch0: https://patch-diff.githubusercontent.com/raw/baresip/baresip/pull/2439.patch#/baresip-3.0.0-pipewire.patch BuildRequires: cmake %if 0%{?rhel} && 0%{?rhel} < 8 BuildRequires: cmake3 %endif BuildRequires: gcc BuildRequires: gcc-c++ -BuildRequires: libre-devel >= 3.1.0 +BuildRequires: libre-devel >= 3.2.0 %if 0%{?fedora} || 0%{?rhel} >= 8 BuildRequires: openssl-devel >= 1.1.0 %else @@ -367,7 +366,6 @@ This module provides the X11 video output driver. %prep %setup -q -%patch0 -p1 -b .pipewire %build %if 0%{?rhel} && 0%{?rhel} < 8 @@ -446,7 +444,7 @@ gtk-update-icon-cache --force %{_datadir}/icons/Adwaita &>/dev/null || : %license LICENSE %doc CHANGELOG.md docs/THANKS docs/examples %{_bindir}/%{name} -%{_libdir}/lib%{name}.so.6* +%{_libdir}/lib%{name}.so.7* %dir %{_libdir}/%{name}/ %dir %{_libdir}/%{name}/modules/ %{_libdir}/%{name}/modules/account.so @@ -586,6 +584,9 @@ gtk-update-icon-cache --force %{_datadir}/icons/Adwaita &>/dev/null || : %{_libdir}/%{name}/modules/x11.so %changelog +* Wed May 31 2023 Robert Scheck 3.2.0-1 +- Upgrade to 3.2.0 (#2211408) + * Thu Apr 27 2023 Robert Scheck 3.1.0-1 - Upgrade to 3.1.0 (#2190310) diff --git a/sources b/sources index 8ab0673..be77a3e 100644 --- a/sources +++ b/sources @@ -1,4 +1,4 @@ -SHA512 (baresip-3.1.0.tar.gz) = 5a56b9cebd66d57ae75c7175402e8516652ac165f97531698240f17b049ccd8b0974f6bdea4a37a18a2d563997abfb3ec03a05c8e45038d48b2edca0f40c6de0 +SHA512 (baresip-3.2.0.tar.gz) = c1c73d18f15b4fd251fea9476ffffe5e06e60e238bc73c19877ee10d8a96251db006b0c270bfbe0ad88c73aed40b7e4064e43c7e71720fa2c107c64428025290 SHA512 (call-incoming-symbolic.svg) = 49b6422efff9986dd4a18b34df4ab185b01b46c44ab5b8c1d45ab1ca25694cb42e73428b0a69e5fe2eb61c4e7a7aba9c0df82b5e0290f45950f3942be63bf987 SHA512 (call-outgoing-symbolic.svg) = 142cf668d977e3a709d3c13e01d86fdd09e501affd1756df3000de84581c55b3b5082758b32a73ae0e47f45233cc7e55609f3e54effbba01666ca97d5a55fdaa SHA512 (COPYING.adwaita-icon-theme) = e8963bab4d94d9fbcfc930b95164afff9502e4e53209104f4836fcd6dab2c2e9f105c9f9a17b43bc9502903c9c7b2e0880dacf2339cbe110a19654f13742e20a