TagAny: support CUE tracks

Closes https://github.com/MusicPlayerDaemon/MPD/issues/1482
This commit is contained in:
Max Kellermann 2022-03-14 17:44:39 +01:00
parent 71cd6e6248
commit 2aed7378cc
2 changed files with 62 additions and 0 deletions

1
NEWS
View File

@ -1,6 +1,7 @@
ver 0.23.6 (not yet released) ver 0.23.6 (not yet released)
* protocol * protocol
- support filename "cover.webp" for "albumart" command - support filename "cover.webp" for "albumart" command
- support "readcomments" and "readpicture" on CUE tracks
* decoder * decoder
- ffmpeg: fix end-of-file check (update stuck at empty files) - ffmpeg: fix end-of-file check (update stuck at empty files)
- opus: fix "readpicture" on Opus files - opus: fix "readpicture" on Opus files

View File

@ -21,12 +21,16 @@
#include "TagStream.hxx" #include "TagStream.hxx"
#include "TagFile.hxx" #include "TagFile.hxx"
#include "tag/Generic.hxx" #include "tag/Generic.hxx"
#include "song/LightSong.hxx"
#include "db/Interface.hxx"
#include "storage/StorageInterface.hxx" #include "storage/StorageInterface.hxx"
#include "client/Client.hxx" #include "client/Client.hxx"
#include "protocol/Ack.hxx" #include "protocol/Ack.hxx"
#include "fs/AllocatedPath.hxx" #include "fs/AllocatedPath.hxx"
#include "input/InputStream.hxx" #include "input/InputStream.hxx"
#include "util/Compiler.h" #include "util/Compiler.h"
#include "util/ScopeExit.hxx"
#include "util/StringCompare.hxx"
#include "util/UriExtract.hxx" #include "util/UriExtract.hxx"
#include "LocateUri.hxx" #include "LocateUri.hxx"
@ -51,10 +55,67 @@ TagScanFile(const Path path_fs, TagHandler &handler)
ScanGenericTags(path_fs, handler); ScanGenericTags(path_fs, handler);
} }
#ifdef ENABLE_DATABASE
/**
* Collapse "../" prefixes in a URI relative to the specified base
* URI.
*/
static std::string
ResolveUri(std::string_view base, const char *relative)
{
while (true) {
const char *rest = StringAfterPrefix(relative, "../");
if (rest == nullptr)
break;
if (base == ".")
throw ProtocolError(ACK_ERROR_NO_EXIST, "Bad real URI");
base = PathTraitsUTF8::GetParent(base);
relative = rest;
}
return PathTraitsUTF8::Build(base, relative);
}
/**
* Look up the specified song in the database and return its
* (resolved) "real" URI.
*/
static std::string
GetRealSongUri(Client &client, std::string_view uri)
{
const auto &db = client.GetDatabaseOrThrow();
const auto *song = db.GetSong(uri);
if (song == nullptr)
throw ProtocolError(ACK_ERROR_NO_EXIST, "No such song");
AtScopeExit(&db, song) { db.ReturnSong(song); };
if (song->real_uri == nullptr)
return {};
return ResolveUri(PathTraitsUTF8::GetParent(uri), song->real_uri);
}
#endif
static void static void
TagScanDatabase(Client &client, const char *uri, TagHandler &handler) TagScanDatabase(Client &client, const char *uri, TagHandler &handler)
{ {
#ifdef ENABLE_DATABASE #ifdef ENABLE_DATABASE
const auto real_uri = GetRealSongUri(client, uri);
if (!real_uri.empty()) {
uri = real_uri.c_str();
// TODO: support absolute paths?
if (uri_has_scheme(uri))
return TagScanStream(uri, handler);
}
const Storage *storage = client.GetStorage(); const Storage *storage = client.GetStorage();
if (storage == nullptr) { if (storage == nullptr) {
#else #else