Refactoring: remove a couple of the AlbumCoverLoader instances and instead use a shared CurrentArtLoader.

This commit is contained in:
David Sansome 2012-02-13 20:44:04 +00:00
parent 48f15c9fc7
commit bacef04405
72 changed files with 413 additions and 397 deletions

View File

@ -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

View File

@ -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);

View File

@ -20,8 +20,10 @@
#include <QObject>
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_;

View File

@ -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();

View File

@ -21,7 +21,6 @@
#include <QObject>
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();

View File

@ -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 <QCoreApplication>
#include <QDBusConnection>
@ -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&)));
}

View File

@ -25,7 +25,6 @@
#include <QObject>
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();

View File

@ -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()));

View File

@ -27,7 +27,6 @@
#include <boost/scoped_ptr.hpp>
class Application;
class ArtLoader;
class MainWindow;
typedef QList<QVariantMap> 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();

View File

@ -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<Task>::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<quint64>& ids) {
QMutexLocker l(&mutex_);
for (QQueue<Task>::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());
}

View File

@ -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<quint64>& 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<Task> tasks_;
QMap<QNetworkReply*, Task> remote_tasks_;

View File

@ -0,0 +1,19 @@
/* This file is part of Clementine.
Copyright 2012, David Sansome <me@davidsansome.com>
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 <http://www.gnu.org/licenses/>.
*/
#include "albumcoverloaderoptions.h"

View File

@ -0,0 +1,36 @@
/* This file is part of Clementine.
Copyright 2012, David Sansome <me@davidsansome.com>
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 <http://www.gnu.org/licenses/>.
*/
#ifndef ALBUMCOVERLOADEROPTIONS_H
#define ALBUMCOVERLOADEROPTIONS_H
#include <QImage>
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

View File

@ -15,40 +15,41 @@
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
*/
#include "albumcoverloader.h"
#include "artloader.h"
#include "currentartloader.h"
#include "core/application.h"
#include "covers/albumcoverloader.h"
#include "playlist/playlistmanager.h"
#include <QDir>
#include <QTemporaryFile>
#include <QUrl>
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<AlbumCoverLoader, AlbumCoverLoader>(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;

View File

@ -15,27 +15,30 @@
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
*/
#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 <QObject>
#include <boost/scoped_ptr.hpp>
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<QTemporaryFile> temp_art_;
boost::scoped_ptr<QTemporaryFile> temp_art_thumbnail_;
BackgroundThread<AlbumCoverLoader>* cover_loader_;
quint64 id_;
Song last_song_;
};
#endif // ARTLOADER_H
#endif // CURRENTARTLOADER_H

View File

@ -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_++;

View File

@ -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();

View File

@ -25,6 +25,7 @@
#include <QDir>
#include <QFile>
#include <QThread>
#include <QtDebug>
#include <gpod/itdb.h>

View File

@ -27,6 +27,7 @@
#include <libmtp.h>
#include <QFile>
#include <QThread>
bool MtpDevice::sInitialisedLibMTP = false;

View File

@ -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(),

View File

@ -25,7 +25,7 @@ class DigitallyImportedServiceBase;
class DigitallyImportedSearchProvider : public SimpleSearchProvider {
public:
DigitallyImportedSearchProvider(DigitallyImportedServiceBase* service,
QObject* parent);
Application* app, QObject* parent);
void ShowConfig();

View File

@ -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<AlbumCoverLoader, AlbumCoverLoader>(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()) {

View File

@ -22,8 +22,7 @@
#include <QPixmapCache>
#include "searchprovider.h"
#include "core/backgroundthread.h"
#include "covers/albumcoverloaderoptions.h"
class AlbumCoverLoader;
class Application;
@ -126,7 +125,7 @@ private:
QMap<int, QString> pending_art_searches_;
// Used for providers with ArtIsInSongMetadata set.
BackgroundThread<AlbumCoverLoader>* cover_loader_;
AlbumCoverLoaderOptions cover_loader_options_;
QMap<quint64, int> cover_loader_tasks_;
// Special search provider that's used for queries that look like URLs

View File

@ -19,13 +19,16 @@
#include <QIcon>
#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<AlbumCoverLoader, AlbumCoverLoader>(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;
}

View File

@ -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<int, PendingState> pending_searches_;
BackgroundThread<AlbumCoverLoader>* cover_loader_;
AlbumCoverLoaderOptions cover_loader_options_;
QMap<quint64, int> cover_loader_tasks_;
};

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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 |

View File

@ -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);

View File

@ -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"));

View File

@ -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);

View File

@ -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) {

View File

@ -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;

View File

@ -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)

View File

@ -24,7 +24,7 @@ class SimpleSearchProvider : public BlockingSearchProvider {
Q_OBJECT
public:
SimpleSearchProvider(QObject* parent);
SimpleSearchProvider(Application* app, QObject* parent);
static const int kDefaultResultLimit;

View File

@ -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);

View File

@ -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);

View File

@ -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)
{

View File

@ -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);

View File

@ -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");

View File

