Now using new artwork table everywhere in app and subsonic API to refer to artworks
This commit is contained in:
@@ -26,12 +26,13 @@
|
||||
#include "database/Artwork.hpp"
|
||||
#include "database/Db.hpp"
|
||||
#include "database/Image.hpp"
|
||||
#include "database/ImageId.hpp"
|
||||
#include "database/Release.hpp"
|
||||
#include "database/Session.hpp"
|
||||
#include "database/Track.hpp"
|
||||
#include "database/TrackEmbeddedImage.hpp"
|
||||
#include "database/TrackEmbeddedImageLink.hpp"
|
||||
#include "database/Types.hpp"
|
||||
#include "database/TrackList.hpp"
|
||||
#include "image/Exception.hpp"
|
||||
#include "image/IEncodedImage.hpp"
|
||||
#include "image/Image.hpp"
|
||||
@@ -87,12 +88,12 @@ namespace lms::artwork
|
||||
return image;
|
||||
}
|
||||
|
||||
std::shared_ptr<image::IEncodedImage> ArtworkService::getDefaultReleaseCover()
|
||||
std::shared_ptr<image::IEncodedImage> ArtworkService::getDefaultReleaseArtwork()
|
||||
{
|
||||
return _defaultReleaseCover;
|
||||
}
|
||||
|
||||
std::shared_ptr<image::IEncodedImage> ArtworkService::getDefaultArtistImage()
|
||||
std::shared_ptr<image::IEncodedImage> ArtworkService::getDefaultArtistArtwork()
|
||||
{
|
||||
return _defaultArtistImage;
|
||||
}
|
||||
@@ -136,150 +137,104 @@ namespace lms::artwork
|
||||
return image;
|
||||
}
|
||||
|
||||
ArtworkService::ImageFindResult ArtworkService::findArtistImage(db::ArtistId artistId)
|
||||
db::ArtworkId ArtworkService::findTrackListImage(db::TrackListId trackListId)
|
||||
{
|
||||
db::ArtworkId artworkId;
|
||||
|
||||
// Iterate over all tracks and stop when we find an artwork
|
||||
db::Session& session{ _db.getTLSSession() };
|
||||
auto transaction{ session.createReadTransaction() };
|
||||
|
||||
ImageFindResult res;
|
||||
db::TrackList::pointer trackList{ db::TrackList::find(session, trackListId) };
|
||||
if (!trackList)
|
||||
return artworkId;
|
||||
|
||||
const db::Artist::pointer artist{ db::Artist::find(session, artistId) };
|
||||
if (!artist)
|
||||
return res;
|
||||
const auto entries{ trackList->getEntries(db::Range{ 0, 10 }) };
|
||||
for (const auto& entry : entries.results)
|
||||
{
|
||||
const auto track{ entry->getTrack() };
|
||||
if (track->getPreferredMediaArtworkId().isValid())
|
||||
{
|
||||
artworkId = track->getPreferredMediaArtworkId();
|
||||
break; // stop iteration
|
||||
}
|
||||
|
||||
const db::Artwork::pointer artwork{ artist->getPreferredArtwork() };
|
||||
if (artwork && artwork->getImageId().isValid())
|
||||
res = artwork->getImageId();
|
||||
else if (artwork && artwork->getTrackEmbeddedImageId().isValid())
|
||||
res = artwork->getTrackEmbeddedImageId();
|
||||
if (track->getPreferredArtworkId().isValid())
|
||||
{
|
||||
artworkId = track->getPreferredArtworkId();
|
||||
break; // stop iteration
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
return artworkId;
|
||||
}
|
||||
|
||||
ArtworkService::ImageFindResult ArtworkService::findTrackImage(db::TrackId trackId)
|
||||
std::shared_ptr<image::IEncodedImage> ArtworkService::getImage(db::ArtworkId artworkId, std::optional<image::ImageSize> width)
|
||||
{
|
||||
ImageFindResult res;
|
||||
const ImageCache::EntryDesc cacheEntryDesc{ artworkId, width };
|
||||
|
||||
db::Session& session{ _db.getTLSSession() };
|
||||
auto transaction{ session.createReadTransaction() };
|
||||
std::shared_ptr<image::IEncodedImage> image{ _cache.getImage(cacheEntryDesc) };
|
||||
if (image)
|
||||
return image;
|
||||
|
||||
const db::Track::pointer track{ db::Track::find(session, trackId) };
|
||||
if (!track)
|
||||
return res;
|
||||
db::TrackEmbeddedImageId trackEmbeddedImageId;
|
||||
db::ImageId imageId;
|
||||
|
||||
const db::Artwork::pointer artwork{ track->getPreferredArtwork() };
|
||||
if (artwork && artwork->getImageId().isValid())
|
||||
res = artwork->getImageId();
|
||||
else if (artwork && artwork->getTrackEmbeddedImageId().isValid())
|
||||
res = artwork->getTrackEmbeddedImageId();
|
||||
{
|
||||
db::Session& session{ _db.getTLSSession() };
|
||||
auto transaction{ session.createReadTransaction() };
|
||||
|
||||
return res;
|
||||
}
|
||||
db::Artwork::pointer artwork{ db::Artwork::find(session, artworkId) };
|
||||
if (artwork)
|
||||
{
|
||||
trackEmbeddedImageId = artwork->getTrackEmbeddedImageId();
|
||||
imageId = artwork->getImageId();
|
||||
}
|
||||
}
|
||||
|
||||
ArtworkService::ImageFindResult ArtworkService::findTrackMediaImage(db::TrackId trackId)
|
||||
{
|
||||
db::Session& session{ _db.getTLSSession() };
|
||||
auto transaction{ session.createReadTransaction() };
|
||||
ImageFindResult res;
|
||||
if (trackEmbeddedImageId.isValid())
|
||||
image = getTrackEmbeddedImage(trackEmbeddedImageId, width);
|
||||
else if (imageId.isValid())
|
||||
image = getImage(imageId, width);
|
||||
|
||||
const db::Track::pointer track{ db::Track::find(session, trackId) };
|
||||
if (!track)
|
||||
return res;
|
||||
if (image)
|
||||
_cache.addImage(cacheEntryDesc, image);
|
||||
|
||||
const db::Artwork::pointer artwork{ track->getPreferredMediaArtwork() };
|
||||
if (artwork && artwork->getImageId().isValid())
|
||||
res = artwork->getImageId();
|
||||
else if (artwork && artwork->getTrackEmbeddedImageId().isValid())
|
||||
res = artwork->getTrackEmbeddedImageId();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
ArtworkService::ImageFindResult ArtworkService::findReleaseImage(db::ReleaseId releaseId)
|
||||
{
|
||||
db::Session& session{ _db.getTLSSession() };
|
||||
auto transaction{ session.createReadTransaction() };
|
||||
|
||||
ImageFindResult res;
|
||||
const db::Release::pointer release{ db::Release::find(session, releaseId) };
|
||||
if (!release)
|
||||
return res;
|
||||
|
||||
const db::Artwork::pointer artwork{ release->getPreferredArtwork() };
|
||||
if (artwork && artwork->getImageId().isValid())
|
||||
res = artwork->getImageId();
|
||||
else if (artwork && artwork->getTrackEmbeddedImageId().isValid())
|
||||
res = artwork->getTrackEmbeddedImageId();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
ArtworkService::ImageFindResult ArtworkService::findTrackListImage(db::TrackListId trackListId)
|
||||
{
|
||||
db::Session& session{ _db.getTLSSession() };
|
||||
auto transaction{ session.createReadTransaction() };
|
||||
|
||||
ImageFindResult res;
|
||||
|
||||
db::TrackEmbeddedImage::FindParameters params;
|
||||
params.setTrackList(trackListId);
|
||||
params.setSortMethod(db::TrackEmbeddedImageSortMethod::TrackListIndexAscThenSizeDesc);
|
||||
params.setRange(db::Range{ .offset = 0, .size = 1 });
|
||||
|
||||
db::TrackEmbeddedImage::find(session, params, [&](const db::TrackEmbeddedImage::pointer& image) {
|
||||
res = image->getId();
|
||||
});
|
||||
|
||||
// TODO fallback on release image if not found
|
||||
return res;
|
||||
return image;
|
||||
}
|
||||
|
||||
std::shared_ptr<image::IEncodedImage> ArtworkService::getImage(db::ImageId imageId, std::optional<image::ImageSize> width)
|
||||
{
|
||||
const ImageCache::EntryDesc cacheEntryDesc{ imageId, width };
|
||||
|
||||
std::shared_ptr<image::IEncodedImage> cover{ _cache.getImage(cacheEntryDesc) };
|
||||
if (cover)
|
||||
return cover;
|
||||
|
||||
std::filesystem::path imageFile;
|
||||
{
|
||||
db::Session& session{ _db.getTLSSession() };
|
||||
auto transaction{ session.createReadTransaction() };
|
||||
|
||||
const db::Image::pointer image{ db::Image::find(session, imageId) };
|
||||
if (image)
|
||||
imageFile = image->getAbsoluteFilePath();
|
||||
if (!image)
|
||||
return nullptr;
|
||||
|
||||
imageFile = image->getAbsoluteFilePath();
|
||||
}
|
||||
|
||||
cover = getFromImageFile(imageFile, width);
|
||||
if (cover)
|
||||
_cache.addImage(cacheEntryDesc, cover);
|
||||
|
||||
return cover;
|
||||
return getFromImageFile(imageFile, width);
|
||||
}
|
||||
|
||||
std::shared_ptr<image::IEncodedImage> ArtworkService::getTrackEmbeddedImage(db::TrackEmbeddedImageId trackEmbeddedImageId, std::optional<image::ImageSize> width)
|
||||
{
|
||||
const ImageCache::EntryDesc cacheEntryDesc{ trackEmbeddedImageId, width };
|
||||
|
||||
std::shared_ptr<image::IEncodedImage> image{ _cache.getImage(cacheEntryDesc) };
|
||||
if (image)
|
||||
return image;
|
||||
std::shared_ptr<image::IEncodedImage> image;
|
||||
|
||||
{
|
||||
db::Session& session{ _db.getTLSSession() };
|
||||
auto transaction{ session.createReadTransaction() };
|
||||
|
||||
// TODO: could be put outside transaction
|
||||
db::TrackEmbeddedImageLink::find(session, trackEmbeddedImageId, [&](const db::TrackEmbeddedImageLink::pointer& link) {
|
||||
if (!image)
|
||||
image = getTrackImage(link->getTrack()->getAbsoluteFilePath(), link->getIndex(), width);
|
||||
});
|
||||
}
|
||||
|
||||
if (image)
|
||||
_cache.addImage(cacheEntryDesc, image);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
#include <filesystem>
|
||||
#include <vector>
|
||||
|
||||
#include "database/ImageId.hpp"
|
||||
#include "database/TrackEmbeddedImageId.hpp"
|
||||
#include "services/artwork/IArtworkService.hpp"
|
||||
|
||||
#include "ImageCache.hpp"
|
||||
@@ -47,21 +49,19 @@ namespace lms::artwork
|
||||
ArtworkService& operator=(const ArtworkService&) = delete;
|
||||
|
||||
private:
|
||||
ImageFindResult findArtistImage(db::ArtistId artistId) override;
|
||||
ImageFindResult findTrackImage(db::TrackId trackId) override;
|
||||
ImageFindResult findTrackMediaImage(db::TrackId trackId) override;
|
||||
ImageFindResult findReleaseImage(db::ReleaseId releaseId) override;
|
||||
ImageFindResult findTrackListImage(db::TrackListId trackListId) override;
|
||||
db::ArtworkId findTrackListImage(db::TrackListId trackListId) override;
|
||||
|
||||
std::shared_ptr<image::IEncodedImage> getImage(db::ImageId imageId, std::optional<image::ImageSize> width) override;
|
||||
std::shared_ptr<image::IEncodedImage> getTrackEmbeddedImage(db::TrackEmbeddedImageId trackEmbeddedImageId, std::optional<image::ImageSize> width) override;
|
||||
std::shared_ptr<image::IEncodedImage> getImage(db::ArtworkId artworkId, std::optional<image::ImageSize> width) override;
|
||||
|
||||
std::shared_ptr<image::IEncodedImage> getDefaultReleaseCover() override;
|
||||
std::shared_ptr<image::IEncodedImage> getDefaultArtistImage() override;
|
||||
std::shared_ptr<image::IEncodedImage> getDefaultReleaseArtwork() override;
|
||||
std::shared_ptr<image::IEncodedImage> getDefaultArtistArtwork() override;
|
||||
|
||||
void flushCache() override;
|
||||
void setJpegQuality(unsigned quality) override;
|
||||
|
||||
std::shared_ptr<image::IEncodedImage> getImage(db::ImageId imageId, std::optional<image::ImageSize> width);
|
||||
std::shared_ptr<image::IEncodedImage> getTrackEmbeddedImage(db::TrackEmbeddedImageId trackEmbeddedImageId, std::optional<image::ImageSize> width);
|
||||
|
||||
std::unique_ptr<image::IEncodedImage> getFromImageFile(const std::filesystem::path& p, std::optional<image::ImageSize> width) const;
|
||||
std::unique_ptr<image::IEncodedImage> getTrackImage(const std::filesystem::path& path, std::size_t index, std::optional<image::ImageSize> width) const;
|
||||
|
||||
|
||||
@@ -25,10 +25,8 @@
|
||||
#include <optional>
|
||||
#include <shared_mutex>
|
||||
#include <unordered_map>
|
||||
#include <variant>
|
||||
|
||||
#include "database/ImageId.hpp"
|
||||
#include "database/TrackEmbeddedImageId.hpp"
|
||||
#include "database/ArtworkId.hpp"
|
||||
#include "image/IEncodedImage.hpp"
|
||||
|
||||
namespace lms::artwork
|
||||
@@ -40,8 +38,7 @@ namespace lms::artwork
|
||||
|
||||
struct EntryDesc
|
||||
{
|
||||
using VariantType = std::variant<db::TrackEmbeddedImageId, db::ImageId>;
|
||||
VariantType id;
|
||||
db::ArtworkId id;
|
||||
std::optional<std::size_t> size;
|
||||
|
||||
bool operator==(const EntryDesc& other) const = default;
|
||||
@@ -63,13 +60,13 @@ namespace lms::artwork
|
||||
std::size_t operator()(const EntryDesc& entry) const
|
||||
{
|
||||
assert(entry.size); // should not cache unresized images
|
||||
return std::hash<EntryDesc::VariantType>{}(entry.id) ^ std::hash<std::size_t>{}(*entry.size);
|
||||
return std::hash<db::ArtworkId>{}(entry.id) ^ std::hash<std::size_t>{}(*entry.size);
|
||||
}
|
||||
};
|
||||
|
||||
std::unordered_map<EntryDesc, std::shared_ptr<image::IEncodedImage>, EntryHasher> _cache;
|
||||
std::size_t _cacheSize{};
|
||||
mutable std::atomic<std::size_t> _cacheMisses{};
|
||||
mutable std::atomic<std::size_t> _cacheHits{};
|
||||
mutable std::atomic<std::size_t> _cacheMisses;
|
||||
mutable std::atomic<std::size_t> _cacheHits;
|
||||
};
|
||||
} // namespace lms::artwork
|
||||
@@ -22,13 +22,8 @@
|
||||
#include <filesystem>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <variant>
|
||||
|
||||
#include "database/ArtistId.hpp"
|
||||
#include "database/ImageId.hpp"
|
||||
#include "database/ReleaseId.hpp"
|
||||
#include "database/TrackEmbeddedImageId.hpp"
|
||||
#include "database/TrackId.hpp"
|
||||
#include "database/ArtworkId.hpp"
|
||||
#include "database/TrackListId.hpp"
|
||||
#include "image/IEncodedImage.hpp"
|
||||
|
||||
@@ -44,27 +39,15 @@ namespace lms::artwork
|
||||
public:
|
||||
virtual ~IArtworkService() = default;
|
||||
|
||||
// Helpers to find artworks
|
||||
using ImageFindResult = std::variant<std::monostate, db::ImageId, db::TrackEmbeddedImageId>;
|
||||
virtual ImageFindResult findArtistImage(db::ArtistId artistId) = 0;
|
||||
// Helpers to get preferred artworks
|
||||
virtual db::ArtworkId findTrackListImage(db::TrackListId trackListId) = 0;
|
||||
|
||||
// Will get Disc/Media artwork if available, otherwise, will fallback on release artwork
|
||||
virtual ImageFindResult findTrackImage(db::TrackId trackId) = 0;
|
||||
|
||||
// Will get Disc/Media artwork if available, no fallback
|
||||
virtual ImageFindResult findTrackMediaImage(db::TrackId trackId) = 0;
|
||||
|
||||
// Will get Release if available, otherwise, will fallback on embedded artworks
|
||||
virtual ImageFindResult findReleaseImage(db::ReleaseId releaseId) = 0;
|
||||
virtual ImageFindResult findTrackListImage(db::TrackListId trackListId) = 0;
|
||||
|
||||
// Image retrieval
|
||||
virtual std::shared_ptr<image::IEncodedImage> getImage(db::ImageId imageId, std::optional<image::ImageSize> width) = 0;
|
||||
virtual std::shared_ptr<image::IEncodedImage> getTrackEmbeddedImage(db::TrackEmbeddedImageId trackEmbeddedImageId, std::optional<image::ImageSize> width) = 0;
|
||||
// Image retrieval, no width means original size
|
||||
virtual std::shared_ptr<image::IEncodedImage> getImage(db::ArtworkId artworkId, std::optional<image::ImageSize> width) = 0;
|
||||
|
||||
// Svg images don't have image "size"
|
||||
virtual std::shared_ptr<image::IEncodedImage> getDefaultReleaseCover() = 0;
|
||||
virtual std::shared_ptr<image::IEncodedImage> getDefaultArtistImage() = 0;
|
||||
virtual std::shared_ptr<image::IEncodedImage> getDefaultReleaseArtwork() = 0;
|
||||
virtual std::shared_ptr<image::IEncodedImage> getDefaultArtistArtwork() = 0;
|
||||
|
||||
virtual void flushCache() = 0;
|
||||
|
||||
|
||||
@@ -60,14 +60,14 @@ namespace lms::scanner
|
||||
return false;
|
||||
}
|
||||
|
||||
struct ReleaseImageAssociation
|
||||
struct ReleaseArtworkAssociation
|
||||
{
|
||||
db::ReleaseId releaseId;
|
||||
db::Release::pointer release;
|
||||
ReleaseArtwork preferredArtwork;
|
||||
};
|
||||
using ReleaseImageAssociationContainer = std::deque<ReleaseImageAssociation>;
|
||||
using ReleaseArtworkAssociationContainer = std::deque<ReleaseArtworkAssociation>;
|
||||
|
||||
struct SearchReleaseImageContext
|
||||
struct SearchReleaseArtworkContext
|
||||
{
|
||||
db::Session& session;
|
||||
db::ReleaseId lastRetrievedReleaseId;
|
||||
@@ -75,7 +75,7 @@ namespace lms::scanner
|
||||
const std::vector<std::string>& releaseImageFileNames;
|
||||
};
|
||||
|
||||
db::Image::pointer findImageInDirectory(SearchReleaseImageContext& searchContext, const std::filesystem::path& directoryPath)
|
||||
db::Image::pointer findImageInDirectory(SearchReleaseArtworkContext& searchContext, const std::filesystem::path& directoryPath)
|
||||
{
|
||||
db::Image::pointer image;
|
||||
|
||||
@@ -101,7 +101,7 @@ namespace lms::scanner
|
||||
return image;
|
||||
}
|
||||
|
||||
db::Image::pointer computePreferredReleaseImage(SearchReleaseImageContext& searchContext, const db::Release::pointer& release)
|
||||
db::Image::pointer computePreferredReleaseImage(SearchReleaseArtworkContext& searchContext, const db::Release::pointer& release)
|
||||
{
|
||||
db::Image::pointer image;
|
||||
|
||||
@@ -149,7 +149,7 @@ namespace lms::scanner
|
||||
return image;
|
||||
}
|
||||
|
||||
ReleaseArtwork computePreferredReleaseArtwork(SearchReleaseImageContext& searchContext, const db::Release::pointer& release)
|
||||
ReleaseArtwork computePreferredReleaseArtwork(SearchReleaseArtworkContext& searchContext, const db::Release::pointer& release)
|
||||
{
|
||||
const db::Image::pointer image{ computePreferredReleaseImage(searchContext, release) };
|
||||
if (image)
|
||||
@@ -187,7 +187,7 @@ namespace lms::scanner
|
||||
return ReleaseArtwork{};
|
||||
}
|
||||
|
||||
bool fetchNextReleaseArtworksToUpdate(SearchReleaseImageContext& searchContext, ReleaseImageAssociationContainer& releaseImageAssociations)
|
||||
bool fetchNextReleaseArtworksToUpdate(SearchReleaseArtworkContext& searchContext, ReleaseArtworkAssociationContainer& ReleaseArtworkAssociations)
|
||||
{
|
||||
const db::ReleaseId releaseId{ searchContext.lastRetrievedReleaseId };
|
||||
|
||||
@@ -201,7 +201,7 @@ namespace lms::scanner
|
||||
const db::Artwork::pointer currentPreferredArtwork{ release->getPreferredArtwork() };
|
||||
|
||||
if (!isSameArtwork(preferredArtwork, currentPreferredArtwork))
|
||||
releaseImageAssociations.push_back(ReleaseImageAssociation{ release->getId(), preferredArtwork });
|
||||
ReleaseArtworkAssociations.push_back(ReleaseArtworkAssociation{ release, preferredArtwork });
|
||||
searchContext.processedReleaseCount++;
|
||||
});
|
||||
}
|
||||
@@ -209,16 +209,14 @@ namespace lms::scanner
|
||||
return releaseId != searchContext.lastRetrievedReleaseId;
|
||||
}
|
||||
|
||||
void updateReleaseArtwork(db::Session& session, const ReleaseImageAssociation& releaseImageAssociation)
|
||||
void updateReleaseArtwork(db::Session& session, const ReleaseArtworkAssociation& ReleaseArtworkAssociation)
|
||||
{
|
||||
db::Release::pointer release{ db::Release::find(session, releaseImageAssociation.releaseId) };
|
||||
assert(release);
|
||||
db::Release::pointer release{ ReleaseArtworkAssociation.release };
|
||||
|
||||
db::Artwork::pointer artwork;
|
||||
|
||||
if (const db::TrackEmbeddedImageId * trackEmbeddedImageId{ std::get_if<db::TrackEmbeddedImageId>(&releaseImageAssociation.preferredArtwork) })
|
||||
if (const db::TrackEmbeddedImageId * trackEmbeddedImageId{ std::get_if<db::TrackEmbeddedImageId>(&ReleaseArtworkAssociation.preferredArtwork) })
|
||||
artwork = utils::getOrCreateArtworkFromTrackEmbeddedImage(session, *trackEmbeddedImageId);
|
||||
else if (const db::ImageId * imageId{ std::get_if<db::ImageId>(&releaseImageAssociation.preferredArtwork) })
|
||||
else if (const db::ImageId * imageId{ std::get_if<db::ImageId>(&ReleaseArtworkAssociation.preferredArtwork) })
|
||||
artwork = utils::getOrCreateArtworkFromImage(session, *imageId);
|
||||
|
||||
release.modify()->setPreferredArtwork(artwork);
|
||||
@@ -229,7 +227,7 @@ namespace lms::scanner
|
||||
LMS_LOG(DBUPDATER, DEBUG, "Removed preferred artwork from release '" << release->getName() << "'");
|
||||
}
|
||||
|
||||
void updateReleaseImages(db::Session& session, ReleaseImageAssociationContainer& imageAssociations)
|
||||
void updateReleaseArtworks(db::Session& session, ReleaseArtworkAssociationContainer& imageAssociations)
|
||||
{
|
||||
constexpr std::size_t writeBatchSize{ 50 };
|
||||
|
||||
@@ -280,19 +278,19 @@ namespace lms::scanner
|
||||
context.currentStepStats.totalElems = db::Release::getCount(session);
|
||||
}
|
||||
|
||||
SearchReleaseImageContext searchContext{
|
||||
SearchReleaseArtworkContext searchContext{
|
||||
.session = session,
|
||||
.lastRetrievedReleaseId = {},
|
||||
.releaseImageFileNames = _releaseImageFileNames,
|
||||
};
|
||||
|
||||
ReleaseImageAssociationContainer releaseImageAssociations;
|
||||
while (fetchNextReleaseArtworksToUpdate(searchContext, releaseImageAssociations))
|
||||
ReleaseArtworkAssociationContainer ReleaseArtworkAssociations;
|
||||
while (fetchNextReleaseArtworksToUpdate(searchContext, ReleaseArtworkAssociations))
|
||||
{
|
||||
if (_abortScan)
|
||||
return;
|
||||
|
||||
updateReleaseImages(session, releaseImageAssociations);
|
||||
updateReleaseArtworks(session, ReleaseArtworkAssociations);
|
||||
context.currentStepStats.processedElems = searchContext.processedReleaseCount;
|
||||
_progressCallback(context.currentStepStats);
|
||||
}
|
||||
|
||||
@@ -62,22 +62,22 @@ namespace lms::scanner
|
||||
return !std::holds_alternative<std::monostate>(res);
|
||||
}
|
||||
|
||||
struct TrackImageAssociation
|
||||
struct TrackArtworksAssociation
|
||||
{
|
||||
db::Track::pointer track;
|
||||
TrackArtwork preferredArtwork;
|
||||
TrackArtwork preferredMediaArtwork;
|
||||
};
|
||||
using TrackImageAssociationContainer = std::deque<TrackImageAssociation>;
|
||||
using TrackArtworksAssociationContainer = std::deque<TrackArtworksAssociation>;
|
||||
|
||||
struct SearchTrackImageContext
|
||||
struct SearchTrackArtworkContext
|
||||
{
|
||||
db::Session& session;
|
||||
db::TrackId lastRetrievedTrackId;
|
||||
std::size_t processedTrackCount{};
|
||||
};
|
||||
|
||||
TrackArtwork computePreferredTrackArtwork(SearchTrackImageContext& searchContext, const db::Track::pointer& track)
|
||||
TrackArtwork computePreferredTrackArtwork(SearchTrackArtworkContext& searchContext, const db::Track::pointer& track)
|
||||
{
|
||||
// Try to get a media image
|
||||
TrackArtwork res;
|
||||
@@ -135,7 +135,7 @@ namespace lms::scanner
|
||||
return res;
|
||||
}
|
||||
|
||||
TrackArtwork computePreferredTrackMediaArtwork(SearchTrackImageContext& searchContext, const db::Track::pointer& track)
|
||||
TrackArtwork computePreferredTrackMediaArtwork(SearchTrackArtworkContext& searchContext, const db::Track::pointer& track)
|
||||
{
|
||||
TrackArtwork res;
|
||||
{
|
||||
@@ -165,7 +165,7 @@ namespace lms::scanner
|
||||
return res;
|
||||
}
|
||||
|
||||
bool fetchNextTrackArtworksToUpdate(SearchTrackImageContext& searchContext, TrackImageAssociationContainer& trackImageAssociations)
|
||||
bool fetchNextTrackArtworksToUpdate(SearchTrackArtworkContext& searchContext, TrackArtworksAssociationContainer& TrackArtworksAssociations)
|
||||
{
|
||||
const db::TrackId trackId{ searchContext.lastRetrievedTrackId };
|
||||
|
||||
@@ -184,7 +184,7 @@ namespace lms::scanner
|
||||
if (!isSameArtwork(preferredArtwork, currentPreferredArtwork)
|
||||
|| !isSameArtwork(preferredMediaArtwork, currentPreferredMediaArtwork))
|
||||
{
|
||||
trackImageAssociations.push_back(TrackImageAssociation{ track, preferredArtwork, preferredMediaArtwork });
|
||||
TrackArtworksAssociations.push_back(TrackArtworksAssociation{ track, preferredArtwork, preferredMediaArtwork });
|
||||
}
|
||||
|
||||
searchContext.processedTrackCount++;
|
||||
@@ -226,24 +226,24 @@ namespace lms::scanner
|
||||
LMS_LOG(DBUPDATER, DEBUG, "Removed preferred media artwork from track '" << track->getAbsoluteFilePath() << "'");
|
||||
}
|
||||
|
||||
void updateTrackPreferredArtworks(db::Session& session, const TrackImageAssociation& trackImageAssociation)
|
||||
void updateTrackPreferredArtworks(db::Session& session, const TrackArtworksAssociation& TrackArtworksAssociation)
|
||||
{
|
||||
db::Track::pointer track{ trackImageAssociation.track };
|
||||
db::Track::pointer track{ TrackArtworksAssociation.track };
|
||||
|
||||
{
|
||||
const db::Artwork::pointer currentPreferredArtwork{ track->getPreferredArtwork() };
|
||||
if (!isSameArtwork(trackImageAssociation.preferredArtwork, currentPreferredArtwork))
|
||||
updateTrackPreferredArtwork(session, track, trackImageAssociation.preferredArtwork);
|
||||
if (!isSameArtwork(TrackArtworksAssociation.preferredArtwork, currentPreferredArtwork))
|
||||
updateTrackPreferredArtwork(session, track, TrackArtworksAssociation.preferredArtwork);
|
||||
}
|
||||
|
||||
{
|
||||
const db::Artwork::pointer currentPreferredMediaArtwork{ track->getPreferredMediaArtwork() };
|
||||
if (!isSameArtwork(trackImageAssociation.preferredMediaArtwork, currentPreferredMediaArtwork))
|
||||
updateTrackPreferredMediaArtwork(session, track, trackImageAssociation.preferredMediaArtwork);
|
||||
if (!isSameArtwork(TrackArtworksAssociation.preferredMediaArtwork, currentPreferredMediaArtwork))
|
||||
updateTrackPreferredMediaArtwork(session, track, TrackArtworksAssociation.preferredMediaArtwork);
|
||||
}
|
||||
}
|
||||
|
||||
void updateTrackPreferredArtworks(db::Session& session, TrackImageAssociationContainer& imageAssociations)
|
||||
void updateTrackPreferredArtworks(db::Session& session, TrackArtworksAssociationContainer& imageAssociations)
|
||||
{
|
||||
constexpr std::size_t writeBatchSize{ 50 };
|
||||
|
||||
@@ -279,18 +279,18 @@ namespace lms::scanner
|
||||
context.currentStepStats.totalElems = db::Track::getCount(session);
|
||||
}
|
||||
|
||||
SearchTrackImageContext searchContext{
|
||||
SearchTrackArtworkContext searchContext{
|
||||
.session = session,
|
||||
.lastRetrievedTrackId = {},
|
||||
};
|
||||
|
||||
TrackImageAssociationContainer trackImageAssociations;
|
||||
while (fetchNextTrackArtworksToUpdate(searchContext, trackImageAssociations))
|
||||
TrackArtworksAssociationContainer TrackArtworksAssociations;
|
||||
while (fetchNextTrackArtworksToUpdate(searchContext, TrackArtworksAssociations))
|
||||
{
|
||||
if (_abortScan)
|
||||
return;
|
||||
|
||||
updateTrackPreferredArtworks(session, trackImageAssociations);
|
||||
updateTrackPreferredArtworks(session, TrackArtworksAssociations);
|
||||
context.currentStepStats.processedElems = searchContext.processedTrackCount;
|
||||
_progressCallback(context.currentStepStats);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user