From 64fa76c56826cdb89a0eb9b24553bdf6293fe434 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Fri, 16 Jul 2021 07:50:53 +0200 Subject: [PATCH] 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 --- NEWS | 2 ++ src/command/FileCommands.cxx | 48 ++++++++++++++++++++++++++++++++++-- 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 7a34b69ea..7b0c94c90 100644 --- a/NEWS +++ b/NEWS @@ -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