diff options
author | Max Kellermann <max@musicpd.org> | 2020-10-28 17:33:10 +0100 |
---|---|---|
committer | Max Kellermann <max@musicpd.org> | 2020-10-28 17:33:10 +0100 |
commit | bb99cf37e3f48c851bea671566cd9923d771396d (patch) | |
tree | beac1e78e7261e54e20eeceeab71a4aaa889ef23 /src/db | |
parent | 7c47fe746cf2eb45863532201339de6f230f4bff (diff) | |
parent | dc432f3ffa9b1c8a60b9224c0ae00a40b8b819d1 (diff) |
Merge tag 'v0.22.2' into master
release v0.22.2
Diffstat (limited to 'src/db')
-rw-r--r-- | src/db/meson.build | 1 | ||||
-rw-r--r-- | src/db/plugins/simple/Directory.hxx | 8 | ||||
-rw-r--r-- | src/db/plugins/simple/Song.cxx | 8 | ||||
-rw-r--r-- | src/db/plugins/simple/Song.hxx | 10 | ||||
-rw-r--r-- | src/db/update/SpecialDirectory.cxx | 74 | ||||
-rw-r--r-- | src/db/update/Walk.cxx | 62 |
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(); |