From 6d9b452fde3c5b53994628374cda0e9d52da54f7 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 22 May 2023 13:48:13 +0200 Subject: [PATCH 01/13] lib/ffmpeg/LogError: remove unused library --- src/lib/ffmpeg/LogError.cxx | 42 ------------------------------------- src/lib/ffmpeg/LogError.hxx | 29 ------------------------- src/lib/ffmpeg/meson.build | 1 - 3 files changed, 72 deletions(-) delete mode 100644 src/lib/ffmpeg/LogError.cxx delete mode 100644 src/lib/ffmpeg/LogError.hxx diff --git a/src/lib/ffmpeg/LogError.cxx b/src/lib/ffmpeg/LogError.cxx deleted file mode 100644 index 7cb02278c..000000000 --- a/src/lib/ffmpeg/LogError.cxx +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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. - */ - -#include "LogError.hxx" -#include "Domain.hxx" -#include "Log.hxx" - -extern "C" { -#include -} - -void -LogFfmpegError(int errnum) -{ - char msg[256]; - av_strerror(errnum, msg, sizeof(msg)); - LogError(ffmpeg_domain, msg); -} - -void -LogFfmpegError(int errnum, const char *prefix) -{ - char msg[256]; - av_strerror(errnum, msg, sizeof(msg)); - FmtError(ffmpeg_domain, "{}: {}", prefix, msg); -} diff --git a/src/lib/ffmpeg/LogError.hxx b/src/lib/ffmpeg/LogError.hxx deleted file mode 100644 index 8951caba6..000000000 --- a/src/lib/ffmpeg/LogError.hxx +++ /dev/null @@ -1,29 +0,0 @@ -/* - * 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. - */ - -#ifndef MPD_FFMPEG_LOG_ERROR_HXX -#define MPD_FFMPEG_LOG_ERROR_HXX - -void -LogFfmpegError(int errnum); - -void -LogFfmpegError(int errnum, const char *prefix); - -#endif diff --git a/src/lib/ffmpeg/meson.build b/src/lib/ffmpeg/meson.build index 43ceef505..d570beb42 100644 --- a/src/lib/ffmpeg/meson.build +++ b/src/lib/ffmpeg/meson.build @@ -30,7 +30,6 @@ ffmpeg = static_library( 'ffmpeg', 'Init.cxx', 'Interleave.cxx', - 'LogError.cxx', 'LogCallback.cxx', 'Error.cxx', 'Domain.cxx', From 7c759ba8b0ba6ae7125d1baad1f9b9f096615b61 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 22 May 2023 13:49:38 +0200 Subject: [PATCH 02/13] lib/ffmpeg/meson.build: move libavutil helpers into separate library --- src/lib/ffmpeg/meson.build | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/lib/ffmpeg/meson.build b/src/lib/ffmpeg/meson.build index d570beb42..3e62881c0 100644 --- a/src/lib/ffmpeg/meson.build +++ b/src/lib/ffmpeg/meson.build @@ -13,6 +13,29 @@ else endif conf.set('HAVE_LIBAVFILTER', libavfilter_dep.found()) +if not libavutil_dep.found() + ffmpeg_util_dep = dependency('', required: false) + ffmpeg_dep = dependency('', required: false) + subdir_done() +endif + +ffmpeg_util = static_library( + 'ffmpeg_util', + 'Interleave.cxx', + 'Error.cxx', + include_directories: inc, + dependencies: [ + libavutil_dep, + ], +) + +ffmpeg_util_dep = declare_dependency( + link_with: ffmpeg_util, + dependencies: [ + libavutil_dep, + ], +) + if not enable_ffmpeg ffmpeg_dep = dependency('', required: false) subdir_done() @@ -36,10 +59,10 @@ ffmpeg = static_library( ffmpeg_sources, include_directories: inc, dependencies: [ + ffmpeg_util_dep, libavformat_dep, libavcodec_dep, libavfilter_dep, - libavutil_dep, log_dep, ], ) @@ -47,9 +70,9 @@ ffmpeg = static_library( ffmpeg_dep = declare_dependency( link_with: ffmpeg, dependencies: [ + ffmpeg_util_dep, libavformat_dep, libavcodec_dep, libavfilter_dep, - libavutil_dep, ], ) From 2fa8c7d2db8e2a00d74cce404a22cfd581883ba9 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 22 May 2023 14:04:01 +0200 Subject: [PATCH 03/13] lib/crypto/meson.build: link with `ffmpeg_util_dep` This adds `MakeFfmpegError()` to the executable and fixes a linker failure when `libavutil` is available, but `libavformat` and `libavcodec` are not. Closes https://github.com/MusicPlayerDaemon/MPD/issues/1786 --- src/lib/crypto/meson.build | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/crypto/meson.build b/src/lib/crypto/meson.build index f3a99cb86..a10548ff5 100644 --- a/src/lib/crypto/meson.build +++ b/src/lib/crypto/meson.build @@ -18,13 +18,13 @@ endif conf.set('HAVE_MD5', crypto_md5_dep.found()) -if libavutil_dep.found() +if ffmpeg_util_dep.found() crypto_base64 = static_library( 'crypto_base64', 'Base64.cxx', include_directories: inc, dependencies: [ - libavutil_dep, + ffmpeg_util_dep, ], ) From 2ab03a0914023d2150f38fa11c48ddedd90d0c94 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 22 May 2023 14:42:02 +0200 Subject: [PATCH 04/13] util/ScopeExit: allow the function to throw Fixes crash inside AtScopeExit() in the WASAPI output plugin. Closes https://github.com/MusicPlayerDaemon/MPD/issues/1759 --- src/util/ScopeExit.hxx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/util/ScopeExit.hxx b/src/util/ScopeExit.hxx index b64a35cf0..0fecf6c1e 100644 --- a/src/util/ScopeExit.hxx +++ b/src/util/ScopeExit.hxx @@ -47,7 +47,11 @@ public: src.enabled = false; } - ~ScopeExitGuard() { + /* destructors are "noexcept" by default; this explicit + "noexcept" declaration allows the destructor to throw if + the function can throw; without this, a throwing function + would std::terminate() */ + ~ScopeExitGuard() noexcept(noexcept(F::operator()())) { if (enabled) F::operator()(); } From 70b451db7b457f505f4aa03c08cfd9302931d5f0 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 22 May 2023 14:43:36 +0200 Subject: [PATCH 05/13] util/ScopeExit: add `noexcept` --- src/util/ScopeExit.hxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/util/ScopeExit.hxx b/src/util/ScopeExit.hxx index 0fecf6c1e..8dc0e2c70 100644 --- a/src/util/ScopeExit.hxx +++ b/src/util/ScopeExit.hxx @@ -40,9 +40,9 @@ class ScopeExitGuard : F { bool enabled = true; public: - explicit ScopeExitGuard(F &&f):F(std::forward(f)) {} + explicit ScopeExitGuard(F &&f) noexcept:F(std::forward(f)) {} - ScopeExitGuard(ScopeExitGuard &&src) + ScopeExitGuard(ScopeExitGuard &&src) noexcept :F(std::move(src)), enabled(src.enabled) { src.enabled = false; } @@ -68,7 +68,7 @@ struct ScopeExitTag { parantheses at the end of the expression AtScopeExit() call */ template - ScopeExitGuard operator+(F &&f) { + ScopeExitGuard operator+(F &&f) noexcept { return ScopeExitGuard(std::forward(f)); } }; From 7a99a7008c0807fb6b9dff230d45847a584e6de9 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 22 May 2023 14:44:32 +0200 Subject: [PATCH 06/13] util/ScopeExit: use std::exchange() --- src/util/ScopeExit.hxx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/util/ScopeExit.hxx b/src/util/ScopeExit.hxx index 8dc0e2c70..a53282676 100644 --- a/src/util/ScopeExit.hxx +++ b/src/util/ScopeExit.hxx @@ -43,9 +43,8 @@ public: explicit ScopeExitGuard(F &&f) noexcept:F(std::forward(f)) {} ScopeExitGuard(ScopeExitGuard &&src) noexcept - :F(std::move(src)), enabled(src.enabled) { - src.enabled = false; - } + :F(std::move(src)), + enabled(std::exchange(src.enabled, false)) {} /* destructors are "noexcept" by default; this explicit "noexcept" declaration allows the destructor to throw if From dc127f39a787a2919a5aa90b75b85753ae64c012 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 22 May 2023 15:01:00 +0200 Subject: [PATCH 07/13] util/ScopeExit: use std::declval() Fixes GCC 10 error: error: cannot call member function `Foo` without object --- src/util/ScopeExit.hxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/ScopeExit.hxx b/src/util/ScopeExit.hxx index a53282676..b50468702 100644 --- a/src/util/ScopeExit.hxx +++ b/src/util/ScopeExit.hxx @@ -50,7 +50,7 @@ public: "noexcept" declaration allows the destructor to throw if the function can throw; without this, a throwing function would std::terminate() */ - ~ScopeExitGuard() noexcept(noexcept(F::operator()())) { + ~ScopeExitGuard() noexcept(noexcept(std::declval()())) { if (enabled) F::operator()(); } From 068cd559e11dd5b95229d4e18710dffe27fa9ae9 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 22 May 2023 15:41:20 +0200 Subject: [PATCH 08/13] db/update/Walk: clear `Song::in_playlist` Without clearing all `in_playlist` flags, the songs will never be revealed again if they were hidden once by a CUE sheet, not even after the CUE sheet gets deleted or modified. Closes https://github.com/MusicPlayerDaemon/MPD/issues/1784 --- NEWS | 2 ++ src/db/plugins/simple/Directory.cxx | 12 ++++++++++++ src/db/plugins/simple/Directory.hxx | 8 ++++++++ src/db/update/Walk.cxx | 1 + 4 files changed, 23 insertions(+) diff --git a/NEWS b/NEWS index 69d88b777..cd9636d6f 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,8 @@ ver 0.23.13 (not yet released) - curl: fix busy loop after connection failed * archive - zzip: fix crash bug +* database + - simple: reveal hidden songs after deleting containing CUE * decoder - ffmpeg: reorder to a lower priority than "gme" - gme: require GME 0.6 or later diff --git a/src/db/plugins/simple/Directory.cxx b/src/db/plugins/simple/Directory.cxx index 313709a31..f00215355 100644 --- a/src/db/plugins/simple/Directory.cxx +++ b/src/db/plugins/simple/Directory.cxx @@ -126,6 +126,18 @@ Directory::LookupTargetSong(std::string_view _target) noexcept return lr.directory->FindSong(lr.rest); } +void +Directory::ClearInPlaylist() noexcept +{ + assert(holding_db_lock()); + + for (auto &child : children) + child.ClearInPlaylist(); + + for (auto &song : songs) + song.in_playlist = false; +} + void Directory::PruneEmpty() noexcept { diff --git a/src/db/plugins/simple/Directory.hxx b/src/db/plugins/simple/Directory.hxx index e13b556ff..3b4b280fe 100644 --- a/src/db/plugins/simple/Directory.hxx +++ b/src/db/plugins/simple/Directory.hxx @@ -287,6 +287,14 @@ public: */ SongPtr RemoveSong(Song *song) noexcept; + /** + * Recursively walk through the whole tree and set all + * `Song::in_playlist` fields to `false`. + * + * Caller must lock the #db_mutex. + */ + void ClearInPlaylist() noexcept; + /** * Caller must lock the #db_mutex. */ diff --git a/src/db/update/Walk.cxx b/src/db/update/Walk.cxx index be71e7195..4fdec28d9 100644 --- a/src/db/update/Walk.cxx +++ b/src/db/update/Walk.cxx @@ -531,6 +531,7 @@ UpdateWalk::Walk(Directory &root, const char *path, bool discard) noexcept { const ScopeDatabaseLock protect; + root.ClearInPlaylist(); PurgeDanglingFromPlaylists(root); } From ed890a273a9e579cbd471ef74193ec0ae25cd6fb Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 22 May 2023 16:15:52 +0200 Subject: [PATCH 09/13] doc/user.rst: document the `replaygain_missing_preamp` setting Closes https://github.com/MusicPlayerDaemon/MPD/issues/1785 --- doc/user.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/user.rst b/doc/user.rst index 57918fad3..489df08ad 100644 --- a/doc/user.rst +++ b/doc/user.rst @@ -611,6 +611,11 @@ If ReplayGain is enabled, then the setting ``replaygain_preamp`` is set to a value (in dB) between ``-15`` and ``15``. This is the gain applied to songs with ReplayGain tags. +On songs without ReplayGain tags, the setting +``replaygain_missing_preamp`` is used instead. If this setting is not +configured, then no ReplayGain is applied to such songs, and they will +appear too loud. + ReplayGain is usually implemented with a software volume filter (which prevents `Bit-perfect playback`_). To use a hardware mixer, set ``replay_gain_handler`` to ``mixer`` in the ``audio_output`` section From 740cbe9e028814b09cd720d3fe8a117ae2f233cb Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 22 May 2023 18:12:54 +0200 Subject: [PATCH 10/13] event/Loop: remove failing assert() The `assert(!quit)` can fail if the `EventThread` gets stopped before it enters `EventLoop::Run()`. There is a similar problem with `alive`, which gets reset by `EventThread::Stop()`. If that happens, then `EventLoop::Run()` should return immediately without handling any events. --- src/event/Loop.cxx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/event/Loop.cxx b/src/event/Loop.cxx index be0f1804b..1b99cd91b 100644 --- a/src/event/Loop.cxx +++ b/src/event/Loop.cxx @@ -272,9 +272,8 @@ EventLoop::Run() noexcept #endif assert(IsInside()); - assert(!quit); #ifdef HAVE_THREADED_EVENT_LOOP - assert(alive); + assert(alive || quit); assert(busy); wake_event.Schedule(SocketEvent::READ); @@ -299,7 +298,7 @@ EventLoop::Run() noexcept steady_clock_cache.flush(); - do { + while (!quit) { again = false; /* invoke timers */ @@ -361,7 +360,7 @@ EventLoop::Run() noexcept socket_event.Dispatch(); } - } while (!quit); + } #ifdef HAVE_THREADED_EVENT_LOOP #ifndef NDEBUG From 5cd86e272f28b4a204bdf19d6573e3b7cd68e663 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 22 May 2023 18:47:00 +0200 Subject: [PATCH 11/13] input/curl: disable `CURLOPT_FAILONERROR` Let OnHeaders() check the status. The status checking code was added by commit 4f021cbced19dfc6 in 2011, but in 2008, commit a8e81326d0 enabled `CURLOPT_FAILONERROR`, which means the status checking code never had any effect. This allows `LoadExcludeListOrLog()` to hide boring "404 Not Found" log messages via `IsFileNotFound()`. --- NEWS | 1 + src/input/plugins/CurlInputPlugin.cxx | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS b/NEWS index cd9636d6f..5d57af4a6 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,7 @@ ver 0.23.13 (not yet released) * input - curl: fix busy loop after connection failed + - curl: hide "404" log messages for non-existent ".mpdignore" files * archive - zzip: fix crash bug * database diff --git a/src/input/plugins/CurlInputPlugin.cxx b/src/input/plugins/CurlInputPlugin.cxx index e90ce8daf..e7a766658 100644 --- a/src/input/plugins/CurlInputPlugin.cxx +++ b/src/input/plugins/CurlInputPlugin.cxx @@ -417,7 +417,6 @@ CurlInputStream::InitEasy() request->SetOption(CURLOPT_HTTP200ALIASES, http_200_aliases); request->SetOption(CURLOPT_FOLLOWLOCATION, 1L); request->SetOption(CURLOPT_MAXREDIRS, 5L); - request->SetOption(CURLOPT_FAILONERROR, 1L); /* this option eliminates the probe request when username/password are specified */ From d5bf128ceef6cfdeb029f1ab2ce4a9a73618f5cc Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 22 May 2023 18:56:32 +0200 Subject: [PATCH 12/13] storage/curl: throw HttpStatusError --- src/storage/plugins/CurlStorage.cxx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/storage/plugins/CurlStorage.cxx b/src/storage/plugins/CurlStorage.cxx index 1a6578f68..62107b536 100644 --- a/src/storage/plugins/CurlStorage.cxx +++ b/src/storage/plugins/CurlStorage.cxx @@ -22,6 +22,7 @@ #include "storage/StorageInterface.hxx" #include "storage/FileInfo.hxx" #include "storage/MemoryDirectoryReader.hxx" +#include "lib/curl/Error.hxx" #include "lib/curl/Init.hxx" #include "lib/curl/Global.hxx" #include "lib/curl/Slist.hxx" @@ -300,8 +301,9 @@ private: /* virtual methods from CurlResponseHandler */ void OnHeaders(unsigned status, Curl::Headers &&headers) final { if (status != 207) - throw FormatRuntimeError("Status %d from WebDAV server; expected \"207 Multi-Status\"", - status); + throw HttpStatusError(status, + StringFormat<80>("Status %u from WebDAV server; expected \"207 Multi-Status\"", + status).c_str()); if (!IsXmlContentType(headers)) throw std::runtime_error("Unexpected Content-Type from WebDAV server"); From 8842650c330f0383192c5accdbe895e48f548d16 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 22 May 2023 19:46:38 +0200 Subject: [PATCH 13/13] release v0.23.13 --- NEWS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 5d57af4a6..df45c188a 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,4 @@ -ver 0.23.13 (not yet released) +ver 0.23.13 (2023/05/22) * input - curl: fix busy loop after connection failed - curl: hide "404" log messages for non-existent ".mpdignore" files