diff --git a/NEWS b/NEWS index 04e6f1dbc..831a7aad4 100644 --- a/NEWS +++ b/NEWS @@ -16,11 +16,16 @@ ver 0.23 (not yet released) - new tags "ComposerSort", "Ensemble", "Movement", "MovementNumber", and "Location" * new build-time dependency: libfmt -ver 0.22.9 (not yet released) +ver 0.22.9 (2021/06/23) * database - simple: load all .mpdignore files of all parent directories +* tags + - fix "readcomments" and "readpicture" on remote files with ID3 tags * decoder - ffmpeg: support the tags "sort_album", "album-sort", "artist-sort" + - ffmpeg: fix build failure with FFmpeg 3.4 +* Android + - fix auto-start on boot in Android 8 or later * Windows - fix build failure with SQLite diff --git a/README.md b/README.md index ea588710d..1c65bb12d 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ For basic installation instructions - [Manual](http://www.musicpd.org/doc/user/) - [Forum](http://forum.musicpd.org/) -- [IRC](irc://chat.freenode.net/#mpd) +- [IRC](ircs://irc.libera.chat:6697/#mpd) - [Bug tracker](https://github.com/MusicPlayerDaemon/MPD/issues/) # Developers diff --git a/android/src/Main.java b/android/src/Main.java index 2c307811a..15c7ba419 100644 --- a/android/src/Main.java +++ b/android/src/Main.java @@ -414,6 +414,15 @@ public class Main extends Service implements Runnable { * start Main service without any callback */ public static void start(Context context, boolean wakelock) { - context.startService(new Intent(context, Main.class).putExtra("wakelock", wakelock)); + Intent intent = new Intent(context, Main.class) + .putExtra("wakelock", wakelock); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) + /* in Android 8+, we need to use this method + or else we'll get "IllegalStateException: + app is in background" */ + context.startForegroundService(intent); + else + context.startService(intent); } } diff --git a/doc/plugins.rst b/doc/plugins.rst index dc097c25c..7d7213fcc 100644 --- a/doc/plugins.rst +++ b/doc/plugins.rst @@ -760,7 +760,7 @@ A resampler using `libsamplerate `_ a.k.a. Secret * - Name - Description * - **type** - - The interpolator type. See below for a list of known types. + - The interpolator type. Defaults to :samp:`2`. See below for a list of known types. The following converter types are provided by libsamplerate: diff --git a/doc/user.rst b/doc/user.rst index 51d952c20..2acfbc0dc 100644 --- a/doc/user.rst +++ b/doc/user.rst @@ -689,6 +689,8 @@ The State File - Specify the state file location. The parent directory must be writable by the :program:`MPD` user (+wx). * - **state_file_interval SECONDS** - Auto-save the state file this number of seconds after each state change. Defaults to 120 (2 minutes). + * - **restore_paused yes|no** + - If set to :samp:`yes`, then :program:`MPD` is put into pause mode instead of starting playback after startup. Default is :samp:`no`. The Sticker Database ^^^^^^^^^^^^^^^^^^^^ @@ -1121,7 +1123,7 @@ Support Getting Help ^^^^^^^^^^^^ -The :program:`MPD` project runs a `forum `_ and an IRC channel (#mpd on Freenode) for requesting help. Visit the MPD help page for details on how to get help. +The :program:`MPD` project runs a `forum `_ and an IRC channel (#mpd on Libera.Chat) for requesting help. Visit the MPD help page for details on how to get help. Common Problems ^^^^^^^^^^^^^^^ diff --git a/python/build/project.py b/python/build/project.py index a0cfa60ba..374ccdb14 100644 --- a/python/build/project.py +++ b/python/build/project.py @@ -20,7 +20,7 @@ class Project: self.base = base if name is None or version is None: - m = re.match(r'^([-\w]+)-(\d[\d.]*[a-z]?[\d.]*(?:-alpha\d+)?)$', self.base) + m = re.match(r'^([-\w]+)-(\d[\d.]*[a-z]?[\d.]*(?:-alpha\d+)?)(\+.*)?$', self.base) if name is None: name = m.group(1) if version is None: version = m.group(2) diff --git a/src/Main.cxx b/src/Main.cxx index 76ecff3a2..b3dcb4f33 100644 --- a/src/Main.cxx +++ b/src/Main.cxx @@ -489,6 +489,15 @@ MainConfigured(const struct options &options, const ConfigData &raw_config) LogError(std::current_exception(), "Zeroconf initialization failed"); } + + AtScopeExit(&zeroconf, &instance) { + if (zeroconf) { + auto &event_loop = instance.io_thread.GetEventLoop(); + BlockingCall(event_loop, [&](){ + zeroconf.reset(); + }); + } + }; #endif #ifdef ENABLE_DATABASE @@ -550,16 +559,6 @@ MainConfigured(const struct options &options, const ConfigData &raw_config) instance.state_file->Write(); instance.BeginShutdownUpdate(); - -#ifdef HAVE_ZEROCONF - if (zeroconf) { - auto &event_loop = instance.io_thread.GetEventLoop(); - BlockingCall(event_loop, [&](){ - zeroconf.reset(); - }); - } -#endif - instance.BeginShutdownPartitions(); } diff --git a/src/TagAny.cxx b/src/TagAny.cxx index faa237b4c..6f875846e 100644 --- a/src/TagAny.cxx +++ b/src/TagAny.cxx @@ -25,6 +25,7 @@ #include "client/Client.hxx" #include "protocol/Ack.hxx" #include "fs/AllocatedPath.hxx" +#include "input/InputStream.hxx" #include "util/Compiler.h" #include "util/UriExtract.hxx" #include "LocateUri.hxx" @@ -32,8 +33,13 @@ static void TagScanStream(const char *uri, TagHandler &handler) { - if (!tag_stream_scan(uri, handler)) + Mutex mutex; + + auto is = InputStream::OpenReady(uri, mutex); + if (!tag_stream_scan(*is, handler)) throw ProtocolError(ACK_ERROR_NO_EXIST, "Failed to load file"); + + ScanGenericTags(*is, handler); } static void diff --git a/src/db/plugins/ProxyDatabasePlugin.cxx b/src/db/plugins/ProxyDatabasePlugin.cxx index 6f8aaeca2..df886851d 100644 --- a/src/db/plugins/ProxyDatabasePlugin.cxx +++ b/src/db/plugins/ProxyDatabasePlugin.cxx @@ -430,6 +430,7 @@ SendGroup(mpd_connection *connection, TagType group) return mpd_search_add_group_tag(connection, tag); #else (void)connection; + (void)group; throw std::runtime_error("Grouping requires libmpdclient 2.12"); #endif diff --git a/src/decoder/plugins/FfmpegDecoderPlugin.cxx b/src/decoder/plugins/FfmpegDecoderPlugin.cxx index 889062ee6..c817277e1 100644 --- a/src/decoder/plugins/FfmpegDecoderPlugin.cxx +++ b/src/decoder/plugins/FfmpegDecoderPlugin.cxx @@ -470,6 +470,7 @@ IsSeekable(const AVFormatContext &format_context) noexcept #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(58, 6, 100) return (format_context.ctx_flags & AVFMTCTX_UNSEEKABLE) != 0; #else + (void)format_context; return false; #endif } @@ -658,6 +659,8 @@ ffmpeg_scan_stream(InputStream &is, TagHandler &handler) return FfmpegScanStream(*f, handler); } +#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(58, 9, 100) + static void ffmpeg_uri_decode(DecoderClient &client, const char *uri) { @@ -689,6 +692,8 @@ ffmpeg_protocols() noexcept return protocols; } +#endif + /** * A list of extensions found for the formats supported by ffmpeg. * This list is current as of 02-23-09; To find out if there are more @@ -812,6 +817,8 @@ static const char *const ffmpeg_mime_types[] = { constexpr DecoderPlugin ffmpeg_decoder_plugin = DecoderPlugin("ffmpeg", ffmpeg_decode, ffmpeg_scan_stream) .WithInit(ffmpeg_init, ffmpeg_finish) +#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(58, 9, 100) .WithProtocols(ffmpeg_protocols, ffmpeg_uri_decode) +#endif .WithSuffixes(ffmpeg_suffixes) .WithMimeTypes(ffmpeg_mime_types); diff --git a/src/input/LastInputStream.cxx b/src/input/LastInputStream.cxx index 40bd5ccc2..e0829c122 100644 --- a/src/input/LastInputStream.cxx +++ b/src/input/LastInputStream.cxx @@ -32,6 +32,7 @@ LastInputStream::~LastInputStream() noexcept = default; void LastInputStream::Close() noexcept { + uri.clear(); is.reset(); close_timer.Cancel(); } diff --git a/src/input/LastInputStream.hxx b/src/input/LastInputStream.hxx index 635e87741..559d45c16 100644 --- a/src/input/LastInputStream.hxx +++ b/src/input/LastInputStream.hxx @@ -64,8 +64,7 @@ public: return is.get(); } - is.reset(); - close_timer.Cancel(); + Close(); is = open(new_uri, mutex); uri = std::forward(new_uri);