From 97e5787ff77dcfd0f6801b03896dc3bfc9231b06 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Fri, 30 Jul 2021 13:43:53 +0200 Subject: [PATCH] output/pipewire: call libpipewire only while holding the lock Closes https://github.com/MusicPlayerDaemon/MPD/issues/1210 --- src/lib/pipewire/ThreadLoop.hxx | 56 +++++++++++++++++++++ src/output/plugins/PipeWireOutputPlugin.cxx | 8 ++- 2 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 src/lib/pipewire/ThreadLoop.hxx diff --git a/src/lib/pipewire/ThreadLoop.hxx b/src/lib/pipewire/ThreadLoop.hxx new file mode 100644 index 000000000..fead26c58 --- /dev/null +++ b/src/lib/pipewire/ThreadLoop.hxx @@ -0,0 +1,56 @@ +/* + * Copyright 2003-2021 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +/* oh no, libspa likes to cast away "const"! */ +#pragma GCC diagnostic ignored "-Wcast-qual" +/* suppress more annoying warnings */ +#pragma GCC diagnostic ignored "-Wmissing-field-initializers" +#endif + +#include + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + +namespace PipeWire { + +class ThreadLoopLock { + struct pw_thread_loop *const loop; + +public: + explicit ThreadLoopLock(struct pw_thread_loop *_loop) noexcept + :loop(_loop) + { + pw_thread_loop_lock(loop); + } + + ~ThreadLoopLock() noexcept { + pw_thread_loop_unlock(loop); + } + + ThreadLoopLock(const ThreadLoopLock &) = delete; + ThreadLoopLock &operator=(const ThreadLoopLock &) = delete; +}; + +} // namespace PipeWire diff --git a/src/output/plugins/PipeWireOutputPlugin.cxx b/src/output/plugins/PipeWireOutputPlugin.cxx index d1ea6ffed..993c14fbe 100644 --- a/src/output/plugins/PipeWireOutputPlugin.cxx +++ b/src/output/plugins/PipeWireOutputPlugin.cxx @@ -18,7 +18,7 @@ */ #include "PipeWireOutputPlugin.hxx" -//#include "lib/pipewire/MainLoop.hxx" +#include "lib/pipewire/ThreadLoop.hxx" #include "../OutputAPI.hxx" #include "../Error.hxx" @@ -212,6 +212,7 @@ PipeWireOutput::Open(AudioFormat &audio_format) params[0] = spa_format_audio_raw_build(&pod_builder, SPA_PARAM_EnumFormat, &raw); + const PipeWire::ThreadLoopLock lock(thread_loop); pw_stream_connect(stream, PW_DIRECTION_OUTPUT, target_id, @@ -224,7 +225,10 @@ PipeWireOutput::Open(AudioFormat &audio_format) void PipeWireOutput::Close() noexcept { - pw_stream_destroy(stream); + { + const PipeWire::ThreadLoopLock lock(thread_loop); + pw_stream_destroy(stream); + } // TODO synchronize with Process()? delete ring_buffer;