From bacef04405310f18a9927def7dcd6fc445a28727 Mon Sep 17 00:00:00 2001 From: David Sansome Date: Mon, 13 Feb 2012 20:44:04 +0000 Subject: [PATCH] Refactoring: remove a couple of the AlbumCoverLoader instances and instead use a shared CurrentArtLoader. --- src/CMakeLists.txt | 4 +- src/core/application.cpp | 8 + src/core/application.h | 13 +- src/core/mpris.cpp | 7 +- src/core/mpris.h | 3 +- src/core/mpris1.cpp | 6 +- src/core/mpris1.h | 3 +- src/core/mpris2.cpp | 7 +- src/core/mpris2.h | 4 +- src/covers/albumcoverloader.cpp | 72 +++++--- src/covers/albumcoverloader.h | 23 +-- src/covers/albumcoverloaderoptions.cpp | 19 +++ src/covers/albumcoverloaderoptions.h | 36 ++++ .../{artloader.cpp => currentartloader.cpp} | 37 ++-- .../{artloader.h => currentartloader.h} | 24 +-- src/covers/kittenloader.cpp | 8 +- src/covers/kittenloader.h | 6 +- src/devices/gpoddevice.cpp | 1 + src/devices/mtpdevice.cpp | 1 + .../digitallyimportedsearchprovider.cpp | 4 +- .../digitallyimportedsearchprovider.h | 2 +- src/globalsearch/globalsearch.cpp | 16 +- src/globalsearch/globalsearch.h | 5 +- .../groovesharksearchprovider.cpp | 20 ++- src/globalsearch/groovesharksearchprovider.h | 5 +- src/globalsearch/icecastsearchprovider.cpp | 5 +- src/globalsearch/icecastsearchprovider.h | 2 +- src/globalsearch/lastfmsearchprovider.cpp | 5 +- src/globalsearch/lastfmsearchprovider.h | 2 +- src/globalsearch/librarysearchprovider.cpp | 3 +- src/globalsearch/librarysearchprovider.h | 3 +- src/globalsearch/savedradiosearchprovider.cpp | 5 +- src/globalsearch/savedradiosearchprovider.h | 2 +- src/globalsearch/searchprovider.cpp | 7 +- src/globalsearch/searchprovider.h | 7 +- src/globalsearch/simplesearchprovider.cpp | 4 +- src/globalsearch/simplesearchprovider.h | 2 +- src/globalsearch/somafmsearchprovider.cpp | 4 +- src/globalsearch/somafmsearchprovider.h | 2 +- src/globalsearch/spotifysearchprovider.cpp | 4 +- src/globalsearch/spotifysearchprovider.h | 2 +- src/globalsearch/urlsearchprovider.cpp | 4 +- src/globalsearch/urlsearchprovider.h | 2 +- src/internet/digitallyimportedservicebase.cpp | 3 +- src/internet/digitallyimportedsettingspage.h | 2 + src/internet/groovesharkservice.cpp | 2 +- src/internet/groovesharkservice.h | 4 +- src/internet/icecastservice.cpp | 2 +- src/internet/jamendoservice.cpp | 3 +- src/internet/lastfmservice.cpp | 2 +- src/internet/magnatuneservice.cpp | 3 +- src/internet/savedradio.cpp | 2 +- src/internet/somafmservice.cpp | 2 +- src/internet/somafmservice.h | 1 + src/internet/spotifyservice.cpp | 2 +- src/library/librarymodel.cpp | 15 +- src/library/librarymodel.h | 4 +- src/library/libraryview.cpp | 2 +- src/main.cpp | 11 +- src/ui/albumcoverchoicecontroller.cpp | 5 + src/ui/albumcovermanager.cpp | 30 ++-- src/ui/albumcovermanager.h | 6 +- src/ui/albumcoversearcher.cpp | 14 +- src/ui/albumcoversearcher.h | 4 +- src/ui/edittagdialog.cpp | 10 +- src/ui/edittagdialog.h | 5 +- src/ui/mainwindow.cpp | 12 +- src/ui/mainwindow.h | 2 - src/widgets/nowplayingwidget.cpp | 160 ++++++++---------- src/widgets/nowplayingwidget.h | 21 ++- src/widgets/osd.cpp | 60 +++---- src/widgets/osd.h | 22 +-- 72 files changed, 413 insertions(+), 397 deletions(-) create mode 100644 src/covers/albumcoverloaderoptions.cpp create mode 100644 src/covers/albumcoverloaderoptions.h rename src/covers/{artloader.cpp => currentartloader.cpp} (70%) rename src/covers/{artloader.h => currentartloader.h} (74%) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 77366dc35..533295f30 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -109,11 +109,11 @@ set(SOURCES covers/albumcoverfetchersearch.cpp covers/albumcoverloader.cpp covers/amazoncoverprovider.cpp - covers/artloader.cpp covers/coverprovider.cpp covers/coverproviders.cpp covers/coversearchstatistics.cpp covers/coversearchstatisticsdialog.cpp + covers/currentartloader.cpp covers/discogscoverprovider.cpp covers/kittenloader.cpp @@ -367,10 +367,10 @@ set(HEADERS covers/albumcoverfetchersearch.h covers/albumcoverloader.h covers/amazoncoverprovider.h - covers/artloader.h covers/coverprovider.h covers/coverproviders.h covers/coversearchstatisticsdialog.h + covers/currentartloader.h covers/discogscoverprovider.h covers/kittenloader.h diff --git a/src/core/application.cpp b/src/core/application.cpp index ce8a7fbe6..9954b25b2 100644 --- a/src/core/application.cpp +++ b/src/core/application.cpp @@ -21,7 +21,9 @@ #include "player.h" #include "tagreaderclient.h" #include "taskmanager.h" +#include "covers/albumcoverloader.h" #include "covers/coverproviders.h" +#include "covers/currentartloader.h" #include "devices/devicemanager.h" #include "internet/internetmodel.h" #include "globalsearch/globalsearch.h" @@ -34,11 +36,13 @@ Application::Application(QObject* parent) : QObject(parent), tag_reader_client_(NULL), database_(NULL), + album_cover_loader_(NULL), appearance_(NULL), cover_providers_(NULL), task_manager_(NULL), player_(NULL), playlist_manager_(NULL), + current_art_loader_(NULL), global_search_(NULL), internet_model_(NULL), library_(NULL), @@ -52,11 +56,15 @@ Application::Application(QObject* parent) database_ = new Database(this, this); MoveToNewThread(database_); + album_cover_loader_ = new AlbumCoverLoader(this); + MoveToNewThread(album_cover_loader_); + appearance_ = new Appearance(this); cover_providers_ = new CoverProviders(this); task_manager_ = new TaskManager(this); player_ = new Player(this, this); playlist_manager_ = new PlaylistManager(this, this); + current_art_loader_ = new CurrentArtLoader(this, this); global_search_ = new GlobalSearch(this, this); internet_model_ = new InternetModel(this, this); diff --git a/src/core/application.h b/src/core/application.h index ffe3f9223..a43487aec 100644 --- a/src/core/application.h +++ b/src/core/application.h @@ -20,8 +20,10 @@ #include +class AlbumCoverLoader; class Appearance; class CoverProviders; +class CurrentArtLoader; class Database; class DeviceManager; class GlobalSearch; @@ -45,11 +47,13 @@ public: TagReaderClient* tag_reader_client() const { return tag_reader_client_; } Database* database() const { return database_; } + AlbumCoverLoader* album_cover_loader() const { return album_cover_loader_; } Appearance* appearance() const { return appearance_; } CoverProviders* cover_providers() const { return cover_providers_; } TaskManager* task_manager() const { return task_manager_; } Player* player() const { return player_; } PlaylistManager* playlist_manager() const { return playlist_manager_; } + CurrentArtLoader* current_art_loader() const { return current_art_loader_; } GlobalSearch* global_search() const { return global_search_; } InternetModel* internet_model() const { return internet_model_; } @@ -60,24 +64,25 @@ public: LibraryBackend* library_backend() const; LibraryModel* library_model() const; + void MoveToNewThread(QObject* object); + void MoveToThread(QObject* object, QThread* thread); + public slots: void AddError(const QString& message); signals: void ErrorAdded(const QString& message); -private: - void MoveToNewThread(QObject* object); - void MoveToThread(QObject* object, QThread* thread); - private: TagReaderClient* tag_reader_client_; Database* database_; + AlbumCoverLoader* album_cover_loader_; Appearance* appearance_; CoverProviders* cover_providers_; TaskManager* task_manager_; Player* player_; PlaylistManager* playlist_manager_; + CurrentArtLoader* current_art_loader_; GlobalSearch* global_search_; InternetModel* internet_model_; diff --git a/src/core/mpris.cpp b/src/core/mpris.cpp index c30964489..3fcf57874 100644 --- a/src/core/mpris.cpp +++ b/src/core/mpris.cpp @@ -18,14 +18,13 @@ #include "mpris.h" #include "mpris1.h" #include "mpris2.h" -#include "covers/artloader.h" namespace mpris { -Mpris::Mpris(Application* app, ArtLoader* art_loader, QObject* parent) +Mpris::Mpris(Application* app, QObject* parent) : QObject(parent), - mpris1_(new mpris::Mpris1(app, art_loader, this)), - mpris2_(new mpris::Mpris2(app, art_loader, mpris1_, this)) + mpris1_(new mpris::Mpris1(app, this)), + mpris2_(new mpris::Mpris2(app, mpris1_, this)) { connect(mpris2_, SIGNAL(RaiseMainWindow()), SIGNAL(RaiseMainWindow())); mpris2_->InitLibIndicate(); diff --git a/src/core/mpris.h b/src/core/mpris.h index 2c779314a..f858168b1 100644 --- a/src/core/mpris.h +++ b/src/core/mpris.h @@ -21,7 +21,6 @@ #include class Application; -class ArtLoader; namespace mpris { @@ -32,7 +31,7 @@ class Mpris : public QObject { Q_OBJECT public: - Mpris(Application* app, ArtLoader* art_loader, QObject* parent = 0); + Mpris(Application* app, QObject* parent = 0); signals: void RaiseMainWindow(); diff --git a/src/core/mpris1.cpp b/src/core/mpris1.cpp index cc8997489..bf1141860 100644 --- a/src/core/mpris1.cpp +++ b/src/core/mpris1.cpp @@ -19,7 +19,7 @@ #include "mpris_common.h" #include "core/application.h" #include "core/logging.h" -#include "covers/artloader.h" +#include "covers/currentartloader.h" #include #include @@ -37,7 +37,7 @@ namespace mpris { const char* Mpris1::kDefaultDbusServiceName = "org.mpris.clementine"; -Mpris1::Mpris1(Application* app, ArtLoader* art_loader, QObject* parent, +Mpris1::Mpris1(Application* app, QObject* parent, const QString& dbus_service_name) : QObject(parent), dbus_service_name_(dbus_service_name), @@ -61,7 +61,7 @@ Mpris1::Mpris1(Application* app, ArtLoader* art_loader, QObject* parent, player_ = new Mpris1Player(app, this); tracklist_ = new Mpris1TrackList(app, this); - connect(art_loader, SIGNAL(ArtLoaded(const Song&, const QString&, const QImage&)), + connect(app->current_art_loader(), SIGNAL(ArtLoaded(const Song&, const QString&, const QImage&)), player_, SLOT(CurrentSongChanged(const Song&, const QString&, const QImage&))); } diff --git a/src/core/mpris1.h b/src/core/mpris1.h index 8fc0b714c..189b83a86 100644 --- a/src/core/mpris1.h +++ b/src/core/mpris1.h @@ -25,7 +25,6 @@ #include class Application; -class ArtLoader; class Playlist; struct DBusStatus { // From Amarok. @@ -77,7 +76,7 @@ class Mpris1 : public QObject { Q_OBJECT public: - Mpris1(Application* app, ArtLoader* art_loader, QObject* parent = 0, + Mpris1(Application* app, QObject* parent = 0, const QString& dbus_service_name = QString()); ~Mpris1(); diff --git a/src/core/mpris2.cpp b/src/core/mpris2.cpp index 0342375d0..674e67e14 100644 --- a/src/core/mpris2.cpp +++ b/src/core/mpris2.cpp @@ -26,7 +26,7 @@ #include "core/mpris2_tracklist.h" #include "core/player.h" #include "core/timeconstants.h" -#include "covers/artloader.h" +#include "covers/currentartloader.h" #include "engines/enginebase.h" #include "playlist/playlist.h" #include "playlist/playlistmanager.h" @@ -47,8 +47,7 @@ const char* Mpris2::kMprisObjectPath = "/org/mpris/MediaPlayer2"; const char* Mpris2::kServiceName = "org.mpris.MediaPlayer2.clementine"; const char* Mpris2::kFreedesktopPath = "org.freedesktop.DBus.Properties"; -Mpris2::Mpris2(Application* app, ArtLoader* art_loader, - Mpris1* mpris1, QObject* parent) +Mpris2::Mpris2(Application* app, Mpris1* mpris1, QObject* parent) : QObject(parent), app_(app), mpris1_(mpris1) @@ -64,7 +63,7 @@ Mpris2::Mpris2(Application* app, ArtLoader* art_loader, QDBusConnection::sessionBus().registerObject(kMprisObjectPath, this); - connect(art_loader, SIGNAL(ArtLoaded(Song,QString,QImage)), SLOT(ArtLoaded(Song,QString))); + connect(app_->current_art_loader(), SIGNAL(ArtLoaded(Song,QString,QImage)), SLOT(ArtLoaded(Song,QString))); connect(app_->player()->engine(), SIGNAL(StateChanged(Engine::State)), SLOT(EngineStateChanged(Engine::State))); connect(app_->player(), SIGNAL(VolumeChanged(int)), SLOT(VolumeChanged())); diff --git a/src/core/mpris2.h b/src/core/mpris2.h index eaedad386..7324d3e33 100644 --- a/src/core/mpris2.h +++ b/src/core/mpris2.h @@ -27,7 +27,6 @@ #include class Application; -class ArtLoader; class MainWindow; typedef QList TrackMetadata; @@ -72,8 +71,7 @@ class Mpris2 : public QObject { Q_PROPERTY( bool CanEditTracks READ CanEditTracks ) public: - Mpris2(Application* app, ArtLoader* art_loader, Mpris1* mpris1, - QObject* parent = 0); + Mpris2(Application* app, Mpris1* mpris1, QObject* parent = 0); void InitLibIndicate(); diff --git a/src/covers/albumcoverloader.cpp b/src/covers/albumcoverloader.cpp index d6fab628e..054cb09b4 100644 --- a/src/covers/albumcoverloader.cpp +++ b/src/covers/albumcoverloader.cpp @@ -37,9 +37,6 @@ AlbumCoverLoader::AlbumCoverLoader(QObject* parent) : QObject(parent), stop_requested_(false), - height_(120), - scale_(true), - padding_(true), next_id_(0), network_(new NetworkAccessManager(this)), connected_spotify_(false) @@ -50,16 +47,34 @@ QString AlbumCoverLoader::ImageCacheDir() { return Utilities::GetConfigPath(Utilities::Path_AlbumCovers); } -void AlbumCoverLoader::Clear() { +void AlbumCoverLoader::CancelTask(quint64 id) { QMutexLocker l(&mutex_); - tasks_.clear(); + for (QQueue::iterator it = tasks_.begin() ; it != tasks_.end() ; ++it) { + if (it->id == id) { + tasks_.erase(it); + break; + } + } } -quint64 AlbumCoverLoader::LoadImageAsync(const QString& art_automatic, +void AlbumCoverLoader::CancelTasks(const QSet& ids) { + QMutexLocker l(&mutex_); + for (QQueue::iterator it = tasks_.begin() ; it != tasks_.end() ; ) { + if (ids.contains(it->id)) { + it = tasks_.erase(it); + } else { + ++it; + } + } +} + +quint64 AlbumCoverLoader::LoadImageAsync(const AlbumCoverLoaderOptions& options, + const QString& art_automatic, const QString& art_manual, const QString& song_filename, const QImage& embedded_image) { Task task; + task.options = options; task.art_automatic = art_automatic; task.art_manual = art_manual; task.song_filename = song_filename; @@ -101,7 +116,7 @@ void AlbumCoverLoader::ProcessTask(Task *task) { } if (result.loaded_success) { - QImage scaled = ScaleAndPad(result.image); + QImage scaled = ScaleAndPad(task->options, result.image); emit ImageLoaded(task->id, scaled); emit ImageLoaded(task->id, scaled, result.image); return; @@ -117,8 +132,9 @@ void AlbumCoverLoader::NextState(Task* task) { ProcessTask(task); } else { // Give up - emit ImageLoaded(task->id, default_); - emit ImageLoaded(task->id, default_, default_); + emit ImageLoaded(task->id, task->options.default_output_image_); + emit ImageLoaded(task->id, task->options.default_output_image_, + task->options.default_output_image_); } } @@ -126,7 +142,7 @@ AlbumCoverLoader::TryLoadResult AlbumCoverLoader::TryLoadImage( const Task& task) { // An image embedded in the song itself takes priority if (!task.embedded_image.isNull()) - return TryLoadResult(false, true, ScaleAndPad(task.embedded_image)); + return TryLoadResult(false, true, ScaleAndPad(task.options, task.embedded_image)); QString filename; switch (task.state) { @@ -135,14 +151,14 @@ AlbumCoverLoader::TryLoadResult AlbumCoverLoader::TryLoadImage( } if (filename == Song::kManuallyUnsetCover) - return TryLoadResult(false, true, default_); + return TryLoadResult(false, true, task.options.default_output_image_); if (filename == Song::kEmbeddedCover && !task.song_filename.isEmpty()) { const QImage taglib_image = TagReaderClient::Instance()->LoadEmbeddedArtBlocking(task.song_filename); if (!taglib_image.isNull()) - return TryLoadResult(false, true, ScaleAndPad(taglib_image)); + return TryLoadResult(false, true, ScaleAndPad(task.options, taglib_image)); } if (filename.toLower().startsWith("http://")) { @@ -178,7 +194,8 @@ AlbumCoverLoader::TryLoadResult AlbumCoverLoader::TryLoadImage( } QImage image(filename); - return TryLoadResult(false, !image.isNull(), image.isNull() ? default_ : image); + return TryLoadResult(false, !image.isNull(), + image.isNull() ? task.options.default_output_image_: image); } void AlbumCoverLoader::SpotifyImageLoaded(const QString& id, const QImage& image) { @@ -186,7 +203,7 @@ void AlbumCoverLoader::SpotifyImageLoaded(const QString& id, const QImage& image return; Task task = remote_spotify_tasks_.take(id); - QImage scaled = ScaleAndPad(image); + QImage scaled = ScaleAndPad(task.options, image); emit ImageLoaded(task.id, scaled); emit ImageLoaded(task.id, scaled, image); } @@ -218,7 +235,7 @@ void AlbumCoverLoader::RemoteFetchFinished() { // Try to load the image QImage image; if (image.load(reply, 0)) { - QImage scaled = ScaleAndPad(image); + QImage scaled = ScaleAndPad(task.options, image); emit ImageLoaded(task.id, scaled); emit ImageLoaded(task.id, scaled, image); return; @@ -228,28 +245,31 @@ void AlbumCoverLoader::RemoteFetchFinished() { NextState(&task); } -QImage AlbumCoverLoader::ScaleAndPad(const QImage& image) const { +QImage AlbumCoverLoader::ScaleAndPad(const AlbumCoverLoaderOptions& options, + const QImage& image) { if (image.isNull()) return image; // Scale the image down QImage copy; - if (scale_) { - copy = image.scaled(QSize(height_, height_), + if (options.scale_output_image_) { + copy = image.scaled(QSize(options.desired_height_, options.desired_height_), Qt::KeepAspectRatio, Qt::SmoothTransformation); } else { copy = image; } - if (!padding_) + if (!options.pad_output_image_) return copy; // Pad the image to height_ x height_ - QImage padded_image(height_, height_, QImage::Format_ARGB32); + QImage padded_image(options.desired_height_, options.desired_height_, + QImage::Format_ARGB32); padded_image.fill(0); QPainter p(&padded_image); - p.drawImage((height_ - copy.width()) / 2, (height_ - copy.height()) / 2, + p.drawImage((options.desired_height_ - copy.width()) / 2, + (options.desired_height_ - copy.height()) / 2, copy); p.end(); @@ -274,11 +294,9 @@ QPixmap AlbumCoverLoader::TryLoadPixmap(const QString& automatic, return ret; } -void AlbumCoverLoader::SetDefaultOutputImage(const QImage &image) { - default_ = ScaleAndPad(image); -} - -quint64 AlbumCoverLoader::LoadImageAsync(const Song &song) { - return LoadImageAsync(song.art_automatic(), song.art_manual(), +quint64 AlbumCoverLoader::LoadImageAsync(const AlbumCoverLoaderOptions& options, + const Song &song) { + return LoadImageAsync(options, + song.art_automatic(), song.art_manual(), song.url().toLocalFile(), song.image()); } diff --git a/src/covers/albumcoverloader.h b/src/covers/albumcoverloader.h index 18b24d6a3..442716b33 100644 --- a/src/covers/albumcoverloader.h +++ b/src/covers/albumcoverloader.h @@ -18,6 +18,7 @@ #ifndef ALBUMCOVERLOADER_H #define ALBUMCOVERLOADER_H +#include "albumcoverloaderoptions.h" #include "core/backgroundthread.h" #include "core/song.h" @@ -40,23 +41,20 @@ class AlbumCoverLoader : public QObject { static QString ImageCacheDir(); - void SetDesiredHeight(int height) { height_ = height; } - void SetScaleOutputImage(bool scale) { scale_ = scale; } - void SetPadOutputImage(bool padding) { padding_ = padding; } - void SetDefaultOutputImage(const QImage& image); - - - quint64 LoadImageAsync(const Song& song); + quint64 LoadImageAsync(const AlbumCoverLoaderOptions& options, const Song& song); virtual quint64 LoadImageAsync( + const AlbumCoverLoaderOptions& options, const QString& art_automatic, const QString& art_manual, const QString& song_filename = QString(), const QImage& embedded_image = QImage()); - void Clear(); + void CancelTask(quint64 id); + void CancelTasks(const QSet& ids); static QPixmap TryLoadPixmap(const QString& automatic, const QString& manual, const QString& filename = QString()); + static QImage ScaleAndPad(const AlbumCoverLoaderOptions& options, const QImage& image); signals: void ImageLoaded(quint64 id, const QImage& image); @@ -75,6 +73,9 @@ class AlbumCoverLoader : public QObject { struct Task { Task() : redirects(0) {} + + AlbumCoverLoaderOptions options; + quint64 id; QString art_automatic; QString art_manual; @@ -96,15 +97,9 @@ class AlbumCoverLoader : public QObject { void ProcessTask(Task* task); void NextState(Task* task); TryLoadResult TryLoadImage(const Task& task); - QImage ScaleAndPad(const QImage& image) const; bool stop_requested_; - int height_; - bool scale_; - bool padding_; - QImage default_; - QMutex mutex_; QQueue tasks_; QMap remote_tasks_; diff --git a/src/covers/albumcoverloaderoptions.cpp b/src/covers/albumcoverloaderoptions.cpp new file mode 100644 index 000000000..e3a522f1d --- /dev/null +++ b/src/covers/albumcoverloaderoptions.cpp @@ -0,0 +1,19 @@ +/* This file is part of Clementine. + Copyright 2012, David Sansome + + Clementine is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Clementine is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Clementine. If not, see . +*/ + +#include "albumcoverloaderoptions.h" + diff --git a/src/covers/albumcoverloaderoptions.h b/src/covers/albumcoverloaderoptions.h new file mode 100644 index 000000000..33faccc15 --- /dev/null +++ b/src/covers/albumcoverloaderoptions.h @@ -0,0 +1,36 @@ +/* This file is part of Clementine. + Copyright 2012, David Sansome + + Clementine is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Clementine is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Clementine. If not, see . +*/ + +#ifndef ALBUMCOVERLOADEROPTIONS_H +#define ALBUMCOVERLOADEROPTIONS_H + +#include + +struct AlbumCoverLoaderOptions { + AlbumCoverLoaderOptions() + : desired_height_(120), + scale_output_image_(true), + pad_output_image_(true) + {} + + int desired_height_; + bool scale_output_image_; + bool pad_output_image_; + QImage default_output_image_; +}; + +#endif // ALBUMCOVERLOADEROPTIONS_H diff --git a/src/covers/artloader.cpp b/src/covers/currentartloader.cpp similarity index 70% rename from src/covers/artloader.cpp rename to src/covers/currentartloader.cpp index 3d72e62ab..d0dd47a9c 100644 --- a/src/covers/artloader.cpp +++ b/src/covers/currentartloader.cpp @@ -15,40 +15,41 @@ along with Clementine. If not, see . */ -#include "albumcoverloader.h" -#include "artloader.h" +#include "currentartloader.h" +#include "core/application.h" +#include "covers/albumcoverloader.h" +#include "playlist/playlistmanager.h" #include #include #include -ArtLoader::ArtLoader(QObject* parent) +CurrentArtLoader::CurrentArtLoader(Application* app, QObject* parent) : QObject(parent), + app_(app), temp_file_pattern_(QDir::tempPath() + "/clementine-art-XXXXXX.jpg"), - cover_loader_(new BackgroundThreadImplementation(this)), id_(0) { - cover_loader_->Start(); - connect(cover_loader_, SIGNAL(Initialised()), SLOT(Initialised())); -} + options_.scale_output_image_ = false; + options_.pad_output_image_ = false; + options_.default_output_image_ = QImage(":nocover.png"); -ArtLoader::~ArtLoader() { -} - -void ArtLoader::Initialised() { - cover_loader_->Worker()->SetScaleOutputImage(false); - cover_loader_->Worker()->SetPadOutputImage(false); - cover_loader_->Worker()->SetDefaultOutputImage(QImage(":nocover.png")); - connect(cover_loader_->Worker().get(), SIGNAL(ImageLoaded(quint64,QImage)), + connect(app_->album_cover_loader(), SIGNAL(ImageLoaded(quint64,QImage)), SLOT(TempArtLoaded(quint64,QImage))); + + connect(app_->playlist_manager(), SIGNAL(CurrentSongChanged(Song)), + SLOT(LoadArt(Song))); } -void ArtLoader::LoadArt(const Song& song) { +CurrentArtLoader::~CurrentArtLoader() { +} + +void CurrentArtLoader::LoadArt(const Song& song) { last_song_ = song; - id_ = cover_loader_->Worker()->LoadImageAsync(song); + id_ = app_->album_cover_loader()->LoadImageAsync(options_, last_song_); } -void ArtLoader::TempArtLoaded(quint64 id, const QImage& image) { +void CurrentArtLoader::TempArtLoaded(quint64 id, const QImage& image) { if (id != id_) return; id_ = 0; diff --git a/src/covers/artloader.h b/src/covers/currentartloader.h similarity index 74% rename from src/covers/artloader.h rename to src/covers/currentartloader.h index fb07319c5..05e1a7db7 100644 --- a/src/covers/artloader.h +++ b/src/covers/currentartloader.h @@ -15,27 +15,30 @@ along with Clementine. If not, see . */ -#ifndef ARTLOADER_H -#define ARTLOADER_H +#ifndef CURRENTARTLOADER_H +#define CURRENTARTLOADER_H -#include "core/backgroundthread.h" #include "core/song.h" +#include "covers/albumcoverloaderoptions.h" #include #include -class AlbumCoverLoader; +class Application; class QImage; class QTemporaryFile; -class ArtLoader : public QObject { +class CurrentArtLoader : public QObject { Q_OBJECT public: - ArtLoader(QObject* parent = 0); - ~ArtLoader(); + CurrentArtLoader(Application* app, QObject* parent = 0); + ~CurrentArtLoader(); + + const AlbumCoverLoaderOptions& options() const { return options_; } + const Song& last_song() const { return last_song_; } public slots: void LoadArt(const Song& song); @@ -45,18 +48,19 @@ signals: void ThumbnailLoaded(const Song& song, const QString& uri, const QImage& image); private slots: - void Initialised(); void TempArtLoaded(quint64 id, const QImage& image); private: + Application* app_; + AlbumCoverLoaderOptions options_; + QString temp_file_pattern_; boost::scoped_ptr temp_art_; boost::scoped_ptr temp_art_thumbnail_; - BackgroundThread* cover_loader_; quint64 id_; Song last_song_; }; -#endif // ARTLOADER_H +#endif // CURRENTARTLOADER_H diff --git a/src/covers/kittenloader.cpp b/src/covers/kittenloader.cpp index 97964e22d..bc7b3780c 100644 --- a/src/covers/kittenloader.cpp +++ b/src/covers/kittenloader.cpp @@ -21,14 +21,11 @@ KittenLoader::KittenLoader(QObject* parent) : AlbumCoverLoader(parent) { } -quint64 KittenLoader::LoadImageAsync( - const QString& art_automatic, - const QString& art_manual, - const QString& song_filename, - const QImage& embedded_image) { +quint64 KittenLoader::LoadKitten(const AlbumCoverLoaderOptions& options) { if (!kitten_urls_.isEmpty()) { QUrl url = kitten_urls_.dequeue(); return AlbumCoverLoader::LoadImageAsync( + options, QString::null, url.toString(), QString::null, @@ -36,6 +33,7 @@ quint64 KittenLoader::LoadImageAsync( } Task task; + task.options = options; { QMutexLocker l(&mutex_); task.id = next_id_++; diff --git a/src/covers/kittenloader.h b/src/covers/kittenloader.h index 9d82cfc7c..c962e4dc4 100644 --- a/src/covers/kittenloader.h +++ b/src/covers/kittenloader.h @@ -11,11 +11,7 @@ class KittenLoader : public AlbumCoverLoader { public: KittenLoader(QObject* parent = 0); - virtual quint64 LoadImageAsync( - const QString& art_automatic, - const QString& art_manual, - const QString& song_filename, - const QImage& embedded_image); + virtual quint64 LoadKitten(const AlbumCoverLoaderOptions& options); private slots: void KittensRetrieved(); diff --git a/src/devices/gpoddevice.cpp b/src/devices/gpoddevice.cpp index ed6578345..cc3aa6598 100644 --- a/src/devices/gpoddevice.cpp +++ b/src/devices/gpoddevice.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include diff --git a/src/devices/mtpdevice.cpp b/src/devices/mtpdevice.cpp index ea81062a9..d55259aa6 100644 --- a/src/devices/mtpdevice.cpp +++ b/src/devices/mtpdevice.cpp @@ -27,6 +27,7 @@ #include #include +#include bool MtpDevice::sInitialisedLibMTP = false; diff --git a/src/globalsearch/digitallyimportedsearchprovider.cpp b/src/globalsearch/digitallyimportedsearchprovider.cpp index a799d924a..8ecb92828 100644 --- a/src/globalsearch/digitallyimportedsearchprovider.cpp +++ b/src/globalsearch/digitallyimportedsearchprovider.cpp @@ -20,8 +20,8 @@ #include "internet/digitallyimportedservicebase.h" DigitallyImportedSearchProvider::DigitallyImportedSearchProvider( - DigitallyImportedServiceBase* service, QObject* parent) - : SimpleSearchProvider(parent), + DigitallyImportedServiceBase* service, Application* app, QObject* parent) + : SimpleSearchProvider(app, parent), service_(service) { Init(service_->name(), service->api_service_name(), service_->icon(), diff --git a/src/globalsearch/digitallyimportedsearchprovider.h b/src/globalsearch/digitallyimportedsearchprovider.h index 1501ed991..a2aeebd6d 100644 --- a/src/globalsearch/digitallyimportedsearchprovider.h +++ b/src/globalsearch/digitallyimportedsearchprovider.h @@ -25,7 +25,7 @@ class DigitallyImportedServiceBase; class DigitallyImportedSearchProvider : public SimpleSearchProvider { public: DigitallyImportedSearchProvider(DigitallyImportedServiceBase* service, - QObject* parent); + Application* app, QObject* parent); void ShowConfig(); diff --git a/src/globalsearch/globalsearch.cpp b/src/globalsearch/globalsearch.cpp index 4b4ad9b4c..14476a7a4 100644 --- a/src/globalsearch/globalsearch.cpp +++ b/src/globalsearch/globalsearch.cpp @@ -18,6 +18,7 @@ #include "librarysearchprovider.h" #include "globalsearch.h" #include "urlsearchprovider.h" +#include "core/application.h" #include "core/logging.h" #include "covers/albumcoverloader.h" @@ -34,15 +35,13 @@ GlobalSearch::GlobalSearch(Application* app, QObject* parent) : QObject(parent), app_(app), next_id_(1), - cover_loader_(new BackgroundThreadImplementation(this)), - url_provider_(new UrlSearchProvider(this)) + url_provider_(new UrlSearchProvider(app, this)) { - cover_loader_->Start(true); - cover_loader_->Worker()->SetDesiredHeight(SearchProvider::kArtHeight); - cover_loader_->Worker()->SetPadOutputImage(true); - cover_loader_->Worker()->SetScaleOutputImage(true); + cover_loader_options_.desired_height_ = SearchProvider::kArtHeight; + cover_loader_options_.pad_output_image_ = true; + cover_loader_options_.scale_output_image_ = true; - connect(cover_loader_->Worker().get(), + connect(app_->album_cover_loader(), SIGNAL(ImageLoaded(quint64,QImage)), SLOT(AlbumArtLoaded(quint64,QImage))); @@ -212,7 +211,8 @@ int GlobalSearch::LoadArtAsync(const SearchProvider::Result& result) { } if (result.provider_->art_is_in_song_metadata()) { - quint64 loader_id = cover_loader_->Worker()->LoadImageAsync(result.metadata_); + quint64 loader_id = app_->album_cover_loader()->LoadImageAsync( + cover_loader_options_, result.metadata_); cover_loader_tasks_[loader_id] = id; } else if (providers_.contains(result.provider_) && result.provider_->wants_serialised_art()) { diff --git a/src/globalsearch/globalsearch.h b/src/globalsearch/globalsearch.h index 33dab875e..a521fbf3d 100644 --- a/src/globalsearch/globalsearch.h +++ b/src/globalsearch/globalsearch.h @@ -22,8 +22,7 @@ #include #include "searchprovider.h" -#include "core/backgroundthread.h" - +#include "covers/albumcoverloaderoptions.h" class AlbumCoverLoader; class Application; @@ -126,7 +125,7 @@ private: QMap pending_art_searches_; // Used for providers with ArtIsInSongMetadata set. - BackgroundThread* cover_loader_; + AlbumCoverLoaderOptions cover_loader_options_; QMap cover_loader_tasks_; // Special search provider that's used for queries that look like URLs diff --git a/src/globalsearch/groovesharksearchprovider.cpp b/src/globalsearch/groovesharksearchprovider.cpp index 767bd3837..94155bc03 100644 --- a/src/globalsearch/groovesharksearchprovider.cpp +++ b/src/globalsearch/groovesharksearchprovider.cpp @@ -19,13 +19,16 @@ #include +#include "core/application.h" #include "core/logging.h" #include "covers/albumcoverloader.h" #include "internet/groovesharkservice.h" #include "internet/internetsongmimedata.h" -GroovesharkSearchProvider::GroovesharkSearchProvider(QObject* parent) - : service_(NULL) { +GroovesharkSearchProvider::GroovesharkSearchProvider(Application* app, QObject* parent) + : SearchProvider(app, parent), + service_(NULL) +{ } void GroovesharkSearchProvider::Init(GroovesharkService* service) { @@ -41,13 +44,11 @@ void GroovesharkSearchProvider::Init(GroovesharkService* service) { connect(service_, SIGNAL(AlbumSongsLoaded(int, SongList)), SLOT(AlbumSongsLoaded(int, SongList))); - cover_loader_ = new BackgroundThreadImplementation(this); - cover_loader_->Start(true); - cover_loader_->Worker()->SetDesiredHeight(kArtHeight); - cover_loader_->Worker()->SetPadOutputImage(true); - cover_loader_->Worker()->SetScaleOutputImage(true); + cover_loader_options_.desired_height_ = kArtHeight; + cover_loader_options_.pad_output_image_ = true; + cover_loader_options_.scale_output_image_ = true; - connect(cover_loader_->Worker().get(), + connect(app_->album_cover_loader(), SIGNAL(ImageLoaded(quint64, QImage)), SLOT(AlbumArtLoaded(quint64, QImage))); } @@ -111,7 +112,8 @@ void GroovesharkSearchProvider::MaybeSearchFinished(int id) { void GroovesharkSearchProvider::LoadArtAsync(int id, const Result& result) { - quint64 loader_id = cover_loader_->Worker()->LoadImageAsync(result.metadata_); + quint64 loader_id = app_->album_cover_loader()->LoadImageAsync( + cover_loader_options_, result.metadata_); cover_loader_tasks_[loader_id] = id; } diff --git a/src/globalsearch/groovesharksearchprovider.h b/src/globalsearch/groovesharksearchprovider.h index 1a21f4ca2..854e90b74 100644 --- a/src/globalsearch/groovesharksearchprovider.h +++ b/src/globalsearch/groovesharksearchprovider.h @@ -20,6 +20,7 @@ #include "searchprovider.h" #include "core/backgroundthread.h" +#include "covers/albumcoverloaderoptions.h" class AlbumCoverLoader; class GroovesharkService; @@ -28,7 +29,7 @@ class GroovesharkSearchProvider : public SearchProvider { Q_OBJECT public: - explicit GroovesharkSearchProvider(QObject* parent = 0); + explicit GroovesharkSearchProvider(Application* app, QObject* parent = 0); void Init(GroovesharkService* service); // SearchProvider @@ -51,7 +52,7 @@ class GroovesharkSearchProvider : public SearchProvider { GroovesharkService* service_; QMap pending_searches_; - BackgroundThread* cover_loader_; + AlbumCoverLoaderOptions cover_loader_options_; QMap cover_loader_tasks_; }; diff --git a/src/globalsearch/icecastsearchprovider.cpp b/src/globalsearch/icecastsearchprovider.cpp index 5cbb730a5..e55527a4d 100644 --- a/src/globalsearch/icecastsearchprovider.cpp +++ b/src/globalsearch/icecastsearchprovider.cpp @@ -18,8 +18,9 @@ #include "icecastsearchprovider.h" #include "internet/icecastbackend.h" -IcecastSearchProvider::IcecastSearchProvider(IcecastBackend* backend, QObject* parent) - : BlockingSearchProvider(parent), +IcecastSearchProvider::IcecastSearchProvider(IcecastBackend* backend, + Application* app, QObject* parent) + : BlockingSearchProvider(app, parent), backend_(backend) { Init("Icecast", "icecast", QIcon(":last.fm/icon_radio.png"), DisabledByDefault); diff --git a/src/globalsearch/icecastsearchprovider.h b/src/globalsearch/icecastsearchprovider.h index c8bce4268..c9b3a775e 100644 --- a/src/globalsearch/icecastsearchprovider.h +++ b/src/globalsearch/icecastsearchprovider.h @@ -25,7 +25,7 @@ class IcecastBackend; class IcecastSearchProvider : public BlockingSearchProvider { public: - IcecastSearchProvider(IcecastBackend* backend, QObject* parent); + IcecastSearchProvider(IcecastBackend* backend, Application* app, QObject* parent); ResultList Search(int id, const QString& query); diff --git a/src/globalsearch/lastfmsearchprovider.cpp b/src/globalsearch/lastfmsearchprovider.cpp index 2d346d586..b6335ae56 100644 --- a/src/globalsearch/lastfmsearchprovider.cpp +++ b/src/globalsearch/lastfmsearchprovider.cpp @@ -20,8 +20,9 @@ #include "internet/lastfmservice.h" -LastFMSearchProvider::LastFMSearchProvider(LastFMService* service, QObject* parent) - : SimpleSearchProvider(parent), +LastFMSearchProvider::LastFMSearchProvider(LastFMService* service, + Application* app, QObject* parent) + : SimpleSearchProvider(app, parent), service_(service) { Init("Last.fm", "lastfm", QIcon(":last.fm/as.png"), CanShowConfig | CanGiveSuggestions); diff --git a/src/globalsearch/lastfmsearchprovider.h b/src/globalsearch/lastfmsearchprovider.h index d26c0fc0a..849bb1a0f 100644 --- a/src/globalsearch/lastfmsearchprovider.h +++ b/src/globalsearch/lastfmsearchprovider.h @@ -24,7 +24,7 @@ class LastFMService; class LastFMSearchProvider : public SimpleSearchProvider { public: - LastFMSearchProvider(LastFMService* service, QObject* parent); + LastFMSearchProvider(LastFMService* service, Application* app, QObject* parent); void LoadArtAsync(int id, const Result& result); diff --git a/src/globalsearch/librarysearchprovider.cpp b/src/globalsearch/librarysearchprovider.cpp index 4d82b719f..06db6cb67 100644 --- a/src/globalsearch/librarysearchprovider.cpp +++ b/src/globalsearch/librarysearchprovider.cpp @@ -29,8 +29,9 @@ LibrarySearchProvider::LibrarySearchProvider(LibraryBackendInterface* backend, const QString& id, const QIcon& icon, bool enabled_by_default, + Application* app, QObject* parent) - : BlockingSearchProvider(parent), + : BlockingSearchProvider(app, parent), backend_(backend) { Hints hints = WantsSerialisedArtQueries | ArtIsInSongMetadata | diff --git a/src/globalsearch/librarysearchprovider.h b/src/globalsearch/librarysearchprovider.h index 65bb1d34e..83848a055 100644 --- a/src/globalsearch/librarysearchprovider.h +++ b/src/globalsearch/librarysearchprovider.h @@ -27,7 +27,8 @@ class LibrarySearchProvider : public BlockingSearchProvider { public: LibrarySearchProvider(LibraryBackendInterface* backend, const QString& name, const QString& id, const QIcon& icon, - bool enabled_by_default, QObject* parent = 0); + bool enabled_by_default, + Application* app, QObject* parent = 0); ResultList Search(int id, const QString& query); void LoadTracksAsync(int id, const Result& result); diff --git a/src/globalsearch/savedradiosearchprovider.cpp b/src/globalsearch/savedradiosearchprovider.cpp index 016eb9b78..43a012914 100644 --- a/src/globalsearch/savedradiosearchprovider.cpp +++ b/src/globalsearch/savedradiosearchprovider.cpp @@ -20,8 +20,9 @@ #include "internet/savedradio.h" #include "ui/iconloader.h" -SavedRadioSearchProvider::SavedRadioSearchProvider(SavedRadio* service, QObject* parent) - : SimpleSearchProvider(parent), +SavedRadioSearchProvider::SavedRadioSearchProvider(SavedRadio* service, + Application* app, QObject* parent) + : SimpleSearchProvider(app, parent), service_(service) { Init(tr("Your radio streams"), "savedradio", IconLoader::Load("document-open-remote")); diff --git a/src/globalsearch/savedradiosearchprovider.h b/src/globalsearch/savedradiosearchprovider.h index 365b4d45e..3367df199 100644 --- a/src/globalsearch/savedradiosearchprovider.h +++ b/src/globalsearch/savedradiosearchprovider.h @@ -24,7 +24,7 @@ class SavedRadio; class SavedRadioSearchProvider : public SimpleSearchProvider { public: - SavedRadioSearchProvider(SavedRadio* service, QObject* parent); + SavedRadioSearchProvider(SavedRadio* service, Application* app, QObject* parent); void LoadTracksAsync(int id, const Result& result); diff --git a/src/globalsearch/searchprovider.cpp b/src/globalsearch/searchprovider.cpp index 9f60738ca..f06ea2187 100644 --- a/src/globalsearch/searchprovider.cpp +++ b/src/globalsearch/searchprovider.cpp @@ -25,8 +25,9 @@ const int SearchProvider::kArtHeight = 32; -SearchProvider::SearchProvider(QObject* parent) +SearchProvider::SearchProvider(Application* app, QObject* parent) : QObject(parent), + app_(app), hints_(0) { } @@ -72,8 +73,8 @@ globalsearch::MatchQuality SearchProvider::MatchQuality( return ret; } -BlockingSearchProvider::BlockingSearchProvider(QObject* parent) - : SearchProvider(parent) { +BlockingSearchProvider::BlockingSearchProvider(Application* app, QObject* parent) + : SearchProvider(app, parent) { } void BlockingSearchProvider::SearchAsync(int id, const QString& query) { diff --git a/src/globalsearch/searchprovider.h b/src/globalsearch/searchprovider.h index 39d5060a7..1e43c035a 100644 --- a/src/globalsearch/searchprovider.h +++ b/src/globalsearch/searchprovider.h @@ -25,6 +25,7 @@ #include "core/song.h" #include "globalsearch/common.h" +class Application; class MimeData; @@ -32,7 +33,7 @@ class SearchProvider : public QObject { Q_OBJECT public: - SearchProvider(QObject* parent = 0); + SearchProvider(Application* app, QObject* parent = 0); static const int kArtHeight; @@ -177,6 +178,8 @@ protected: } }; +protected: + Application* app_; private: QString name_; @@ -194,7 +197,7 @@ class BlockingSearchProvider : public SearchProvider { Q_OBJECT public: - BlockingSearchProvider(QObject* parent = 0); + BlockingSearchProvider(Application* app, QObject* parent = 0); void SearchAsync(int id, const QString& query); virtual ResultList Search(int id, const QString& query) = 0; diff --git a/src/globalsearch/simplesearchprovider.cpp b/src/globalsearch/simplesearchprovider.cpp index b581ee4d5..6e1bb39ac 100644 --- a/src/globalsearch/simplesearchprovider.cpp +++ b/src/globalsearch/simplesearchprovider.cpp @@ -36,8 +36,8 @@ SimpleSearchProvider::Item::Item(const Song& song, const QString& keyword) } -SimpleSearchProvider::SimpleSearchProvider(QObject* parent) - : BlockingSearchProvider(parent), +SimpleSearchProvider::SimpleSearchProvider(Application* app, QObject* parent) + : BlockingSearchProvider(app, parent), result_limit_(kDefaultResultLimit), items_dirty_(true), has_searched_before_(false) diff --git a/src/globalsearch/simplesearchprovider.h b/src/globalsearch/simplesearchprovider.h index 18133d4a7..00a1d88a3 100644 --- a/src/globalsearch/simplesearchprovider.h +++ b/src/globalsearch/simplesearchprovider.h @@ -24,7 +24,7 @@ class SimpleSearchProvider : public BlockingSearchProvider { Q_OBJECT public: - SimpleSearchProvider(QObject* parent); + SimpleSearchProvider(Application* app, QObject* parent); static const int kDefaultResultLimit; diff --git a/src/globalsearch/somafmsearchprovider.cpp b/src/globalsearch/somafmsearchprovider.cpp index 56019b580..9d697b680 100644 --- a/src/globalsearch/somafmsearchprovider.cpp +++ b/src/globalsearch/somafmsearchprovider.cpp @@ -18,8 +18,8 @@ #include "somafmsearchprovider.h" #include "internet/somafmservice.h" -SomaFMSearchProvider::SomaFMSearchProvider(SomaFMService* service, QObject* parent) - : SimpleSearchProvider(parent), +SomaFMSearchProvider::SomaFMSearchProvider(SomaFMService* service, Application* app, QObject* parent) + : SimpleSearchProvider(app, parent), service_(service) { Init("SomaFM", "somafm", QIcon(":/providers/somafm.png"), CanGiveSuggestions); diff --git a/src/globalsearch/somafmsearchprovider.h b/src/globalsearch/somafmsearchprovider.h index 5488c0400..836a046d2 100644 --- a/src/globalsearch/somafmsearchprovider.h +++ b/src/globalsearch/somafmsearchprovider.h @@ -24,7 +24,7 @@ class SomaFMService; class SomaFMSearchProvider : public SimpleSearchProvider { public: - SomaFMSearchProvider(SomaFMService* service, QObject* parent); + SomaFMSearchProvider(SomaFMService* service, Application* app, QObject* parent); void LoadArtAsync(int id, const Result& result); diff --git a/src/globalsearch/spotifysearchprovider.cpp b/src/globalsearch/spotifysearchprovider.cpp index 650311e79..c4402dc0c 100644 --- a/src/globalsearch/spotifysearchprovider.cpp +++ b/src/globalsearch/spotifysearchprovider.cpp @@ -22,8 +22,8 @@ #include "internet/spotifyservice.h" #include "playlist/songmimedata.h" -SpotifySearchProvider::SpotifySearchProvider(QObject* parent) - : SearchProvider(parent), +SpotifySearchProvider::SpotifySearchProvider(Application* app, QObject* parent) + : SearchProvider(app, parent), server_(NULL), service_(NULL) { diff --git a/src/globalsearch/spotifysearchprovider.h b/src/globalsearch/spotifysearchprovider.h index 7c4212f19..2b452928c 100644 --- a/src/globalsearch/spotifysearchprovider.h +++ b/src/globalsearch/spotifysearchprovider.h @@ -29,7 +29,7 @@ class SpotifySearchProvider : public SearchProvider { Q_OBJECT public: - SpotifySearchProvider(QObject* parent = 0); + SpotifySearchProvider(Application* app, QObject* parent = 0); void SearchAsync(int id, const QString& query); void LoadArtAsync(int id, const Result& result); diff --git a/src/globalsearch/urlsearchprovider.cpp b/src/globalsearch/urlsearchprovider.cpp index 49c174b42..c22979a23 100644 --- a/src/globalsearch/urlsearchprovider.cpp +++ b/src/globalsearch/urlsearchprovider.cpp @@ -24,8 +24,8 @@ const char* UrlSearchProvider::kUrlRegex = "^[a-zA-Z][a-zA-Z0-9+-.]*://"; -UrlSearchProvider::UrlSearchProvider(QObject* parent) - : SearchProvider(parent), +UrlSearchProvider::UrlSearchProvider(Application* app, QObject* parent) + : SearchProvider(app, parent), url_regex_(kUrlRegex) { QIcon icon = IconLoader::Load("applications-internet"); diff --git a/src/globalsearch/urlsearchprovider.h b/src/globalsearch/urlsearchprovider.h index 6283b7ff8..43eb7baba 100644 --- a/src/globalsearch/urlsearchprovider.h +++ b/src/globalsearch/urlsearchprovider.h @@ -24,7 +24,7 @@ class UrlSearchProvider : public SearchProvider { public: - UrlSearchProvider(QObject* parent); + UrlSearchProvider(Application* app, QObject* parent); bool LooksLikeUrl(const QString& query) const; diff --git a/src/internet/digitallyimportedservicebase.cpp b/src/internet/digitallyimportedservicebase.cpp index 55378d182..d6550733d 100644 --- a/src/internet/digitallyimportedservicebase.cpp +++ b/src/internet/digitallyimportedservicebase.cpp @@ -63,7 +63,8 @@ DigitallyImportedServiceBase::DigitallyImportedServiceBase( ReloadSettings(); model->app()->player()->RegisterUrlHandler(url_handler_); - model->app()->global_search()->AddProvider(new DigitallyImportedSearchProvider(this, this)); + model->app()->global_search()->AddProvider( + new DigitallyImportedSearchProvider(this, app_, this)); basic_playlists_ << "http://%1/public3/%2.pls" diff --git a/src/internet/digitallyimportedsettingspage.h b/src/internet/digitallyimportedsettingspage.h index bb58729e0..eaf31ef45 100644 --- a/src/internet/digitallyimportedsettingspage.h +++ b/src/internet/digitallyimportedsettingspage.h @@ -23,6 +23,8 @@ class DigitallyImportedClient; class Ui_DigitallyImportedSettingsPage; +class QNetworkReply; + class DigitallyImportedSettingsPage : public SettingsPage { Q_OBJECT diff --git a/src/internet/groovesharkservice.cpp b/src/internet/groovesharkservice.cpp index 492a310ed..0310ac393 100644 --- a/src/internet/groovesharkservice.cpp +++ b/src/internet/groovesharkservice.cpp @@ -121,7 +121,7 @@ GroovesharkService::GroovesharkService(Application* app, InternetModel *parent) session_id_ = s.value("sessionid").toString(); username_ = s.value("username").toString(); - GroovesharkSearchProvider* search_provider = new GroovesharkSearchProvider(this); + GroovesharkSearchProvider* search_provider = new GroovesharkSearchProvider(app_, this); search_provider->Init(this); app_->global_search()->AddProvider(search_provider); diff --git a/src/internet/groovesharkservice.h b/src/internet/groovesharkservice.h index 10f69f900..ef7a17425 100644 --- a/src/internet/groovesharkservice.h +++ b/src/internet/groovesharkservice.h @@ -26,9 +26,11 @@ class GroovesharkUrlHandler; class NetworkAccessManager; class Playlist; + class QMenu; -class QSortFilterProxyModel; +class QNetworkReply; class QNetworkRequest; +class QSortFilterProxyModel; class GroovesharkService : public InternetService { Q_OBJECT diff --git a/src/internet/icecastservice.cpp b/src/internet/icecastservice.cpp index b548143a2..9d696bb57 100644 --- a/src/internet/icecastservice.cpp +++ b/src/internet/icecastservice.cpp @@ -63,7 +63,7 @@ IcecastService::IcecastService(Application* app, InternetModel* parent) model_ = new IcecastModel(backend_, this); filter_->SetIcecastModel(model_); - app_->global_search()->AddProvider(new IcecastSearchProvider(backend_, this)); + app_->global_search()->AddProvider(new IcecastSearchProvider(backend_, app_, this)); } IcecastService::~IcecastService() { diff --git a/src/internet/jamendoservice.cpp b/src/internet/jamendoservice.cpp index 3fd203a3a..bf1efeca7 100644 --- a/src/internet/jamendoservice.cpp +++ b/src/internet/jamendoservice.cpp @@ -125,8 +125,7 @@ JamendoService::JamendoService(Application* app, InternetModel* parent) tr("Jamendo"), "jamendo", QIcon(":/providers/jamendo.png"), - false, - this)); + false, app_, this)); } JamendoService::~JamendoService() { diff --git a/src/internet/lastfmservice.cpp b/src/internet/lastfmservice.cpp index 5110ba576..33c815c77 100644 --- a/src/internet/lastfmservice.cpp +++ b/src/internet/lastfmservice.cpp @@ -134,7 +134,7 @@ LastFMService::LastFMService(Application* app, InternetModel* parent) app_->player()->RegisterUrlHandler(url_handler_); app_->cover_providers()->AddProvider(new LastFmCoverProvider(this)); - app_->global_search()->AddProvider(new LastFMSearchProvider(this, this)); + app_->global_search()->AddProvider(new LastFMSearchProvider(this, app_, this)); } LastFMService::~LastFMService() { diff --git a/src/internet/magnatuneservice.cpp b/src/internet/magnatuneservice.cpp index a195010fa..a6a0f2719 100644 --- a/src/internet/magnatuneservice.cpp +++ b/src/internet/magnatuneservice.cpp @@ -102,8 +102,7 @@ MagnatuneService::MagnatuneService(Application* app, InternetModel* parent) tr("Magnatune"), "magnatune", QIcon(":/providers/magnatune.png"), - true, - this)); + true, app_, this)); } MagnatuneService::~MagnatuneService() { diff --git a/src/internet/savedradio.cpp b/src/internet/savedradio.cpp index 3946037c0..9489d60e3 100644 --- a/src/internet/savedradio.cpp +++ b/src/internet/savedradio.cpp @@ -37,7 +37,7 @@ SavedRadio::SavedRadio(Application* app, InternetModel* parent) { LoadStreams(); - app_->global_search()->AddProvider(new SavedRadioSearchProvider(this, this)); + app_->global_search()->AddProvider(new SavedRadioSearchProvider(this, app_, this)); } SavedRadio::~SavedRadio() { diff --git a/src/internet/somafmservice.cpp b/src/internet/somafmservice.cpp index 4c40b12bf..58b6b438d 100644 --- a/src/internet/somafmservice.cpp +++ b/src/internet/somafmservice.cpp @@ -55,7 +55,7 @@ SomaFMService::SomaFMService(Application* app, InternetModel* parent) ReloadSettings(); app_->player()->RegisterUrlHandler(url_handler_); - app_->global_search()->AddProvider(new SomaFMSearchProvider(this, this)); + app_->global_search()->AddProvider(new SomaFMSearchProvider(this, app_, this)); } SomaFMService::~SomaFMService() { diff --git a/src/internet/somafmservice.h b/src/internet/somafmservice.h index 0ff2c83a8..8583ce264 100644 --- a/src/internet/somafmservice.h +++ b/src/internet/somafmservice.h @@ -26,6 +26,7 @@ class SomaFMUrlHandler; class QNetworkAccessManager; +class QNetworkReply; class QMenu; class SomaFMService : public InternetService { diff --git a/src/internet/spotifyservice.cpp b/src/internet/spotifyservice.cpp index 46ae58b7e..c4bb1b566 100644 --- a/src/internet/spotifyservice.cpp +++ b/src/internet/spotifyservice.cpp @@ -74,7 +74,7 @@ SpotifyService::SpotifyService(Application* app, InternetModel* parent) app_->playlist_manager()->RegisterSpecialPlaylistType( new SpotifySearchPlaylistType(this)); - app_->global_search()->AddProvider(new SpotifySearchProvider(this)); + app_->global_search()->AddProvider(new SpotifySearchProvider(app_, this)); search_delay_->setInterval(kSearchDelayMsec); search_delay_->setSingleShot(true); diff --git a/src/library/librarymodel.cpp b/src/library/librarymodel.cpp index 3dc3a43f1..c075e2167 100644 --- a/src/library/librarymodel.cpp +++ b/src/library/librarymodel.cpp @@ -75,8 +75,7 @@ LibraryModel::LibraryModel(LibraryBackend* backend, Application* app, playlist_icon_(":/icons/22x22/x-clementine-albums.png"), init_task_id_(-1), use_pretty_covers_(false), - show_dividers_(true), - cover_loader_(new BackgroundThreadImplementation(this)) + show_dividers_(true) { root_->lazy_loaded = true; @@ -84,12 +83,11 @@ LibraryModel::LibraryModel(LibraryBackend* backend, Application* app, group_by_[1] = GroupBy_Album; group_by_[2] = GroupBy_None; - cover_loader_->Start(true); - cover_loader_->Worker()->SetDesiredHeight(kPrettyCoverSize); - cover_loader_->Worker()->SetPadOutputImage(true); - cover_loader_->Worker()->SetScaleOutputImage(true); + cover_loader_options_.desired_height_ = kPrettyCoverSize; + cover_loader_options_.pad_output_image_ = true; + cover_loader_options_.scale_output_image_ = true; - connect(cover_loader_->Worker().get(), + connect(app_->album_cover_loader(), SIGNAL(ImageLoaded(quint64,QImage)), SLOT(AlbumArtLoaded(quint64,QImage))); @@ -403,7 +401,8 @@ QVariant LibraryModel::AlbumIcon(const QModelIndex& index) { // No art is cached - load art for the first Song in the album. SongList songs = GetChildSongs(index); if (!songs.isEmpty()) { - const quint64 id = cover_loader_->Worker()->LoadImageAsync(songs.first()); + const quint64 id = app_->album_cover_loader()->LoadImageAsync( + cover_loader_options_, songs.first()); pending_art_[id] = item; } diff --git a/src/library/librarymodel.h b/src/library/librarymodel.h index c772e24fd..cedd3228b 100644 --- a/src/library/librarymodel.h +++ b/src/library/librarymodel.h @@ -25,9 +25,9 @@ #include "libraryquery.h" #include "librarywatcher.h" #include "sqlrow.h" -#include "core/backgroundthread.h" #include "core/simpletreemodel.h" #include "core/song.h" +#include "covers/albumcoverloaderoptions.h" #include "engines/engine_fwd.h" #include "playlist/playlistmanager.h" #include "smartplaylists/generator_fwd.h" @@ -269,7 +269,7 @@ class LibraryModel : public SimpleTreeModel { bool use_pretty_covers_; bool show_dividers_; - BackgroundThread* cover_loader_; + AlbumCoverLoaderOptions cover_loader_options_; QMap pending_art_; }; diff --git a/src/library/libraryview.cpp b/src/library/libraryview.cpp index 02dd611b7..40ea0c9ad 100644 --- a/src/library/libraryview.cpp +++ b/src/library/libraryview.cpp @@ -380,7 +380,7 @@ void LibraryView::ShowInVarious(bool on) { // if there are other Artists in this album and prompt the user if they'd like them moved, too if(on && albums.keys().count() == 1) { const QString album = albums.keys().first(); - QList all_of_album = library_->backend()->GetSongsByAlbum(album); + QList all_of_album = app_->library_backend()->GetSongsByAlbum(album); QSet other_artists; foreach (const Song& s, all_of_album) { if(!albums.contains(album, s.artist()) && !other_artists.contains(s.artist())) { diff --git a/src/main.cpp b/src/main.cpp index e3b35bbd7..035f80a7c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -39,7 +39,6 @@ #include "covers/albumcoverfetcher.h" #include "covers/amazoncoverprovider.h" #include "covers/discogscoverprovider.h" -#include "covers/artloader.h" #include "covers/coverproviders.h" #include "engines/enginebase.h" #include "internet/digitallyimportedclient.h" @@ -399,25 +398,19 @@ int main(int argc, char *argv[]) { scoped_ptr tray_icon(SystemTrayIcon::CreateSystemTrayIcon()); OSD osd(tray_icon.get(), &app); - ArtLoader art_loader; - #ifdef HAVE_DBUS qDBusRegisterMetaType(); qDBusRegisterMetaType(); qDBusRegisterMetaType(); qDBusRegisterMetaType >(); - mpris::Mpris mpris(&app, &art_loader); - - QObject::connect(app.playlist_manager(), SIGNAL(CurrentSongChanged(Song)), &art_loader, SLOT(LoadArt(Song))); - QObject::connect(&art_loader, SIGNAL(ThumbnailLoaded(Song, QString, QImage)), - &osd, SLOT(CoverArtPathReady(Song, QString))); + mpris::Mpris mpris(&app); GlobalSearchService global_search_service(app.global_search()); #endif // Window - MainWindow w(&app, tray_icon.get(), &osd, &art_loader); + MainWindow w(&app, tray_icon.get(), &osd); #ifdef HAVE_GIO ScanGIOModulePath(); #endif diff --git a/src/ui/albumcoverchoicecontroller.cpp b/src/ui/albumcoverchoicecontroller.cpp index 30e7ca94a..1b762eaca 100644 --- a/src/ui/albumcoverchoicecontroller.cpp +++ b/src/ui/albumcoverchoicecontroller.cpp @@ -20,6 +20,7 @@ #include "core/logging.h" #include "covers/albumcoverfetcher.h" #include "covers/albumcoverloader.h" +#include "covers/currentartloader.h" #include "library/librarybackend.h" #include "ui/albumcoverchoicecontroller.h" #include "ui/albumcovermanager.h" @@ -207,6 +208,10 @@ void AlbumCoverChoiceController::SaveCover(Song* song, const QString &cover) { if(song->is_valid() && song->id() != -1) { song->set_art_manual(cover); app_->library_backend()->UpdateManualAlbumArtAsync(song->artist(), song->album(), cover); + + if (song->url() == app_->current_art_loader()->last_song().url()) { + app_->current_art_loader()->LoadArt(*song); + } } } diff --git a/src/ui/albumcovermanager.cpp b/src/ui/albumcovermanager.cpp index 2126cb64a..ca64386f5 100644 --- a/src/ui/albumcovermanager.cpp +++ b/src/ui/albumcovermanager.cpp @@ -23,6 +23,7 @@ #include "core/logging.h" #include "core/utilities.h" #include "covers/albumcoverfetcher.h" +#include "covers/albumcoverloader.h" #include "covers/coverproviders.h" #include "covers/coversearchstatisticsdialog.h" #include "library/librarybackend.h" @@ -57,7 +58,6 @@ AlbumCoverManager::AlbumCoverManager(Application* app, ui_(new Ui_CoverManager), app_(app), album_cover_choice_controller_(new AlbumCoverChoiceController(this)), - cover_loader_(new BackgroundThreadImplementation(this)), cover_fetcher_(new AlbumCoverFetcher(app_->cover_providers(), this, network)), cover_searcher_(NULL), artist_icon_(IconLoader::Load("x-clementine-artist")), @@ -191,19 +191,15 @@ void AlbumCoverManager::Init() { ui_->splitter->setSizes(QList() << 200 << width() - 200); } - cover_loader_->Start(true); - CoverLoaderInitialised(); + connect(app_->album_cover_loader(), + SIGNAL(ImageLoaded(quint64,QImage)), + SLOT(CoverImageLoaded(quint64,QImage))); + cover_searcher_->Init(cover_fetcher_); new ForceScrollPerPixel(ui_->albums, this); } -void AlbumCoverManager::CoverLoaderInitialised() { - cover_loader_->Worker()->SetDefaultOutputImage(QImage()); - connect(cover_loader_->Worker().get(), SIGNAL(ImageLoaded(quint64,QImage)), - SLOT(CoverImageLoaded(quint64,QImage))); -} - void AlbumCoverManager::showEvent(QShowEvent *) { Reset(); } @@ -234,10 +230,9 @@ void AlbumCoverManager::closeEvent(QCloseEvent* e) { } void AlbumCoverManager::CancelRequests() { + app_->album_cover_loader()->CancelTasks( + QSet::fromList(cover_loading_tasks_.keys())); cover_loading_tasks_.clear(); - if (cover_loader_ && cover_loader_->Worker()) { - cover_loader_->Worker()->Clear(); - } cover_fetching_tasks_.clear(); cover_fetcher_->Clear(); @@ -278,8 +273,6 @@ void AlbumCoverManager::ResetFetchCoversButton() { } void AlbumCoverManager::ArtistChanged(QListWidgetItem* current) { - if (!cover_loader_->Worker()) - return; if (!current) return; @@ -319,7 +312,8 @@ void AlbumCoverManager::ArtistChanged(QListWidgetItem* current) { item->setToolTip(info.artist + " - " + info.album_name); if (!info.art_automatic.isEmpty() || !info.art_manual.isEmpty()) { - quint64 id = cover_loader_->Worker()->LoadImageAsync( + quint64 id = app_->album_cover_loader()->LoadImageAsync( + cover_loader_options_, info.art_automatic, info.art_manual, info.first_url.toLocalFile()); item->setData(Role_PathAutomatic, info.art_automatic); item->setData(Role_PathManual, info.art_manual); @@ -538,7 +532,8 @@ void AlbumCoverManager::FetchSingleCover() { void AlbumCoverManager::UpdateCoverInList(QListWidgetItem* item, const QString& cover) { - quint64 id = cover_loader_->Worker()->LoadImageAsync(QString(), cover); + quint64 id = app_->album_cover_loader()->LoadImageAsync( + cover_loader_options_, QString(), cover); item->setData(Role_PathManual, cover); cover_loading_tasks_[id] = item; } @@ -712,7 +707,8 @@ void AlbumCoverManager::SaveAndSetCover(QListWidgetItem *item, const QImage &ima app_->library_backend()->UpdateManualAlbumArtAsync(artist, album, path); // Update the icon in our list - quint64 id = cover_loader_->Worker()->LoadImageAsync(QString(), path); + quint64 id = app_->album_cover_loader()->LoadImageAsync( + cover_loader_options_, QString(), path); item->setData(Role_PathManual, path); cover_loading_tasks_[id] = item; } diff --git a/src/ui/albumcovermanager.h b/src/ui/albumcovermanager.h index ca37ed64f..b3d9c7c13 100644 --- a/src/ui/albumcovermanager.h +++ b/src/ui/albumcovermanager.h @@ -24,9 +24,8 @@ #include "gtest/gtest_prod.h" -#include "core/backgroundthread.h" #include "core/song.h" -#include "covers/albumcoverloader.h" +#include "covers/albumcoverloaderoptions.h" #include "covers/coversearchstatistics.h" class AlbumCoverChoiceController; @@ -77,7 +76,6 @@ class AlbumCoverManager : public QMainWindow { private slots: void ArtistChanged(QListWidgetItem* current); - void CoverLoaderInitialised(); void CoverImageLoaded(quint64 id, const QImage& image); void UpdateFilter(); void FetchAlbumCovers(); @@ -151,7 +149,7 @@ class AlbumCoverManager : public QMainWindow { QAction* filter_with_covers_; QAction* filter_without_covers_; - BackgroundThread* cover_loader_; + AlbumCoverLoaderOptions cover_loader_options_; QMap cover_loading_tasks_; AlbumCoverFetcher* cover_fetcher_; diff --git a/src/ui/albumcoversearcher.cpp b/src/ui/albumcoversearcher.cpp index fdfbabe08..230314d95 100644 --- a/src/ui/albumcoversearcher.cpp +++ b/src/ui/albumcoversearcher.cpp @@ -17,6 +17,7 @@ #include "albumcoversearcher.h" #include "ui_albumcoversearcher.h" +#include "core/application.h" #include "core/logging.h" #include "core/utilities.h" #include "covers/albumcoverfetcher.h" @@ -95,7 +96,6 @@ AlbumCoverSearcher::AlbumCoverSearcher(const QIcon& no_cover_icon, app_(app), model_(new QStandardItemModel(this)), no_cover_icon_(no_cover_icon), - loader_(new BackgroundThreadImplementation(this)), fetcher_(NULL), id_(0) { @@ -108,10 +108,11 @@ AlbumCoverSearcher::AlbumCoverSearcher(const QIcon& no_cover_icon, ui_->covers->setItemDelegate(new SizeOverlayDelegate(this)); ui_->covers->setModel(model_); - loader_->Start(true); - loader_->Worker()->SetScaleOutputImage(false); - loader_->Worker()->SetPadOutputImage(false); - connect(loader_->Worker().get(), SIGNAL(ImageLoaded(quint64,QImage)), + options_.scale_output_image_ = false; + options_.pad_output_image_ = false; + + connect(app_->album_cover_loader(), + SIGNAL(ImageLoaded(quint64,QImage)), SLOT(ImageLoaded(quint64,QImage))); connect(ui_->search, SIGNAL(clicked()), SLOT(Search())); @@ -183,7 +184,8 @@ void AlbumCoverSearcher::SearchFinished(quint64 id, const CoverSearchResults& re if (result.image_url.isEmpty()) continue; - quint64 id = loader_->Worker()->LoadImageAsync(result.image_url, QString()); + quint64 id = app_->album_cover_loader()->LoadImageAsync( + options_, result.image_url, QString()); QStandardItem* item = new QStandardItem; item->setIcon(no_cover_icon_); diff --git a/src/ui/albumcoversearcher.h b/src/ui/albumcoversearcher.h index b4d2a33b4..710e9ce8a 100644 --- a/src/ui/albumcoversearcher.h +++ b/src/ui/albumcoversearcher.h @@ -18,8 +18,8 @@ #ifndef ALBUMCOVERSEARCHER_H #define ALBUMCOVERSEARCHER_H -#include "core/backgroundthread.h" #include "covers/albumcoverfetcher.h" +#include "covers/albumcoverloaderoptions.h" #include #include @@ -90,7 +90,7 @@ private: QStandardItemModel* model_; QIcon no_cover_icon_; - BackgroundThread* loader_; + AlbumCoverLoaderOptions options_; AlbumCoverFetcher* fetcher_; quint64 id_; diff --git a/src/ui/edittagdialog.cpp b/src/ui/edittagdialog.cpp index 760978518..776f952d5 100644 --- a/src/ui/edittagdialog.cpp +++ b/src/ui/edittagdialog.cpp @@ -57,15 +57,15 @@ EditTagDialog::EditTagDialog(Application* app, QWidget* parent) loading_(false), ignore_edits_(false), tag_fetcher_(new TagFetcher(this)), - cover_loader_(new BackgroundThreadImplementation(this)), cover_art_id_(0), cover_art_is_set_(false), results_dialog_(new TrackSelectionDialog(this)) { - cover_loader_->Start(true); - cover_loader_->Worker()->SetDefaultOutputImage(QImage(":nocover.png")); - connect(cover_loader_->Worker().get(), SIGNAL(ImageLoaded(quint64,QImage,QImage)), + cover_options_.default_output_image_ = QImage(":nocover.png"); + + connect(app_->album_cover_loader(), SIGNAL(ImageLoaded(quint64,QImage,QImage)), SLOT(ArtLoaded(quint64,QImage,QImage))); + connect(tag_fetcher_, SIGNAL(ResultAvailable(Song, SongList)), results_dialog_, SLOT(FetchTagFinished(Song, SongList)), Qt::QueuedConnection); @@ -421,7 +421,7 @@ static void SetDate(QLabel* label, uint time) { } void EditTagDialog::UpdateSummaryTab(const Song& song) { - cover_art_id_ = cover_loader_->Worker()->LoadImageAsync(song); + cover_art_id_ = app_->album_cover_loader()->LoadImageAsync(cover_options_, song); QString summary = "" + Qt::escape(song.PrettyTitleWithArtist()) + "
"; diff --git a/src/ui/edittagdialog.h b/src/ui/edittagdialog.h index 9e5f8d327..f5e492fad 100644 --- a/src/ui/edittagdialog.h +++ b/src/ui/edittagdialog.h @@ -22,8 +22,8 @@ #include #include "config.h" -#include "core/backgroundthread.h" #include "core/song.h" +#include "covers/albumcoverloaderoptions.h" #include "musicbrainz/tagfetcher.h" #include "playlist/playlistitem.h" #include "widgets/lineedit.h" @@ -31,7 +31,6 @@ class Application; class AlbumCoverChoiceController; -class AlbumCoverLoader; class LibraryBackend; class Ui_EditTagDialog; @@ -152,7 +151,7 @@ private: TagFetcher* tag_fetcher_; - BackgroundThread* cover_loader_; + AlbumCoverLoaderOptions cover_options_; quint64 cover_art_id_; bool cover_art_is_set_; diff --git a/src/ui/mainwindow.cpp b/src/ui/mainwindow.cpp index bf4a636c5..81ccc8095 100644 --- a/src/ui/mainwindow.cpp +++ b/src/ui/mainwindow.cpp @@ -36,7 +36,6 @@ #include "core/stylesheetloader.h" #include "core/taskmanager.h" #include "core/utilities.h" -#include "covers/artloader.h" #include "devices/devicemanager.h" #include "devices/devicestatefiltermodel.h" #include "devices/deviceview.h" @@ -152,7 +151,6 @@ const char* MainWindow::kAllFilesFilterSpec = MainWindow::MainWindow(Application* app, SystemTrayIcon* tray_icon, OSD* osd, - ArtLoader* art_loader, QWidget* parent) : QMainWindow(parent), ui_(new Ui_MainWindow), @@ -213,7 +211,7 @@ MainWindow::MainWindow(Application* app, // Add global search providers app_->global_search()->AddProvider(new LibrarySearchProvider( app_->library_backend(), tr("Library"), "library", - IconLoader::Load("folder-sound"), true, this)); + IconLoader::Load("folder-sound"), true, app_, this)); app_->global_search()->ReloadSettings(); @@ -412,7 +410,6 @@ MainWindow::MainWindow(Application* app, connect(app_->player(), SIGNAL(VolumeChanged(int)), ui_->volume, SLOT(setValue(int))); connect(app_->player(), SIGNAL(ForceShowOSD(Song, bool)), SLOT(ForceShowOSD(Song, bool))); connect(app_->playlist_manager(), SIGNAL(CurrentSongChanged(Song)), SLOT(SongChanged(Song))); - connect(app_->playlist_manager(), SIGNAL(CurrentSongChanged(Song)), osd_, SLOT(SongChanged(Song))); connect(app_->playlist_manager(), SIGNAL(CurrentSongChanged(Song)), app_->player(), SLOT(CurrentMetadataChanged(Song))); connect(app_->playlist_manager(), SIGNAL(EditingFinished(QModelIndex)), SLOT(PlaylistEditFinished(QModelIndex))); connect(app_->playlist_manager(), SIGNAL(Error(QString)), SLOT(ShowErrorDialog(QString))); @@ -636,7 +633,6 @@ MainWindow::MainWindow(Application* app, qLog(Debug) << "Creating now playing widget"; ui_->now_playing->set_ideal_height(ui_->status_bar->sizeHint().height() + ui_->player_controls->sizeHint().height()); - connect(app_->playlist_manager(), SIGNAL(CurrentSongChanged(Song)), ui_->now_playing, SLOT(NowPlaying(Song))); connect(app_->player(), SIGNAL(Stopped()), ui_->now_playing, SLOT(Stopped())); connect(ui_->now_playing, SIGNAL(ShowAboveStatusBarChanged(bool)), SLOT(NowPlayingWidgetPositionChanged(bool))); @@ -1675,13 +1671,11 @@ void MainWindow::CommandlineOptionsReceived(const CommandlineOptions &options) { app_->player()->TogglePrettyOSD(); } -void MainWindow::ForceShowOSD(const Song &song, const bool toggle) { +void MainWindow::ForceShowOSD(const Song& song, const bool toggle) { if (toggle) { osd_->SetPrettyOSDToggleMode(toggle); - } else { - osd_->ForceShowNextNotification(); } - osd_->SongChanged(song); + osd_->ReshowCurrentSong(); } void MainWindow::Activate() { diff --git a/src/ui/mainwindow.h b/src/ui/mainwindow.h index 0edd96f6b..7adc6f93b 100644 --- a/src/ui/mainwindow.h +++ b/src/ui/mainwindow.h @@ -38,7 +38,6 @@ class AlbumCoverManager; class Appearance; class Application; class ArtistInfoView; -class ArtLoader; class BackgroundStreams; class CommandlineOptions; class CoverProviders; @@ -88,7 +87,6 @@ class MainWindow : public QMainWindow, public PlatformInterface { MainWindow(Application* app, SystemTrayIcon* tray_icon, OSD* osd, - ArtLoader* art_loader, QWidget *parent = 0); ~MainWindow(); diff --git a/src/widgets/nowplayingwidget.cpp b/src/widgets/nowplayingwidget.cpp index 4b293e8ed..a7b781f86 100644 --- a/src/widgets/nowplayingwidget.cpp +++ b/src/widgets/nowplayingwidget.cpp @@ -20,6 +20,7 @@ #include "core/application.h" #include "covers/albumcoverloader.h" #include "covers/coverproviders.h" +#include "covers/currentartloader.h" #include "covers/kittenloader.h" #include "library/librarybackend.h" #include "ui/albumcoverchoicecontroller.h" @@ -60,21 +61,19 @@ NowPlayingWidget::NowPlayingWidget(QWidget* parent) : QWidget(parent), app_(NULL), album_cover_choice_controller_(new AlbumCoverChoiceController(this)), - cover_loader_(new BackgroundThreadImplementation(this)), - kitten_loader_(NULL), mode_(SmallSongDetails), menu_(new QMenu(this)), above_statusbar_action_(NULL), visible_(false), small_ideal_height_(0), - cover_height_(0), show_hide_animation_(new QTimeLine(500, this)), fade_animation_(new QTimeLine(1000, this)), - load_cover_id_(0), details_(new QTextDocument(this)), previous_track_opacity_(0.0), bask_in_his_glory_action_(NULL), - aww_(false) + aww_(false), + kittens_(NULL), + pending_kitten_(0) { // Load settings QSettings s; @@ -128,9 +127,7 @@ NowPlayingWidget::NowPlayingWidget(QWidget* parent) connect(fade_animation_, SIGNAL(valueChanged(qreal)), SLOT(FadePreviousTrack(qreal))); fade_animation_->setDirection(QTimeLine::Backward); // 1.0 -> 0.0 - // Start loading the cover loader thread - cover_loader_->Start(); - connect(cover_loader_, SIGNAL(Initialised()), SLOT(CoverLoaderInitialised())); + UpdateHeight(); } NowPlayingWidget::~NowPlayingWidget() { @@ -140,6 +137,8 @@ void NowPlayingWidget::SetApplication(Application* app) { app_ = app; album_cover_choice_controller_->SetApplication(app_); + connect(app_->current_art_loader(), SIGNAL(ArtLoaded(Song,QString,QImage)), + SLOT(AlbumArtLoaded(Song,QString,QImage))); } void NowPlayingWidget::CreateModeAction(Mode mode, const QString &text, QActionGroup *group, QSignalMapper* mapper) { @@ -154,38 +153,23 @@ void NowPlayingWidget::CreateModeAction(Mode mode, const QString &text, QActionG void NowPlayingWidget::set_ideal_height(int height) { small_ideal_height_ = height; - UpdateHeight(aww_ - ? kitten_loader_->Worker().get() - : cover_loader_->Worker().get()); + UpdateHeight(); } QSize NowPlayingWidget::sizeHint() const { - return QSize(cover_height_, total_height_); + return QSize(cover_loader_options_.desired_height_, total_height_); } -void NowPlayingWidget::CoverLoaderInitialised() { - BackgroundThread* loader = - static_cast*>(sender()); - UpdateHeight(loader->Worker().get()); - loader->Worker()->SetPadOutputImage(true); - connect(loader->Worker().get(), SIGNAL(ImageLoaded(quint64,QImage,QImage)), - SLOT(AlbumArtLoaded(quint64,QImage,QImage))); -} - -void NowPlayingWidget::UpdateHeight(AlbumCoverLoader* loader) { - if (!loader) { - return; - } - +void NowPlayingWidget::UpdateHeight() { switch (mode_) { case SmallSongDetails: - cover_height_ = small_ideal_height_; + cover_loader_options_.desired_height_ = small_ideal_height_; total_height_ = small_ideal_height_; break; case LargeSongDetails: - cover_height_ = qMin(kMaxCoverSize, width()); - total_height_ = kTopBorder + cover_height_ + kBottomOffset; + cover_loader_options_.desired_height_ = qMin(kMaxCoverSize, width()); + total_height_ = kTopBorder + cover_loader_options_.desired_height_ + kBottomOffset; break; } @@ -194,41 +178,15 @@ void NowPlayingWidget::UpdateHeight(AlbumCoverLoader* loader) { if (visible_ && show_hide_animation_->state() != QTimeLine::Running) setMaximumHeight(total_height_); - // Tell the cover loader what size we want the images in - loader->SetDesiredHeight(cover_height_); - loader->SetDefaultOutputImage(QImage(":nocover.png")); - - // Re-fetch the current image - load_cover_id_ = loader->LoadImageAsync(metadata_); + // Re-scale the current image + if (metadata_.is_valid()) { + ScaleCover(); + } // Tell Qt we've changed size updateGeometry(); } -void NowPlayingWidget::NowPlaying(const Song& metadata) { - if (visible_) { - // Cache the current pixmap so we can fade between them - previous_track_ = QPixmap(size()); - previous_track_.fill(palette().background().color()); - previous_track_opacity_ = 1.0; - QPainter p(&previous_track_); - DrawContents(&p); - p.end(); - } - - metadata_ = metadata; - cover_ = QPixmap(); - - // Loads the cover too. - UpdateHeight(aww_ - ? kitten_loader_->Worker().get() - : cover_loader_->Worker().get()); - UpdateDetailsText(); - - SetVisible(true); - update(); -} - void NowPlayingWidget::Stopped() { SetVisible(false); } @@ -244,7 +202,7 @@ void NowPlayingWidget::UpdateDetailsText() { break; case LargeSongDetails: - details_->setTextWidth(cover_height_); + details_->setTextWidth(cover_loader_options_.desired_height_); details_->setDefaultStyleSheet("p {" " font-size: small;" " color: white;" @@ -262,13 +220,46 @@ void NowPlayingWidget::UpdateDetailsText() { details_->setHtml(html); } -void NowPlayingWidget::AlbumArtLoaded(quint64 id, const QImage& scaled, const QImage& original) { - if (id != load_cover_id_) - return; - - cover_ = QPixmap::fromImage(scaled); - original_ = original; +void NowPlayingWidget::ScaleCover() { + cover_ = QPixmap::fromImage( + AlbumCoverLoader::ScaleAndPad(cover_loader_options_, original_)); update(); +} + +void NowPlayingWidget::KittenLoaded(quint64 id, const QImage& image) { + if (aww_ && pending_kitten_ == id) { + SetImage(image); + } +} + +void NowPlayingWidget::AlbumArtLoaded(const Song& metadata, const QString&, + const QImage& image) { + metadata_ = metadata; + + if (aww_) { + pending_kitten_ = kittens_->LoadKitten(app_->current_art_loader()->options()); + return; + } + + SetImage(image); +} + +void NowPlayingWidget::SetImage(const QImage& image) { + if (visible_) { + // Cache the current pixmap so we can fade between them + previous_track_ = QPixmap(size()); + previous_track_.fill(palette().background().color()); + previous_track_opacity_ = 1.0; + QPainter p(&previous_track_); + DrawContents(&p); + p.end(); + } + + original_ = image; + + UpdateDetailsText(); + ScaleCover(); + SetVisible(true); // Were we waiting for this cover to load before we started fading? if (!previous_track_.isNull()) { @@ -319,7 +310,7 @@ void NowPlayingWidget::DrawContents(QPainter *p) { case LargeSongDetails: const int total_size = qMin(kMaxCoverSize, width()); - const int x_offset = (width() - cover_height_) / 2; + const int x_offset = (width() - cover_loader_options_.desired_height_) / 2; // Draw the black background p->fillRect(QRect(0, kTopBorder, width(), height() - kTopBorder), Qt::black); @@ -363,9 +354,7 @@ void NowPlayingWidget::FadePreviousTrack(qreal value) { void NowPlayingWidget::SetMode(int mode) { mode_ = Mode(mode); - UpdateHeight(aww_ - ? kitten_loader_->Worker().get() - : cover_loader_->Worker().get()); + UpdateHeight(); UpdateDetailsText(); update(); @@ -376,9 +365,7 @@ void NowPlayingWidget::SetMode(int mode) { void NowPlayingWidget::resizeEvent(QResizeEvent* e) { if (visible_ && mode_ == LargeSongDetails && e->oldSize().width() != e->size().width()) { - UpdateHeight(aww_ - ? kitten_loader_->Worker().get() - : cover_loader_->Worker().get()); + UpdateHeight(); UpdateDetailsText(); } } @@ -432,36 +419,25 @@ void NowPlayingWidget::AllHail(bool hypnotoad) { } void NowPlayingWidget::EnableKittens(bool aww) { - if (!kitten_loader_ && aww) { - kitten_loader_ = new BackgroundThreadImplementation(this); - kitten_loader_->Start(); - connect(kitten_loader_, SIGNAL(Initialised()), SLOT(CoverLoaderInitialised())); - } else if (aww) { - NowPlaying(metadata_); + if (!kittens_ && aww) { + kittens_ = new KittenLoader(this); + app_->MoveToNewThread(kittens_); + connect(kittens_, SIGNAL(ImageLoaded(quint64,QImage)), SLOT(KittenLoaded(quint64,QImage))); } aww_ = aww; } void NowPlayingWidget::LoadCoverFromFile() { - QString cover = album_cover_choice_controller_->LoadCoverFromFile(&metadata_); - - if(!cover.isEmpty()) - NowPlaying(metadata_); + album_cover_choice_controller_->LoadCoverFromFile(&metadata_); } void NowPlayingWidget::LoadCoverFromURL() { - QString cover = album_cover_choice_controller_->LoadCoverFromURL(&metadata_); - - if(!cover.isEmpty()) - NowPlaying(metadata_); + album_cover_choice_controller_->LoadCoverFromURL(&metadata_); } void NowPlayingWidget::SearchForCover() { - QString cover = album_cover_choice_controller_->SearchForCover(&metadata_); - - if(!cover.isEmpty()) - NowPlaying(metadata_); + album_cover_choice_controller_->SearchForCover(&metadata_); } void NowPlayingWidget::SaveCoverToFile() { @@ -470,7 +446,6 @@ void NowPlayingWidget::SaveCoverToFile() { void NowPlayingWidget::UnsetCover() { album_cover_choice_controller_->UnsetCover(&metadata_); - NowPlaying(metadata_); } void NowPlayingWidget::ShowCover() { @@ -492,7 +467,6 @@ void NowPlayingWidget::dragEnterEvent(QDragEnterEvent* e) { void NowPlayingWidget::dropEvent(QDropEvent* e) { album_cover_choice_controller_->SaveCover(&metadata_, e); - NowPlaying(metadata_); QWidget::dropEvent(e); } diff --git a/src/widgets/nowplayingwidget.h b/src/widgets/nowplayingwidget.h index 9ceb05882..498e1a44e 100644 --- a/src/widgets/nowplayingwidget.h +++ b/src/widgets/nowplayingwidget.h @@ -18,17 +18,17 @@ #ifndef NOWPLAYINGWIDGET_H #define NOWPLAYINGWIDGET_H -#include "core/backgroundthread.h" #include "core/song.h" +#include "covers/albumcoverloaderoptions.h" #include #include class AlbumCoverChoiceController; -class AlbumCoverLoader; class Application; class FullscreenHypnotoad; +class KittenLoader; class QAction; class QActionGroup; @@ -70,7 +70,6 @@ signals: void ShowAboveStatusBarChanged(bool above); public slots: - void NowPlaying(const Song& metadata); void Stopped(); void AllHail(bool hypnotoad); void EnableKittens(bool aww); @@ -86,8 +85,8 @@ private slots: void SetMode(int mode); void ShowAboveStatusBar(bool above); - void CoverLoaderInitialised(); - void AlbumArtLoaded(quint64 id, const QImage& scaled, const QImage& original); + void AlbumArtLoaded(const Song& metadata, const QString& uri, const QImage& image); + void KittenLoaded(quint64 id, const QImage& image); void SetVisible(bool visible); void SetHeight(int height); @@ -107,16 +106,15 @@ private: void CreateModeAction(Mode mode, const QString& text, QActionGroup* group, QSignalMapper* mapper); void UpdateDetailsText(); - void UpdateHeight(AlbumCoverLoader* loader); + void UpdateHeight(); void DrawContents(QPainter* p); + void SetImage(const QImage& image); + void ScaleCover(); private: Application* app_; AlbumCoverChoiceController* album_cover_choice_controller_; - BackgroundThread* cover_loader_; - BackgroundThread* kitten_loader_; - Mode mode_; QMenu* menu_; @@ -125,14 +123,13 @@ private: bool visible_; int small_ideal_height_; - int cover_height_; + AlbumCoverLoaderOptions cover_loader_options_; int total_height_; QTimeLine* show_hide_animation_; QTimeLine* fade_animation_; // Information about the current track Song metadata_; - quint64 load_cover_id_; QPixmap cover_; // A copy of the original, unscaled album cover. QImage original_; @@ -148,6 +145,8 @@ private: boost::scoped_ptr big_hypnotoad_; bool aww_; + KittenLoader* kittens_; + quint64 pending_kitten_; }; #endif // NOWPLAYINGWIDGET_H diff --git a/src/widgets/osd.cpp b/src/widgets/osd.cpp index dcf30b11a..159407f06 100644 --- a/src/widgets/osd.cpp +++ b/src/widgets/osd.cpp @@ -16,7 +16,9 @@ */ #include "config.h" +#include "core/application.h" #include "core/logging.h" +#include "covers/currentartloader.h" #include "osd.h" #include "osdpretty.h" #include "ui/systemtrayicon.h" @@ -46,12 +48,10 @@ OSD::OSD(SystemTrayIcon* tray_icon, Application* app, QObject* parent) preview_mode_(false), force_show_next_(false), ignore_next_stopped_(false), - pretty_popup_(new OSDPretty(OSDPretty::Mode_Popup)), - cover_loader_(new BackgroundThreadImplementation(this)) + pretty_popup_(new OSDPretty(OSDPretty::Mode_Popup)) { - cover_loader_->Start(); - - connect(cover_loader_, SIGNAL(Initialised()), SLOT(CoverLoaderInitialised())); + connect(app_->current_art_loader(), SIGNAL(ArtLoaded(Song,QString,QImage)), + SLOT(AlbumArtLoaded(Song,QString,QImage))); ReloadSettings(); Init(); @@ -61,13 +61,6 @@ OSD::~OSD() { delete pretty_popup_; } -void OSD::CoverLoaderInitialised() { - cover_loader_->Worker()->SetPadOutputImage(false); - cover_loader_->Worker()->SetDefaultOutputImage(QImage(":nocover.png")); - connect(cover_loader_->Worker().get(), SIGNAL(ImageLoaded(quint64,QImage)), - SLOT(AlbumArtLoaded(quint64,QImage))); -} - void OSD::ReloadSettings() { QSettings s; s.beginGroup(kSettingsGroup); @@ -94,13 +87,21 @@ void OSD::ReloadPrettyOSDSettings() { pretty_popup_->ReloadSettings(); } -void OSD::SongChanged(const Song &song) { +void OSD::ReshowCurrentSong() { + force_show_next_ = true; + AlbumArtLoaded(last_song_, last_image_uri_, last_image_); +} + +void OSD::AlbumArtLoaded(const Song& song, const QString& uri, const QImage& image) { // Don't change tray icon details if it's a preview if (!preview_mode_) { - // no cover art yet - tray_icon_->SetNowPlaying(song, NULL); + tray_icon_->SetNowPlaying(song, uri); } + last_song_ = song; + last_image_ = image; + last_image_uri_ = uri; + QStringList message_parts; QString summary; if (!use_custom_text_) { @@ -138,34 +139,11 @@ void OSD::SongChanged(const Song &song) { message_parts << message; } - WaitingForAlbumArt waiting; - waiting.icon = "notification-audio-play"; - waiting.summary = summary; - waiting.message = message_parts.join(", "); - if (show_art_) { - // Load the art in a background thread (maybe from a remote server), - // AlbumArtLoaded gets called when it's ready. - quint64 id = cover_loader_->Worker()->LoadImageAsync(song); - waiting_for_album_art_.insert(id, waiting); + ShowMessage(summary, message_parts.join(", "), "notification-audio-play", image); } else { - AlbumArtLoaded(waiting, QImage()); + ShowMessage(summary, message_parts.join(", "), "notification-audio-play", QImage()); } -} - -void OSD::CoverArtPathReady(const Song& song, const QString& image_path) { - // Don't change tray icon details if it's a preview - if (!preview_mode_) - tray_icon_->SetNowPlaying(song, image_path); -} - -void OSD::AlbumArtLoaded(quint64 id, const QImage& image) { - WaitingForAlbumArt info = waiting_for_album_art_.take(id); - AlbumArtLoaded(info, image); -} - -void OSD::AlbumArtLoaded(const WaitingForAlbumArt info, const QImage& image) { - ShowMessage(info.summary, info.message, info.icon, image); // Reload the saved settings if they were changed for preview if (preview_mode_) { @@ -380,7 +358,7 @@ void OSD::ShowPreview(const Behaviour type, const QString& line1, const QString& // We want to reload the settings, but we can't do this here because the cover art loading is asynch preview_mode_ = true; - SongChanged(song); + AlbumArtLoaded(song, QString(), QImage()); } void OSD::SetPrettyOSDToggleMode(bool toggle) { diff --git a/src/widgets/osd.h b/src/widgets/osd.h index d62d1180a..dddd7648e 100644 --- a/src/widgets/osd.h +++ b/src/widgets/osd.h @@ -24,9 +24,7 @@ #include "config.h" #include "engines/engine_fwd.h" -#include "core/backgroundthread.h" #include "core/song.h" -#include "covers/albumcoverloader.h" #include "playlist/playlistsequence.h" class Application; @@ -71,8 +69,6 @@ class OSD : public QObject { public slots: void ReloadSettings(); - void ForceShowNextNotification() { force_show_next_ = true; } - void SongChanged(const Song& song); void Paused(); void Stopped(); void PlaylistFinished(); @@ -81,6 +77,8 @@ class OSD : public QObject { void RepeatModeChanged(PlaylistSequence::RepeatMode mode); void ShuffleModeChanged(PlaylistSequence::ShuffleMode mode); + void ReshowCurrentSong(); + #ifdef HAVE_WIIMOTEDEV void WiiremoteActived(int id); void WiiremoteDeactived(int id); @@ -93,12 +91,6 @@ class OSD : public QObject { void ShowPreview(const Behaviour type, const QString& line1, const QString& line2, const Song& song); private: - struct WaitingForAlbumArt { - QString summary; - QString message; - QString icon; - }; - void ShowMessage(const QString& summary, const QString& message = QString(), const QString& icon = QString(), @@ -114,10 +106,7 @@ class OSD : public QObject { private slots: void CallFinished(QDBusPendingCallWatcher* watcher); - void CoverLoaderInitialised(); - void CoverArtPathReady(const Song& song, const QString& image_path); - void AlbumArtLoaded(quint64 id, const QImage& image); - void AlbumArtLoaded(const WaitingForAlbumArt info, const QImage& image); + void AlbumArtLoaded(const Song& song, const QString& uri, const QImage& image); private: SystemTrayIcon* tray_icon_; @@ -137,8 +126,9 @@ class OSD : public QObject { OSDPretty* pretty_popup_; - BackgroundThread* cover_loader_; - QMap waiting_for_album_art_; + Song last_song_; + QString last_image_uri_; + QImage last_image_; #ifdef Q_OS_DARWIN class GrowlNotificationWrapper;