diff options
author | Max Kellermann <max@musicpd.org> | 2021-07-16 07:50:53 +0200 |
---|---|---|
committer | Max Kellermann <max@musicpd.org> | 2021-07-16 09:04:35 +0200 |
commit | 64fa76c56826cdb89a0eb9b24553bdf6293fe434 (patch) | |
tree | dc7c5a9c6d6378f41c5df9079a7e85f385d0193a | |
parent | 19a44076cfd31c4c6e2c58d0efc86244970fc2e8 (diff) |
command/file: support "albumart" for virtual tracks in CUE sheets
Instead of checking for "cover.jpg" in the virtual directory
representing the CUE sheet, check its enclosing directory.
Closes https://github.com/MusicPlayerDaemon/MPD/issues/1206
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | src/command/FileCommands.cxx | 48 |
2 files changed, 48 insertions, 2 deletions
@@ -1,4 +1,6 @@ ver 0.22.10 (not yet released) +* protocol + - support "albumart" for virtual tracks in CUE sheets ver 0.22.9 (2021/06/23) * database diff --git a/src/command/FileCommands.cxx b/src/command/FileCommands.cxx index 52d8abae2..1a2b3b8c4 100644 --- a/src/command/FileCommands.cxx +++ b/src/command/FileCommands.cxx @@ -27,11 +27,15 @@ #include "client/Response.hxx" #include "util/CharUtil.hxx" #include "util/OffsetPointer.hxx" +#include "util/ScopeExit.hxx" +#include "util/StringCompare.hxx" #include "util/StringView.hxx" #include "util/UriExtract.hxx" #include "tag/Handler.hxx" #include "tag/Generic.hxx" #include "TagAny.hxx" +#include "db/Interface.hxx" +#include "song/LightSong.hxx" #include "storage/StorageInterface.hxx" #include "fs/AllocatedPath.hxx" #include "fs/FileInfo.hxx" @@ -242,6 +246,41 @@ read_stream_art(Response &r, const std::string_view art_directory, } #ifdef ENABLE_DATABASE + +/** + * Attempt to locate the "real" directory where the given song is + * stored. This attempts to resolve "virtual" directories/songs, + * e.g. expanded CUE sheet contents. + */ +[[gnu::pure]] +static std::string_view +RealDirectoryOfSong(Client &client, const char *song_uri, + std::string_view directory_uri) noexcept +try { + const auto *db = client.GetDatabase(); + if (db == nullptr) + return directory_uri; + + const auto *song = db->GetSong(song_uri); + if (song == nullptr) + return directory_uri; + + AtScopeExit(db, song) { db->ReturnSong(song); }; + + const char *real_uri = song->real_uri; + + /* this is a simplification which is just enough for CUE + sheets (but may be incomplete): for each "../", go one + level up */ + while ((real_uri = StringAfterPrefix(real_uri, "../")) != nullptr) + directory_uri = PathTraitsUTF8::GetParent(directory_uri); + + return directory_uri; +} catch (...) { + /* ignore all exceptions from Database::GetSong() */ + return directory_uri; +} + static CommandResult read_db_art(Client &client, Response &r, const char *uri, const uint64_t offset) { @@ -251,8 +290,13 @@ read_db_art(Client &client, Response &r, const char *uri, const uint64_t offset) return CommandResult::ERROR; } std::string uri2 = storage->MapUTF8(uri); - return read_stream_art(r, PathTraitsUTF8::GetParent(uri2.c_str()), - offset); + + std::string_view directory_uri = + RealDirectoryOfSong(client, + uri, + PathTraitsUTF8::GetParent(uri2.c_str())); + + return read_stream_art(r, directory_uri, offset); } #endif |