Use std::shared_ptrfor AlbumCoverLoaderResult
Reduces memory fragmentation with Qt 6
This commit is contained in:
@@ -21,6 +21,8 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QObject>
|
||||
#include <QStandardPaths>
|
||||
@@ -81,8 +83,9 @@ void AlbumCoverLoader::Exit() {
|
||||
void AlbumCoverLoader::CancelTask(const quint64 id) {
|
||||
|
||||
QMutexLocker l(&mutex_load_image_async_);
|
||||
for (QQueue<Task>::iterator it = tasks_.begin(); it != tasks_.end(); ++it) {
|
||||
if (it->id == id) {
|
||||
for (QQueue<TaskPtr>::iterator it = tasks_.begin(); it != tasks_.end(); ++it) {
|
||||
TaskPtr task = *it;
|
||||
if (task->id == id) {
|
||||
tasks_.erase(it); // clazy:exclude=strict-iterators
|
||||
break;
|
||||
}
|
||||
@@ -93,8 +96,9 @@ void AlbumCoverLoader::CancelTask(const quint64 id) {
|
||||
void AlbumCoverLoader::CancelTasks(const QSet<quint64> &ids) {
|
||||
|
||||
QMutexLocker l(&mutex_load_image_async_);
|
||||
for (QQueue<Task>::iterator it = tasks_.begin(); it != tasks_.end();) {
|
||||
if (ids.contains(it->id)) {
|
||||
for (QQueue<TaskPtr>::iterator it = tasks_.begin(); it != tasks_.end();) {
|
||||
TaskPtr task = *it;
|
||||
if (ids.contains(task->id)) {
|
||||
it = tasks_.erase(it); // clazy:exclude=strict-iterators
|
||||
}
|
||||
else {
|
||||
@@ -106,10 +110,11 @@ void AlbumCoverLoader::CancelTasks(const QSet<quint64> &ids) {
|
||||
|
||||
quint64 AlbumCoverLoader::LoadImageAsync(const AlbumCoverLoaderOptions &options, const Song &song) {
|
||||
|
||||
Task task;
|
||||
task.options = options;
|
||||
task.song = song;
|
||||
task.state = State::Manual;
|
||||
TaskPtr task = std::make_shared<Task>();
|
||||
task->options = options;
|
||||
task->song = song;
|
||||
task->state = State::Manual;
|
||||
task->album_cover = std::make_shared<AlbumCoverImageResult>();
|
||||
|
||||
return EnqueueTask(task);
|
||||
|
||||
@@ -122,20 +127,21 @@ quint64 AlbumCoverLoader::LoadImageAsync(const AlbumCoverLoaderOptions &options,
|
||||
song.set_art_automatic(art_automatic);
|
||||
song.set_art_manual(art_manual);
|
||||
|
||||
Task task;
|
||||
task.options = options;
|
||||
task.song = song;
|
||||
task.state = State::Manual;
|
||||
TaskPtr task = std::make_shared<Task>();
|
||||
task->options = options;
|
||||
task->song = song;
|
||||
task->state = State::Manual;
|
||||
task->album_cover = std::make_shared<AlbumCoverImageResult>();
|
||||
|
||||
return EnqueueTask(task);
|
||||
|
||||
}
|
||||
|
||||
quint64 AlbumCoverLoader::LoadImageAsync(const AlbumCoverLoaderOptions &options, const AlbumCoverImageResult &album_cover) {
|
||||
quint64 AlbumCoverLoader::LoadImageAsync(const AlbumCoverLoaderOptions &options, AlbumCoverImageResultPtr album_cover) {
|
||||
|
||||
Task task;
|
||||
task.options = options;
|
||||
task.album_cover = album_cover;
|
||||
TaskPtr task = std::make_shared<Task>();
|
||||
task->options = options;
|
||||
task->album_cover = album_cover;
|
||||
|
||||
return EnqueueTask(task);
|
||||
|
||||
@@ -143,25 +149,26 @@ quint64 AlbumCoverLoader::LoadImageAsync(const AlbumCoverLoaderOptions &options,
|
||||
|
||||
quint64 AlbumCoverLoader::LoadImageAsync(const AlbumCoverLoaderOptions &options, const QImage &image) {
|
||||
|
||||
Task task;
|
||||
task.options = options;
|
||||
task.album_cover.image = image;
|
||||
TaskPtr task = std::make_shared<Task>();
|
||||
task->options = options;
|
||||
task->album_cover = std::make_shared<AlbumCoverImageResult>();
|
||||
task->album_cover->image = image;
|
||||
|
||||
return EnqueueTask(task);
|
||||
|
||||
}
|
||||
|
||||
quint64 AlbumCoverLoader::EnqueueTask(Task &task) {
|
||||
quint64 AlbumCoverLoader::EnqueueTask(TaskPtr task) {
|
||||
|
||||
{
|
||||
QMutexLocker l(&mutex_load_image_async_);
|
||||
task.id = load_image_async_id_++;
|
||||
task->id = load_image_async_id_++;
|
||||
tasks_.enqueue(task);
|
||||
}
|
||||
|
||||
QMetaObject::invokeMethod(this, "ProcessTasks", Qt::QueuedConnection);
|
||||
|
||||
return task.id;
|
||||
return task->id;
|
||||
|
||||
}
|
||||
|
||||
@@ -169,19 +176,19 @@ void AlbumCoverLoader::ProcessTasks() {
|
||||
|
||||
while (!stop_requested_) {
|
||||
// Get the next task
|
||||
Task task;
|
||||
TaskPtr task;
|
||||
{
|
||||
QMutexLocker l(&mutex_load_image_async_);
|
||||
if (tasks_.isEmpty()) return;
|
||||
task = tasks_.dequeue();
|
||||
}
|
||||
|
||||
ProcessTask(&task);
|
||||
ProcessTask(task);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void AlbumCoverLoader::ProcessTask(Task *task) {
|
||||
void AlbumCoverLoader::ProcessTask(TaskPtr task) {
|
||||
|
||||
TryLoadResult result = TryLoadImage(task);
|
||||
if (result.started_async) {
|
||||
@@ -190,16 +197,16 @@ void AlbumCoverLoader::ProcessTask(Task *task) {
|
||||
}
|
||||
|
||||
if (result.loaded_success) {
|
||||
result.album_cover.mime_type = Utilities::MimeTypeFromData(result.album_cover.image_data);
|
||||
result.album_cover->mime_type = Utilities::MimeTypeFromData(result.album_cover->image_data);
|
||||
QImage image_scaled;
|
||||
QImage image_thumbnail;
|
||||
if (task->options.get_image_ && task->options.scale_output_image_) {
|
||||
image_scaled = ImageUtils::ScaleAndPad(result.album_cover.image, task->options.scale_output_image_, task->options.pad_output_image_, task->options.desired_height_);
|
||||
image_scaled = ImageUtils::ScaleAndPad(result.album_cover->image, task->options.scale_output_image_, task->options.pad_output_image_, task->options.desired_height_);
|
||||
}
|
||||
if (task->options.get_image_ && task->options.create_thumbnail_) {
|
||||
image_thumbnail = ImageUtils::CreateThumbnail(result.album_cover.image, task->options.pad_thumbnail_image_, task->options.thumbnail_size_);
|
||||
image_thumbnail = ImageUtils::CreateThumbnail(result.album_cover->image, task->options.pad_thumbnail_image_, task->options.thumbnail_size_);
|
||||
}
|
||||
emit AlbumCoverLoaded(task->id, AlbumCoverLoaderResult(result.loaded_success, result.type, result.album_cover, image_scaled, image_thumbnail, task->art_updated));
|
||||
emit AlbumCoverLoaded(task->id, std::make_shared<AlbumCoverLoaderResult>(result.loaded_success, result.type, result.album_cover, image_scaled, image_thumbnail, task->art_updated));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -207,7 +214,7 @@ void AlbumCoverLoader::ProcessTask(Task *task) {
|
||||
|
||||
}
|
||||
|
||||
void AlbumCoverLoader::NextState(Task *task) {
|
||||
void AlbumCoverLoader::NextState(TaskPtr task) {
|
||||
|
||||
if (task->state == State::Manual) {
|
||||
// Try the automatic one next
|
||||
@@ -216,15 +223,15 @@ void AlbumCoverLoader::NextState(Task *task) {
|
||||
}
|
||||
else {
|
||||
// Give up
|
||||
emit AlbumCoverLoaded(task->id, AlbumCoverLoaderResult(false, AlbumCoverLoaderResult::Type::None, AlbumCoverImageResult(task->options.default_output_image_), task->options.default_scaled_image_, task->options.default_thumbnail_image_, task->art_updated));
|
||||
emit AlbumCoverLoaded(task->id, std::make_shared<AlbumCoverLoaderResult>(false, AlbumCoverLoaderResult::Type::None, std::make_shared<AlbumCoverImageResult>(task->options.default_output_image_), task->options.default_scaled_image_, task->options.default_thumbnail_image_, task->art_updated));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
AlbumCoverLoader::TryLoadResult AlbumCoverLoader::TryLoadImage(Task *task) {
|
||||
AlbumCoverLoader::TryLoadResult AlbumCoverLoader::TryLoadImage(TaskPtr task) {
|
||||
|
||||
// Only scale and pad.
|
||||
if (task->album_cover.is_valid()) {
|
||||
if (task->album_cover->is_valid()) {
|
||||
return TryLoadResult(false, true, AlbumCoverLoaderResult::Type::Embedded, task->album_cover);
|
||||
}
|
||||
|
||||
@@ -263,17 +270,17 @@ AlbumCoverLoader::TryLoadResult AlbumCoverLoader::TryLoadImage(Task *task) {
|
||||
|
||||
if (!cover_url.isEmpty() && !cover_url.path().isEmpty()) {
|
||||
if (cover_url.path() == Song::kManuallyUnsetCover) {
|
||||
return TryLoadResult(false, true, AlbumCoverLoaderResult::Type::ManuallyUnset, AlbumCoverImageResult(cover_url, QString(), QByteArray(), task->options.default_output_image_));
|
||||
return TryLoadResult(false, true, AlbumCoverLoaderResult::Type::ManuallyUnset, std::make_shared<AlbumCoverImageResult>(cover_url, QString(), QByteArray(), task->options.default_output_image_));
|
||||
}
|
||||
else if (cover_url.path() == Song::kEmbeddedCover && task->song.url().isLocalFile()) {
|
||||
QByteArray image_data = TagReaderClient::Instance()->LoadEmbeddedArtBlocking(task->song.url().toLocalFile());
|
||||
if (!image_data.isEmpty()) {
|
||||
QImage image;
|
||||
if (!image_data.isEmpty() && task->options.get_image_ && image.loadFromData(image_data)) {
|
||||
return TryLoadResult(false, !image.isNull(), AlbumCoverLoaderResult::Type::Embedded, AlbumCoverImageResult(cover_url, QString(), image_data, image));
|
||||
return TryLoadResult(false, !image.isNull(), AlbumCoverLoaderResult::Type::Embedded, std::make_shared<AlbumCoverImageResult>(cover_url, QString(), image_data, image));
|
||||
}
|
||||
else {
|
||||
return TryLoadResult(false, !image_data.isEmpty(), AlbumCoverLoaderResult::Type::Embedded, AlbumCoverImageResult(cover_url, QString(), image_data, image));
|
||||
return TryLoadResult(false, !image_data.isEmpty(), AlbumCoverLoaderResult::Type::Embedded, std::make_shared<AlbumCoverImageResult>(cover_url, QString(), image_data, image));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -286,10 +293,10 @@ AlbumCoverLoader::TryLoadResult AlbumCoverLoader::TryLoadImage(Task *task) {
|
||||
file.close();
|
||||
QImage image;
|
||||
if (!image_data.isEmpty() && task->options.get_image_ && image.loadFromData(image_data)) {
|
||||
return TryLoadResult(false, !image.isNull(), type, AlbumCoverImageResult(cover_url, QString(), image_data, image.isNull() ? task->options.default_output_image_ : image));
|
||||
return TryLoadResult(false, !image.isNull(), type, std::make_shared<AlbumCoverImageResult>(cover_url, QString(), image_data, image.isNull() ? task->options.default_output_image_ : image));
|
||||
}
|
||||
else {
|
||||
return TryLoadResult(false, !image_data.isEmpty(), type, AlbumCoverImageResult(cover_url, QString(), image_data, image.isNull() ? task->options.default_output_image_ : image));
|
||||
return TryLoadResult(false, !image_data.isEmpty(), type, std::make_shared<AlbumCoverImageResult>(cover_url, QString(), image_data, image.isNull() ? task->options.default_output_image_ : image));
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -308,10 +315,10 @@ AlbumCoverLoader::TryLoadResult AlbumCoverLoader::TryLoadImage(Task *task) {
|
||||
file.close();
|
||||
QImage image;
|
||||
if (!image_data.isEmpty() && task->options.get_image_ && image.loadFromData(image_data)) {
|
||||
return TryLoadResult(false, !image.isNull(), type, AlbumCoverImageResult(cover_url, QString(), image_data, image.isNull() ? task->options.default_output_image_ : image));
|
||||
return TryLoadResult(false, !image.isNull(), type, std::make_shared<AlbumCoverImageResult>(cover_url, QString(), image_data, image.isNull() ? task->options.default_output_image_ : image));
|
||||
}
|
||||
else {
|
||||
return TryLoadResult(false, !image_data.isEmpty(), type, AlbumCoverImageResult(cover_url, QString(), image_data, image.isNull() ? task->options.default_output_image_ : image));
|
||||
return TryLoadResult(false, !image_data.isEmpty(), type, std::make_shared<AlbumCoverImageResult>(cover_url, QString(), image_data, image.isNull() ? task->options.default_output_image_ : image));
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -329,12 +336,12 @@ AlbumCoverLoader::TryLoadResult AlbumCoverLoader::TryLoadImage(Task *task) {
|
||||
QNetworkReply *reply = network_->get(request);
|
||||
QObject::connect(reply, &QNetworkReply::finished, this, [this, reply, cover_url]() { RemoteFetchFinished(reply, cover_url); });
|
||||
|
||||
remote_tasks_.insert(reply, *task);
|
||||
return TryLoadResult(true, false, type, AlbumCoverImageResult(cover_url));
|
||||
remote_tasks_.insert(reply, task);
|
||||
return TryLoadResult(true, false, type, std::make_shared<AlbumCoverImageResult>(cover_url));
|
||||
}
|
||||
}
|
||||
|
||||
return TryLoadResult(false, false, AlbumCoverLoaderResult::Type::None, AlbumCoverImageResult(cover_url, QString(), QByteArray(), task->options.default_output_image_));
|
||||
return TryLoadResult(false, false, AlbumCoverLoaderResult::Type::None, std::make_shared<AlbumCoverImageResult>(cover_url, QString(), QByteArray(), task->options.default_output_image_));
|
||||
|
||||
}
|
||||
|
||||
@@ -343,12 +350,12 @@ void AlbumCoverLoader::RemoteFetchFinished(QNetworkReply *reply, const QUrl &cov
|
||||
reply->deleteLater();
|
||||
|
||||
if (!remote_tasks_.contains(reply)) return;
|
||||
Task task = remote_tasks_.take(reply);
|
||||
TaskPtr task = remote_tasks_.take(reply);
|
||||
|
||||
// Handle redirects.
|
||||
QVariant redirect = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
|
||||
if (redirect.isValid()) {
|
||||
if (++task.redirects > kMaxRedirects) {
|
||||
if (++task->redirects > kMaxRedirects) {
|
||||
return; // Give up.
|
||||
}
|
||||
QNetworkRequest request = reply->request();
|
||||
@@ -369,9 +376,9 @@ void AlbumCoverLoader::RemoteFetchFinished(QNetworkReply *reply, const QUrl &cov
|
||||
if (image.loadFromData(image_data)) {
|
||||
QImage image_scaled;
|
||||
QImage image_thumbnail;
|
||||
if (task.options.scale_output_image_) image_scaled = ImageUtils::ScaleAndPad(image, task.options.scale_output_image_, task.options.pad_output_image_, task.options.desired_height_);
|
||||
if (task.options.create_thumbnail_) image_thumbnail = ImageUtils::CreateThumbnail(image, task.options.pad_thumbnail_image_, task.options.thumbnail_size_);
|
||||
emit AlbumCoverLoaded(task.id, AlbumCoverLoaderResult(true, task.type, AlbumCoverImageResult(cover_url, mime_type, (task.options.get_image_data_ ? image_data : QByteArray()), image), image_scaled, image_thumbnail, task.art_updated));
|
||||
if (task->options.scale_output_image_) image_scaled = ImageUtils::ScaleAndPad(image, task->options.scale_output_image_, task->options.pad_output_image_, task->options.desired_height_);
|
||||
if (task->options.create_thumbnail_) image_thumbnail = ImageUtils::CreateThumbnail(image, task->options.pad_thumbnail_image_, task->options.thumbnail_size_);
|
||||
emit AlbumCoverLoaded(task->id, std::make_shared<AlbumCoverLoaderResult>(true, task->type, std::make_shared<AlbumCoverImageResult>(cover_url, mime_type, (task->options.get_image_data_ ? image_data : QByteArray()), image), image_scaled, image_thumbnail, task->art_updated));
|
||||
return;
|
||||
}
|
||||
else {
|
||||
@@ -382,7 +389,7 @@ void AlbumCoverLoader::RemoteFetchFinished(QNetworkReply *reply, const QUrl &cov
|
||||
qLog(Error) << "Unable to get album cover" << cover_url << reply->error() << reply->errorString();
|
||||
}
|
||||
|
||||
NextState(&task);
|
||||
NextState(task);
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user