From de62552ad171e1a744ed89da959039363fe33bba Mon Sep 17 00:00:00 2001 From: Jonas Kvinge Date: Tue, 3 Sep 2024 22:02:05 +0200 Subject: [PATCH] AlbumCoverManager: Queue album cover loading using timer Helps reduce memory growth. --- src/covermanager/albumcovermanager.cpp | 57 ++++++++++++++++++++------ src/covermanager/albumcovermanager.h | 11 +++-- 2 files changed, 53 insertions(+), 15 deletions(-) diff --git a/src/covermanager/albumcovermanager.cpp b/src/covermanager/albumcovermanager.cpp index 3bb13f1e..b7e94e69 100644 --- a/src/covermanager/albumcovermanager.cpp +++ b/src/covermanager/albumcovermanager.cpp @@ -23,6 +23,7 @@ #include #include +#include #include #include @@ -93,6 +94,8 @@ #include "ui_albumcovermanager.h" +using namespace std::literals::chrono_literals; + namespace { constexpr char kSettingsGroup[] = "CoverManager"; constexpr int kThumbnailSize = 120; @@ -105,6 +108,7 @@ AlbumCoverManager::AlbumCoverManager(Application *app, SharedPtrsetupUi(this); ui_->albums->set_cover_manager(this); + timer_album_cover_load_->setSingleShot(false); + timer_album_cover_load_->setInterval(10ms); + QObject::connect(timer_album_cover_load_, &QTimer::timeout, this, &AlbumCoverManager::LoadAlbumCovers); + // Icons ui_->action_fetch->setIcon(IconLoader::Load(QStringLiteral("download"))); ui_->export_covers->setIcon(IconLoader::Load(QStringLiteral("document-save"))); @@ -316,6 +324,7 @@ void AlbumCoverManager::CancelRequests() { #else app_->album_cover_loader()->CancelTasks(QSet::fromList(cover_loading_tasks_.keys())); #endif + cover_loading_pending_.clear(); cover_loading_tasks_.clear(); cover_save_tasks_.clear(); @@ -346,7 +355,7 @@ void AlbumCoverManager::Reset() { all_artists_ = new QListWidgetItem(all_artists_icon_, tr("All artists"), ui_->artists, All_Artists); new AlbumItem(artist_icon_, tr("Various artists"), ui_->artists, Various_Artists); - QStringList artists(collection_backend_->GetAllArtistsWithAlbums()); + QStringList artists = collection_backend_->GetAllArtistsWithAlbums(); std::stable_sort(artists.begin(), artists.end(), CompareNocase); for (const QString &artist : std::as_const(artists)) { @@ -422,7 +431,7 @@ void AlbumCoverManager::ArtistChanged(QListWidgetItem *current) { album_item->setData(Role_ArtUnset, album_info.art_unset); if (album_info.art_embedded || !album_info.art_automatic.isEmpty() || !album_info.art_manual.isEmpty()) { - LoadAlbumCoverAsync(album_item); + QueueAlbumCoverLoad(album_item); } } @@ -431,6 +440,40 @@ void AlbumCoverManager::ArtistChanged(QListWidgetItem *current) { } +void AlbumCoverManager::QueueAlbumCoverLoad(AlbumItem *album_item) { + + cover_loading_pending_.enqueue(album_item); + + if (!timer_album_cover_load_->isActive()) { + timer_album_cover_load_->start(); + } + +} + +void AlbumCoverManager::LoadAlbumCovers() { + + if (cover_loading_pending_.isEmpty()) { + if (timer_album_cover_load_->isActive()) { + timer_album_cover_load_->stop(); + } + return; + } + + LoadAlbumCoverAsync(cover_loading_pending_.dequeue()); + +} + +void AlbumCoverManager::LoadAlbumCoverAsync(AlbumItem *album_item) { + + AlbumCoverLoaderOptions cover_options(AlbumCoverLoaderOptions::Option::ScaledImage | AlbumCoverLoaderOptions::Option::PadScaledImage); + cover_options.types = cover_types_; + cover_options.desired_scaled_size = QSize(kThumbnailSize, kThumbnailSize); + cover_options.device_pixel_ratio = devicePixelRatioF(); + quint64 cover_load_id = app_->album_cover_loader()->LoadImageAsync(cover_options, album_item->data(Role_ArtEmbedded).toBool(), album_item->data(Role_ArtAutomatic).toUrl(), album_item->data(Role_ArtManual).toUrl(), album_item->data(Role_ArtUnset).toBool(), album_item->urls.constFirst()); + cover_loading_tasks_.insert(cover_load_id, album_item); + +} + void AlbumCoverManager::AlbumCoverLoaded(const quint64 id, const AlbumCoverLoaderResult &result) { if (!cover_loading_tasks_.contains(id)) return; @@ -1076,13 +1119,3 @@ void AlbumCoverManager::SaveEmbeddedCoverFinished(TagReaderReply *reply, AlbumIt } -void AlbumCoverManager::LoadAlbumCoverAsync(AlbumItem *album_item) { - - AlbumCoverLoaderOptions cover_options(AlbumCoverLoaderOptions::Option::ScaledImage | AlbumCoverLoaderOptions::Option::PadScaledImage); - cover_options.types = cover_types_; - cover_options.desired_scaled_size = QSize(kThumbnailSize, kThumbnailSize); - cover_options.device_pixel_ratio = devicePixelRatioF(); - quint64 cover_load_id = app_->album_cover_loader()->LoadImageAsync(cover_options, album_item->data(Role_ArtEmbedded).toBool(), album_item->data(Role_ArtAutomatic).toUrl(), album_item->data(Role_ArtManual).toUrl(), album_item->data(Role_ArtUnset).toBool(), album_item->urls.constFirst()); - cover_loading_tasks_.insert(cover_load_id, album_item); - -} diff --git a/src/covermanager/albumcovermanager.h b/src/covermanager/albumcovermanager.h index bbacc428..5b2515e2 100644 --- a/src/covermanager/albumcovermanager.h +++ b/src/covermanager/albumcovermanager.h @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -44,7 +45,7 @@ #include "albumcoverchoicecontroller.h" #include "coversearchstatistics.h" -class QWidget; +class QTimer; class QMimeData; class QMenu; class QAction; @@ -136,6 +137,9 @@ class AlbumCoverManager : public QMainWindow { Song AlbumItemAsSong(QListWidgetItem *list_widget_item) { return AlbumItemAsSong(static_cast(list_widget_item)); } static Song AlbumItemAsSong(AlbumItem *album_item); + void QueueAlbumCoverLoad(AlbumItem *album_item); + void LoadAlbumCoverAsync(AlbumItem *album_item); + void UpdateStatusText(); bool ShouldHide(const AlbumItem &album_item, const QString &filter, const HideCovers hide_covers) const; void SaveAndSetCover(AlbumItem *album_item, const AlbumCoverImageResult &result); @@ -147,14 +151,13 @@ class AlbumCoverManager : public QMainWindow { bool ItemHasCover(const AlbumItem &album_item) const; - void LoadAlbumCoverAsync(AlbumItem *album_item); - Q_SIGNALS: void Error(const QString &error); void AddToPlaylist(QMimeData *data); private Q_SLOTS: void ArtistChanged(QListWidgetItem *current); + void LoadAlbumCovers(); void AlbumCoverLoaded(const quint64 id, const AlbumCoverLoaderResult &result); void UpdateFilter(); void FetchAlbumCovers(); @@ -190,11 +193,13 @@ class AlbumCoverManager : public QMainWindow { Application *app_; SharedPtr collection_backend_; AlbumCoverChoiceController *album_cover_choice_controller_; + QTimer *timer_album_cover_load_; QAction *filter_all_; QAction *filter_with_covers_; QAction *filter_without_covers_; + QQueue cover_loading_pending_; QMap cover_loading_tasks_; AlbumCoverFetcher *cover_fetcher_;