From 1f9387b703c62db8d4e748458a2a9c4064308df4 Mon Sep 17 00:00:00 2001 From: emeric Date: Fri, 12 Jan 2024 23:19:49 +0100 Subject: [PATCH] Search first artist files whose name is artist's mbid then artist's name. fixes #406 --- conf/lms.conf | 1 + src/libs/services/cover/impl/CoverService.cpp | 77 +++++++++++++++---- 2 files changed, 65 insertions(+), 13 deletions(-) diff --git a/conf/lms.conf b/conf/lms.conf index 34583eee..ef239776 100644 --- a/conf/lms.conf +++ b/conf/lms.conf @@ -87,6 +87,7 @@ cover-jpeg-quality = 75; cover-preferred-file-names = ("cover", "front"); # File names for artist images (order is important) +# Files whose name is the artist's MBID, then the artist's name, are searched before the names in this list artist-image-file-names = ("artist"); # Playqueue max entry count diff --git a/src/libs/services/cover/impl/CoverService.cpp b/src/libs/services/cover/impl/CoverService.cpp index 516267ca..1a941a29 100644 --- a/src/libs/services/cover/impl/CoverService.cpp +++ b/src/libs/services/cover/impl/CoverService.cpp @@ -24,6 +24,7 @@ #include "av/IAudioFile.hpp" #include "database/Db.hpp" +#include "database/Artist.hpp" #include "database/Release.hpp" #include "database/Session.hpp" #include "database/Track.hpp" @@ -426,36 +427,86 @@ namespace Cover if (artistImage) return artistImage; - std::set parentPaths; + std::string artistName; + std::string artistMBID; + + std::set releasePaths; + std::set multiArtistReleasePaths; + { Session& session{ _db.getTLSSession() }; + auto transaction{ session.createReadTransaction() }; + + const Artist::pointer artist{ Artist::find(session, artistId) }; + if (!artist) + return artistImage; + + artistName = artist->getName(); + if (auto mbid{ artist->getMBID() }) + artistMBID = mbid->getAsString(); + Track::FindParameters params; params.setArtist(artistId, { TrackArtistLinkType::ReleaseArtist }); - auto transaction{ session.createReadTransaction() }; - Track::find(session, params, [&](const Track::pointer& track) { - parentPaths.insert(track->getPath().parent_path()); + Artist::FindParameters artistFindParams; + artistFindParams.setTrack(track->getId()); + artistFindParams.setLinkType(TrackArtistLinkType::ReleaseArtist); + + const auto releaseArtists{ Artist::findIds(session, artistFindParams) }; + if (releaseArtists.results.size() == 1) + releasePaths.insert(track->getPath().parent_path()); + else + multiArtistReleasePaths.insert(track->getPath().parent_path()); }); } - if (parentPaths.size() == 1) + std::vector artistFileNames; + if (!artistMBID.empty()) + artistFileNames.push_back(artistMBID); + artistFileNames.push_back(artistName); + + std::vector artistFileNamesWithGenericNames{ artistFileNames }; + artistFileNamesWithGenericNames.insert(artistFileNamesWithGenericNames.end(), std::cbegin(_artistFileNames), std::cend(_artistFileNames)); + + // Expect layout like this: + // ReleaseArtist/Release/Tracks' + // /artist-mbid.jpg + // /artist-name.jpg + // /artist.jpg + if (!releasePaths.empty()) { - artistImage = getFromDirectory(parentPaths.begin()->parent_path(), width, _artistFileNames, false); - } - else if (parentPaths.size() > 1) - { - const std::filesystem::path longestCommonPath{ PathUtils::getLongestCommonPath(std::cbegin(parentPaths), std::cend(parentPaths)) }; - artistImage = getFromDirectory(longestCommonPath, width, _artistFileNames, false); + const std::filesystem::path artistPath{ releasePaths.size() == 1 ? releasePaths.begin()->parent_path() : PathUtils::getLongestCommonPath(std::cbegin(releasePaths), std::cend(releasePaths)) }; + artistImage = getFromDirectory(artistPath, width, artistFileNamesWithGenericNames, false); } + // Expect layout like this: + // ReleaseArtist/Release/Tracks' + // /artist-mbid.jpg + // /artist-name.jpg + // /artist.jpg if (!artistImage) { - for (const std::filesystem::path& parentPath : parentPaths) + for (const std::filesystem::path& releasePath : releasePaths) { - artistImage = getFromDirectory(parentPath, width, _artistFileNames, false); + artistImage = getFromDirectory(releasePath, width, artistFileNamesWithGenericNames, false); + if (artistImage) + break; + } + } + + // Expect layout like this: + // Only search for the artist's name in the release path, as we can't map a generic name to several artists + // ReleaseArtist/Release/Tracks' + // /artist-name.jpg + // /artist-mbid.jpg + if (!artistImage) + { + for (const std::filesystem::path& releasePath : multiArtistReleasePaths) + { + artistImage = getFromDirectory(releasePath, width, artistFileNames, false); if (artistImage) break; }