@ -24,7 +24,7 @@
class UrlSearchProvider : public SearchProvider {
public:
UrlSearchProvider(QObject* parent);
UrlSearchProvider(Application* app, QObject* parent);
bool LooksLikeUrl(const QString& query) const;

View File

@ -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"

View File

@ -23,6 +23,8 @@
class DigitallyImportedClient;
class Ui_DigitallyImportedSettingsPage;
class QNetworkReply;
class DigitallyImportedSettingsPage : public SettingsPage {
Q_OBJECT

View File

@ -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);

View File

@ -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

View File

@ -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() {

View File

@ -125,8 +125,7 @@ JamendoService::JamendoService(Application* app, InternetModel* parent)
tr("Jamendo"),
"jamendo",
QIcon(":/providers/jamendo.png"),
false,
this));
false, app_, this));
}
JamendoService::~JamendoService() {

View File

@ -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() {

View File

@ -102,8 +102,7 @@ MagnatuneService::MagnatuneService(Application* app, InternetModel* parent)
tr("Magnatune"),
"magnatune",
QIcon(":/providers/magnatune.png"),
true,
this));
true, app_, this));
}
MagnatuneService::~MagnatuneService() {

View File

@ -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() {

View File

@ -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() {

View File

@ -26,6 +26,7 @@
class SomaFMUrlHandler;
class QNetworkAccessManager;
class QNetworkReply;
class QMenu;
class SomaFMService : public InternetService {

View File

@ -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);

View File

@ -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<AlbumCoverLoader, AlbumCoverLoader>(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;
}

View File

@ -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<LibraryItem> {
bool use_pretty_covers_;
bool show_dividers_;
BackgroundThread<AlbumCoverLoader>* cover_loader_;
AlbumCoverLoaderOptions cover_loader_options_;
QMap<quint64, LibraryItem*> pending_art_;
};

View File

@ -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<Song> all_of_album = library_->backend()->GetSongsByAlbum(album);
QList<Song> all_of_album = app_->library_backend()->GetSongsByAlbum(album);
QSet<QString> other_artists;
foreach (const Song& s, all_of_album) {
if(!albums.contains(album, s.artist()) && !other_artists.contains(s.artist())) {

View File

@ -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<SystemTrayIcon> tray_icon(SystemTrayIcon::CreateSystemTrayIcon());
OSD osd(tray_icon.get(), &app);
ArtLoader art_loader;
#ifdef HAVE_DBUS
qDBusRegisterMetaType<QImage>();
qDBusRegisterMetaType<TrackMetadata>();
qDBusRegisterMetaType<TrackIds>();
qDBusRegisterMetaType<QList<QByteArray> >();
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

View File

@ -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);
}
}
}

View File

@ -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<AlbumCoverLoader, AlbumCoverLoader>(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<int>() << 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<quint64>::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;
}

View File

@ -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<AlbumCoverLoader>* cover_loader_;
AlbumCoverLoaderOptions cover_loader_options_;
QMap<quint64, QListWidgetItem*> cover_loading_tasks_;
AlbumCoverFetcher* cover_fetcher_;

View File

@ -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<AlbumCoverLoader, AlbumCoverLoader>(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_);

View File

@ -18,8 +18,8 @@
#ifndef ALBUMCOVERSEARCHER_H
#define ALBUMCOVERSEARCHER_H
#include "core/backgroundthread.h"
#include "covers/albumcoverfetcher.h"
#include "covers/albumcoverloaderoptions.h"
#include <QDialog>
#include <QIcon>
@ -90,7 +90,7 @@ private:
QStandardItemModel* model_;
QIcon no_cover_icon_;
BackgroundThread<AlbumCoverLoader>* loader_;
AlbumCoverLoaderOptions options_;
AlbumCoverFetcher* fetcher_;
quint64 id_;

View File

@ -57,15 +57,15 @@ EditTagDialog::EditTagDialog(Application* app, QWidget* parent)
loading_(false),
ignore_edits_(false),
tag_fetcher_(new TagFetcher(this)),
cover_loader_(new BackgroundThreadImplementation<AlbumCoverLoader, AlbumCoverLoader>(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 = "<b>" + Qt::escape(song.PrettyTitleWithArtist()) + "</b><br/>";

View File

@ -22,8 +22,8 @@
#include <QModelIndexList>
#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<AlbumCoverLoader>* cover_loader_;
AlbumCoverLoaderOptions cover_options_;
quint64 cover_art_id_;
bool cover_art_is_set_;

View File

@ -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() {

View File

@ -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();

View File

@ -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<AlbumCoverLoader, AlbumCoverLoader>(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<AlbumCoverLoader>* loader =
static_cast<BackgroundThread<AlbumCoverLoader>*>(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<AlbumCoverLoader, KittenLoader>(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);
}

View File

@ -18,17 +18,17 @@
#ifndef NOWPLAYINGWIDGET_H
#define NOWPLAYINGWIDGET_H
#include "core/backgroundthread.h"
#include "core/song.h"
#include "covers/albumcoverloaderoptions.h"
#include <QWidget>
#include <boost/scoped_ptr.hpp>
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<AlbumCoverLoader>* cover_loader_;
BackgroundThread<AlbumCoverLoader>* 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<FullscreenHypnotoad> big_hypnotoad_;
bool aww_;
KittenLoader* kittens_;
quint64 pending_kitten_;
};
#endif // NOWPLAYINGWIDGET_H

View File

@ -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<AlbumCoverLoader, AlbumCoverLoader>(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) {

View File

@ -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<AlbumCoverLoader>* cover_loader_;
QMap<quint64, WaitingForAlbumArt> waiting_for_album_art_;
Song last_song_;
QString last_image_uri_;
QImage last_image_;
#ifdef Q_OS_DARWIN
class GrowlNotificationWrapper;