summaryrefslogtreecommitdiff
path: root/src/db
diff options
context:
space:
mode:
authorMax Kellermann <max@musicpd.org>2020-10-28 17:33:10 +0100
committerMax Kellermann <max@musicpd.org>2020-10-28 17:33:10 +0100
commitbb99cf37e3f48c851bea671566cd9923d771396d (patch)
treebeac1e78e7261e54e20eeceeab71a4aaa889ef23 /src/db
parent7c47fe746cf2eb45863532201339de6f230f4bff (diff)
parentdc432f3ffa9b1c8a60b9224c0ae00a40b8b819d1 (diff)
Merge tag 'v0.22.2' into master
release v0.22.2
Diffstat (limited to 'src/db')
-rw-r--r--src/db/meson.build1
-rw-r--r--src/db/plugins/simple/Directory.hxx8
-rw-r--r--src/db/plugins/simple/Song.cxx8
-rw-r--r--src/db/plugins/simple/Song.hxx10
-rw-r--r--src/db/update/SpecialDirectory.cxx74
-rw-r--r--src/db/update/Walk.cxx62
6 files changed, 138 insertions, 25 deletions
diff --git a/src/db/meson.build b/src/db/meson.build
index 2a0c8a5bd..69bf50cd6 100644
--- a/src/db/meson.build
+++ b/src/db/meson.build
@@ -31,6 +31,7 @@ db_glue_sources = [
'update/Remove.cxx',
'update/ExcludeList.cxx',
'update/VirtualDirectory.cxx',
+ 'update/SpecialDirectory.cxx',
'DatabaseGlue.cxx',
'Configured.cxx',
'DatabaseSong.cxx',
diff --git a/src/db/plugins/simple/Directory.hxx b/src/db/plugins/simple/Directory.hxx
index 7062e609c..1479b578a 100644
--- a/src/db/plugins/simple/Directory.hxx
+++ b/src/db/plugins/simple/Directory.hxx
@@ -133,6 +133,14 @@ public:
}
/**
+ * Checks whether this is a "special" directory
+ * (e.g. #DEVICE_PLAYLIST) and whether the underlying plugin
+ * is available.
+ */
+ gcc_pure
+ bool IsPluginAvailable() const noexcept;
+
+ /**
* Remove this #Directory object from its parent and free it. This
* must not be called with the root Directory.
*
diff --git a/src/db/plugins/simple/Song.cxx b/src/db/plugins/simple/Song.cxx
index 3da13b9ea..eecf00277 100644
--- a/src/db/plugins/simple/Song.cxx
+++ b/src/db/plugins/simple/Song.cxx
@@ -34,6 +34,14 @@ Song::Song(DetachedSong &&other, Directory &_parent) noexcept
{
}
+const char *
+Song::GetFilenameSuffix() const noexcept
+{
+ return target.empty()
+ ? PathTraitsUTF8::GetFilenameSuffix(filename.c_str())
+ : PathTraitsUTF8::GetPathSuffix(target.c_str());
+}
+
std::string
Song::GetURI() const noexcept
{
diff --git a/src/db/plugins/simple/Song.hxx b/src/db/plugins/simple/Song.hxx
index 04be80845..90334b031 100644
--- a/src/db/plugins/simple/Song.hxx
+++ b/src/db/plugins/simple/Song.hxx
@@ -108,6 +108,16 @@ struct Song {
Song(DetachedSong &&other, Directory &_parent) noexcept;
+ gcc_pure
+ const char *GetFilenameSuffix() const noexcept;
+
+ /**
+ * Checks whether the decoder plugin for this song is
+ * available.
+ */
+ gcc_pure
+ bool IsPluginAvailable() const noexcept;
+
/**
* allocate a new song structure with a local file name and attempt to
* load its metadata. If all decoder plugin fail to read its meta
diff --git a/src/db/update/SpecialDirectory.cxx b/src/db/update/SpecialDirectory.cxx
new file mode 100644
index 000000000..49c025d18
--- /dev/null
+++ b/src/db/update/SpecialDirectory.cxx
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2003-2020 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 "db/plugins/simple/Directory.hxx"
+#include "archive/ArchiveList.hxx"
+#include "decoder/DecoderList.hxx"
+#include "playlist/PlaylistRegistry.hxx"
+#include "fs/Traits.hxx"
+
+gcc_pure
+static bool
+HaveArchivePluginForFilename(const char *filename) noexcept
+{
+#ifdef ENABLE_ARCHIVE
+ const char *suffix = PathTraitsUTF8::GetFilenameSuffix(filename);
+ return suffix != nullptr &&
+ archive_plugin_from_suffix(suffix) != nullptr;
+#else
+ (void)filename;
+ return false;
+#endif
+}
+
+gcc_pure
+static bool
+HaveContainerPluginForFilename(const char *filename) noexcept
+{
+ const char *suffix = PathTraitsUTF8::GetFilenameSuffix(filename);
+ return suffix != nullptr &&
+ // TODO: check if this plugin really supports containers
+ decoder_plugins_supports_suffix(suffix);
+}
+
+gcc_pure
+static bool
+HavePlaylistPluginForFilename(const char *filename) noexcept
+{
+ const char *suffix = PathTraitsUTF8::GetFilenameSuffix(filename);
+ return suffix != nullptr && playlist_suffix_supported(suffix);
+}
+
+bool
+Directory::IsPluginAvailable() const noexcept
+{
+ switch (device) {
+ case DEVICE_INARCHIVE:
+ return HaveArchivePluginForFilename(GetName());
+
+ case DEVICE_CONTAINER:
+ return HaveContainerPluginForFilename(GetName());
+
+ case DEVICE_PLAYLIST:
+ return HavePlaylistPluginForFilename(GetName());
+
+ default:
+ return true;
+ }
+}
diff --git a/src/db/update/Walk.cxx b/src/db/update/Walk.cxx
index 7526c6b6f..3e0677e91 100644
--- a/src/db/update/Walk.cxx
+++ b/src/db/update/Walk.cxx
@@ -69,46 +69,58 @@ UpdateWalk::RemoveExcludedFromDirectory(Directory &directory,
const ScopeDatabaseLock protect;
directory.ForEachChildSafe([&](Directory &child){
- const auto name_fs =
- AllocatedPath::FromUTF8(child.GetName());
+ const auto name_fs =
+ AllocatedPath::FromUTF8(child.GetName());
- if (name_fs.IsNull() || exclude_list.Check(name_fs)) {
- editor.DeleteDirectory(&child);
- modified = true;
- }
- });
+ if (name_fs.IsNull() || exclude_list.Check(name_fs)) {
+ editor.DeleteDirectory(&child);
+ modified = true;
+ }
+ });
directory.ForEachSongSafe([&](Song &song){
- assert(&song.parent == &directory);
+ assert(&song.parent == &directory);
- const auto name_fs = AllocatedPath::FromUTF8(song.filename);
- if (name_fs.IsNull() || exclude_list.Check(name_fs)) {
- editor.DeleteSong(directory, &song);
- modified = true;
- }
- });
+ const auto name_fs = AllocatedPath::FromUTF8(song.filename);
+ if (name_fs.IsNull() || exclude_list.Check(name_fs)) {
+ editor.DeleteSong(directory, &song);
+ modified = true;
+ }
+ });
}
inline void
UpdateWalk::PurgeDeletedFromDirectory(Directory &directory) noexcept
{
directory.ForEachChildSafe([&](Directory &child){
- if (child.IsMount() || DirectoryExists(storage, child))
- return;
+ if (child.IsMount())
+ /* mount points are always preserved */
+ return;
- editor.LockDeleteDirectory(&child);
+ if (DirectoryExists(storage, child) &&
+ child.IsPluginAvailable())
+ return;
- modified = true;
- });
+ /* the directory was deleted (or the plugin which
+ handles this "virtual" directory is unavailable) */
+
+ editor.LockDeleteDirectory(&child);
+
+ modified = true;
+ });
directory.ForEachSongSafe([&](Song &song){
- if (!directory_child_is_regular(storage, directory,
- song.filename)) {
- editor.LockDeleteSong(directory, &song);
+ if (!directory_child_is_regular(storage, directory,
+ song.filename) ||
+ !song.IsPluginAvailable()) {
+ /* the song file was deleted (or the decoder
+ plugin is unavailable) */
- modified = true;
- }
- });
+ editor.LockDeleteSong(directory, &song);
+
+ modified = true;
+ }
+ });
for (auto i = directory.playlists.begin(),
end = directory.playlists.end();