release v0.23.13
-----BEGIN PGP SIGNATURE----- iQJBBAABCgArFiEEA5IzWngIOJSkMBxDI26KWMbbRRIFAmRrqn4NHG1heEBibGFy Zy5kZQAKCRAjbopYxttFErXiD/9QIaeO5d+U7BJK1yGkQgu5vHo4Pm34ewP8LTxs K2MYxQQ2jZc7PXqi5Z04wmUw8ymq1BVA2D0ytMdl1Ejcbrste7UrP+1TuD8L9JBj WCE+4otNVYDpx1PB32BN+gxCmJqiFtAQS+eMIz/SXdEXZ9sJvIgYRRkSiSFd0WHM dT3OeeZ0V8cANbXpgI+RLghRGkVdpZJo4uXh3c0OHog1fjEBWPw6+7tH/mkotM0n /hQjI5j14wnzZuIpkDR1kuzvGYmxJKG6LkuUqcm1WexNFbxMqDSbAlXeCmzJn7eK NQvtROOGNjQ84thxRPLlDlYa6vbxoTqdYgZsVHzsQZWejhqw8zsPsF+Ea0A4tkLd UKDQFTphZMVqx74+1u7IjQyW7x+k02iXWLwH2IheEl+BJhvEB7zEflN9TR81jek4 RrGx7jcTArdpt7okAe2ONkHvTYtIpaK5E2voza8K4TGOMzpkVlOkyvJ+rpn8CDRf w0faVvmCQdSrgHKfwUUY8Z47a7d+kkKpFLlvvzNoDV8drQXfgIj5t9HOLATSVVux l2pbgauXFsKyd4IsByXj+m8cBSvmy2C4eLJCsmguiZEvcobdJtzwOr4KuwQDjBsC 8HW0BD0t9S1dSL59vJdMG+CfK/QU5rmAIkxdydD42uo9UmSS78xw1uQgi9oDaPa8 XNCGdQ== =nOGh -----END PGP SIGNATURE----- Merge tag 'v0.23.13' release v0.23.13
This commit is contained in:
commit
9027e5c5bb
5
NEWS
5
NEWS
|
@ -43,11 +43,14 @@ ver 0.24 (not yet released)
|
|||
* remove Boost dependency
|
||||
* require libfmt 7 or later
|
||||
|
||||
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
|
||||
* 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
|
||||
|
|
|
@ -670,6 +670,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
|
||||
|
|
|
@ -111,6 +111,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
|
||||
{
|
||||
|
|
|
@ -257,6 +257,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.
|
||||
*/
|
||||
|
|
|
@ -515,6 +515,7 @@ UpdateWalk::Walk(Directory &root, const char *path, bool discard) noexcept
|
|||
|
||||
{
|
||||
const ScopeDatabaseLock protect;
|
||||
root.ClearInPlaylist();
|
||||
PurgeDanglingFromPlaylists(root);
|
||||
}
|
||||
|
||||
|
|
|
@ -275,10 +275,8 @@ EventLoop::Run() noexcept
|
|||
#endif
|
||||
|
||||
assert(IsInside());
|
||||
assert(!quit);
|
||||
#ifdef HAVE_THREADED_EVENT_LOOP
|
||||
assert(!quit_injected);
|
||||
assert(alive);
|
||||
assert(alive || quit_injected);
|
||||
assert(busy);
|
||||
|
||||
wake_event.Schedule(SocketEvent::READ);
|
||||
|
@ -303,7 +301,7 @@ EventLoop::Run() noexcept
|
|||
|
||||
FlushClockCaches();
|
||||
|
||||
do {
|
||||
while (!quit) {
|
||||
again = false;
|
||||
|
||||
/* invoke timers */
|
||||
|
@ -365,7 +363,7 @@ EventLoop::Run() noexcept
|
|||
|
||||
socket_event.Dispatch();
|
||||
}
|
||||
} while (!quit);
|
||||
}
|
||||
|
||||
#ifdef HAVE_THREADED_EVENT_LOOP
|
||||
#ifndef NDEBUG
|
||||
|
|
|
@ -463,7 +463,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 */
|
||||
|
|
|
@ -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,
|
||||
],
|
||||
)
|
||||
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
// Copyright The Music Player Daemon Project
|
||||
|
||||
#include "LogError.hxx"
|
||||
#include "Domain.hxx"
|
||||
#include "Log.hxx"
|
||||
|
||||
extern "C" {
|
||||
#include <libavutil/error.h>
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
// Copyright The Music Player Daemon Project
|
||||
|
||||
#ifndef MPD_FFMPEG_LOG_ERROR_HXX
|
||||
#define MPD_FFMPEG_LOG_ERROR_HXX
|
||||
|
||||
void
|
||||
LogFfmpegError(int errnum);
|
||||
|
||||
void
|
||||
LogFfmpegError(int errnum, const char *prefix);
|
||||
|
||||
#endif
|
|
@ -13,6 +13,30 @@ 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: [
|
||||
fmt_dep,
|
||||
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()
|
||||
|
@ -30,17 +54,16 @@ ffmpeg = static_library(
|
|||
'ffmpeg',
|
||||
'Init.cxx',
|
||||
'Interleave.cxx',
|
||||
'LogError.cxx',
|
||||
'LogCallback.cxx',
|
||||
'Error.cxx',
|
||||
'Domain.cxx',
|
||||
ffmpeg_sources,
|
||||
include_directories: inc,
|
||||
dependencies: [
|
||||
ffmpeg_util_dep,
|
||||
libavformat_dep,
|
||||
libavcodec_dep,
|
||||
libavfilter_dep,
|
||||
libavutil_dep,
|
||||
log_dep,
|
||||
],
|
||||
)
|
||||
|
@ -48,9 +71,9 @@ ffmpeg = static_library(
|
|||
ffmpeg_dep = declare_dependency(
|
||||
link_with: ffmpeg,
|
||||
dependencies: [
|
||||
ffmpeg_util_dep,
|
||||
libavformat_dep,
|
||||
libavcodec_dep,
|
||||
libavfilter_dep,
|
||||
libavutil_dep,
|
||||
],
|
||||
)
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "storage/StorageInterface.hxx"
|
||||
#include "storage/FileInfo.hxx"
|
||||
#include "storage/MemoryDirectoryReader.hxx"
|
||||
#include "lib/curl/HttpStatusError.hxx"
|
||||
#include "lib/curl/Init.hxx"
|
||||
#include "lib/curl/Global.hxx"
|
||||
#include "lib/curl/Slist.hxx"
|
||||
|
@ -14,7 +15,6 @@
|
|||
#include "lib/curl/Handler.hxx"
|
||||
#include "lib/curl/Escape.hxx"
|
||||
#include "lib/expat/ExpatParser.hxx"
|
||||
#include "lib/fmt/RuntimeError.hxx"
|
||||
#include "lib/fmt/ToBuffer.hxx"
|
||||
#include "fs/Traits.hxx"
|
||||
#include "event/InjectEvent.hxx"
|
||||
|
@ -286,8 +286,9 @@ private:
|
|||
/* virtual methods from CurlResponseHandler */
|
||||
void OnHeaders(unsigned status, Curl::Headers &&headers) final {
|
||||
if (status != 207)
|
||||
throw FmtRuntimeError("Status {} from WebDAV server; expected \"207 Multi-Status\"",
|
||||
status);
|
||||
throw HttpStatusError(status,
|
||||
FmtBuffer<80>("Status {} from WebDAV server; expected \"207 Multi-Status\"",
|
||||
status));
|
||||
|
||||
if (!IsXmlContentType(headers))
|
||||
throw std::runtime_error("Unexpected Content-Type from WebDAV server");
|
||||
|
|
|
@ -14,14 +14,17 @@ class ScopeExitGuard : F {
|
|||
bool enabled = true;
|
||||
|
||||
public:
|
||||
explicit ScopeExitGuard(F &&f):F(std::forward<F>(f)) {}
|
||||
explicit ScopeExitGuard(F &&f) noexcept:F(std::forward<F>(f)) {}
|
||||
|
||||
ScopeExitGuard(ScopeExitGuard &&src)
|
||||
:F(std::move(src)), enabled(src.enabled) {
|
||||
src.enabled = false;
|
||||
}
|
||||
ScopeExitGuard(ScopeExitGuard &&src) noexcept
|
||||
:F(std::move(src)),
|
||||
enabled(std::exchange(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(std::declval<F>()())) {
|
||||
if (enabled)
|
||||
F::operator()();
|
||||
}
|
||||
|
@ -38,7 +41,7 @@ struct ScopeExitTag {
|
|||
parantheses at the end of the expression AtScopeExit()
|
||||
call */
|
||||
template<typename F>
|
||||
ScopeExitGuard<F> operator+(F &&f) {
|
||||
ScopeExitGuard<F> operator+(F &&f) noexcept {
|
||||
return ScopeExitGuard<F>(std::forward<F>(f));
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue