Rewrite album cover loader
This commit is contained in:
@@ -1,8 +1,6 @@
|
||||
/*
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2019-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
* Copyright 2019-2023, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -24,21 +22,19 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QObject>
|
||||
#include <QMutex>
|
||||
#include <QPair>
|
||||
#include <QSet>
|
||||
#include <QHash>
|
||||
#include <QMultiMap>
|
||||
#include <QQueue>
|
||||
#include <QByteArray>
|
||||
#include <QString>
|
||||
#include <QImage>
|
||||
#include <QPixmap>
|
||||
|
||||
#include "core/song.h"
|
||||
#include "core/tagreaderclient.h"
|
||||
#include "albumcoverloaderoptions.h"
|
||||
#include "albumcoverloaderresult.h"
|
||||
#include "albumcoverimageresult.h"
|
||||
@@ -47,111 +43,96 @@ class QThread;
|
||||
class QNetworkReply;
|
||||
class NetworkAccessManager;
|
||||
|
||||
using std::shared_ptr;
|
||||
|
||||
class AlbumCoverLoader : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AlbumCoverLoader(QObject *parent = nullptr);
|
||||
|
||||
enum class State {
|
||||
None,
|
||||
Manual,
|
||||
Automatic
|
||||
};
|
||||
|
||||
void ExitAsync();
|
||||
void Stop() { stop_requested_ = true; }
|
||||
|
||||
quint64 LoadImageAsync(const AlbumCoverLoaderOptions &options, const Song &song);
|
||||
quint64 LoadImageAsync(const AlbumCoverLoaderOptions &options, const QUrl &art_automatic, const QUrl &art_manual, const QUrl &song_url = QUrl(), const Song::Source song_source = Song::Source::Unknown);
|
||||
quint64 LoadImageAsync(const AlbumCoverLoaderOptions &options, const bool art_embedded, const QUrl &art_automatic, const QUrl &art_manual, const bool art_unset, const QUrl &song_url = QUrl(), const Song::Source song_source = Song::Source::Unknown);
|
||||
quint64 LoadImageAsync(const AlbumCoverLoaderOptions &options, const AlbumCoverImageResult &album_cover);
|
||||
quint64 LoadImageAsync(const AlbumCoverLoaderOptions &options, const QImage &image);
|
||||
|
||||
void CancelTask(const quint64 id);
|
||||
void CancelTasks(const QSet<quint64> &ids);
|
||||
|
||||
quint64 SaveEmbeddedCoverAsync(const QString &song_filename, const QString &cover_filename);
|
||||
quint64 SaveEmbeddedCoverAsync(const QString &song_filename, const QImage &image);
|
||||
quint64 SaveEmbeddedCoverAsync(const QString &song_filename, const QByteArray &image_data);
|
||||
quint64 SaveEmbeddedCoverAsync(const QList<QUrl> &urls, const QString &cover_filename);
|
||||
quint64 SaveEmbeddedCoverAsync(const QList<QUrl> &urls, const QImage &image);
|
||||
quint64 SaveEmbeddedCoverAsync(const QList<QUrl> &urls, const QByteArray &image_data);
|
||||
|
||||
signals:
|
||||
void ExitFinished();
|
||||
void AlbumCoverLoaded(const quint64 id, const AlbumCoverLoaderResult &result);
|
||||
void SaveEmbeddedCoverAsyncFinished(const quint64 id, const bool success, const bool cleared);
|
||||
|
||||
protected slots:
|
||||
void Exit();
|
||||
void ProcessTasks();
|
||||
void RemoteFetchFinished(QNetworkReply *reply, const QUrl &cover_url);
|
||||
private:
|
||||
class Task {
|
||||
public:
|
||||
explicit Task() : id(0), success(false), art_embedded(false), art_unset(false), result_type(AlbumCoverLoaderResult::Type::None), art_updated(false), redirects(0) {}
|
||||
|
||||
void SaveEmbeddedCover(const quint64 id, const QString &song_filename, const QString &cover_filename);
|
||||
void SaveEmbeddedCover(const quint64 id, const QString &song_filename, const QImage &image);
|
||||
void SaveEmbeddedCover(const quint64 id, const QString &song_filename, const QByteArray &image_data);
|
||||
void SaveEmbeddedCover(const quint64 id, const QList<QUrl> &urls, const QImage &image);
|
||||
void SaveEmbeddedCover(const quint64 id, const QList<QUrl> &urls, const QString &cover_filename);
|
||||
void SaveEmbeddedCover(const quint64 id, const QList<QUrl> &urls, const QByteArray &image_data);
|
||||
|
||||
void SaveEmbeddedArtFinished(const quint64 id, TagReaderReply *reply, const bool cleared);
|
||||
|
||||
protected:
|
||||
|
||||
struct Task {
|
||||
explicit Task() : id(0), state(State::None), type(AlbumCoverLoaderResult::Type::None), art_updated(false), redirects(0) {}
|
||||
quint64 id;
|
||||
bool success;
|
||||
|
||||
AlbumCoverLoaderOptions options;
|
||||
|
||||
quint64 id;
|
||||
bool raw_image_data() const { return options.options & AlbumCoverLoaderOptions::Option::RawImageData; }
|
||||
bool original_image() const { return options.options & AlbumCoverLoaderOptions::Option::OriginalImage; }
|
||||
bool scaled_image() const { return options.options & AlbumCoverLoaderOptions::Option::ScaledImage; }
|
||||
bool pad_scaled_image() const { return options.options & AlbumCoverLoaderOptions::Option::PadScaledImage; }
|
||||
|
||||
bool art_embedded;
|
||||
QUrl art_automatic;
|
||||
QUrl art_manual;
|
||||
bool art_unset;
|
||||
QUrl song_url;
|
||||
Song::Source song_source;
|
||||
Song song;
|
||||
AlbumCoverImageResult album_cover;
|
||||
State state;
|
||||
AlbumCoverLoaderResult::Type type;
|
||||
AlbumCoverLoaderResult::Type result_type;
|
||||
bool art_updated;
|
||||
int redirects;
|
||||
};
|
||||
using TaskPtr = std::shared_ptr<Task>;
|
||||
|
||||
struct TryLoadResult {
|
||||
explicit TryLoadResult(const bool _started_async = false,
|
||||
const bool _loaded_success = false,
|
||||
const AlbumCoverLoaderResult::Type _type = AlbumCoverLoaderResult::Type::None,
|
||||
const AlbumCoverImageResult &_album_cover = AlbumCoverImageResult()) :
|
||||
started_async(_started_async),
|
||||
loaded_success(_loaded_success),
|
||||
type(_type),
|
||||
album_cover(_album_cover) {}
|
||||
|
||||
bool started_async;
|
||||
bool loaded_success;
|
||||
using TaskPtr = shared_ptr<Task>;
|
||||
|
||||
class LoadImageResult {
|
||||
public:
|
||||
enum class Status {
|
||||
Failure,
|
||||
Async,
|
||||
Success
|
||||
};
|
||||
explicit LoadImageResult(AlbumCoverLoaderResult::Type _type = AlbumCoverLoaderResult::Type::None, Status _status = Status::Failure) : type(_type), status(_status) {}
|
||||
AlbumCoverLoaderResult::Type type;
|
||||
AlbumCoverImageResult album_cover;
|
||||
Status status;
|
||||
};
|
||||
|
||||
private:
|
||||
quint64 EnqueueTask(TaskPtr task);
|
||||
void ProcessTask(TaskPtr task);
|
||||
void NextState(TaskPtr task);
|
||||
TryLoadResult TryLoadImage(TaskPtr task);
|
||||
void InitArt(TaskPtr task);
|
||||
LoadImageResult LoadImage(TaskPtr task, const AlbumCoverLoaderOptions::Type &type);
|
||||
LoadImageResult LoadEmbeddedImage(TaskPtr task);
|
||||
LoadImageResult LoadUrlImage(TaskPtr task, const AlbumCoverLoaderResult::Type result_type, const QUrl &cover_url);
|
||||
LoadImageResult LoadLocalUrlImage(TaskPtr task, const AlbumCoverLoaderResult::Type result_type, const QUrl &cover_url);
|
||||
LoadImageResult LoadLocalFileImage(TaskPtr task, const AlbumCoverLoaderResult::Type result_type, const QString &cover_file);
|
||||
LoadImageResult LoadRemoteUrlImage(TaskPtr task, const AlbumCoverLoaderResult::Type result_type, const QUrl &cover_url);
|
||||
void FinishTask(TaskPtr task, const AlbumCoverLoaderResult::Type result_type);
|
||||
|
||||
NetworkAccessManager *network_;
|
||||
|
||||
bool stop_requested_;
|
||||
|
||||
QMutex mutex_load_image_async_;
|
||||
QMutex mutex_save_image_async_;
|
||||
QQueue<TaskPtr> tasks_;
|
||||
QHash<QNetworkReply*, TaskPtr> remote_tasks_;
|
||||
quint64 load_image_async_id_;
|
||||
quint64 save_image_async_id_;
|
||||
private slots:
|
||||
void Exit();
|
||||
void ProcessTasks();
|
||||
void LoadRemoteImageFinished(QNetworkReply *reply, TaskPtr task, const AlbumCoverLoaderResult::Type result_type, const QUrl &cover_url);
|
||||
|
||||
private:
|
||||
static const int kMaxRedirects = 3;
|
||||
|
||||
NetworkAccessManager *network_;
|
||||
bool stop_requested_;
|
||||
QMutex mutex_load_image_async_;
|
||||
QQueue<TaskPtr> tasks_;
|
||||
quint64 load_image_async_id_;
|
||||
QThread *original_thread_;
|
||||
|
||||
QMultiMap<quint64, TagReaderReply*> tagreader_save_embedded_art_requests_;
|
||||
|
||||
};
|
||||
|
||||
#endif // ALBUMCOVERLOADER_H
|
||||
|
||||
Reference in New Issue
Block a user