summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Kellermann <max@musicpd.org>2021-07-16 07:50:53 +0200
committerMax Kellermann <max@musicpd.org>2021-07-16 09:04:35 +0200
commit64fa76c56826cdb89a0eb9b24553bdf6293fe434 (patch)
treedc7c5a9c6d6378f41c5df9079a7e85f385d0193a
parent19a44076cfd31c4c6e2c58d0efc86244970fc2e8 (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--NEWS2
-rw-r--r--src/command/FileCommands.cxx48
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