From 41f306fd2a125ff5f0ac587e89ee8decf13e1fe4 Mon Sep 17 00:00:00 2001 From: David Sansome Date: Mon, 10 May 2010 13:15:52 +0000 Subject: [PATCH] Load cover art from Magnatune: make AlbumCoverLoader load from http, and make the OSD load artwork asynchronously. --- src/CMakeLists.txt | 2 + src/albumcoverfetcher.cpp | 5 +- src/albumcoverfetcher.h | 4 +- src/albumcoverloader.cpp | 122 ++++++++++++++++++++++++++--------- src/albumcoverloader.h | 30 ++++++++- src/albumcovermanager.cpp | 4 +- src/albumcovermanager.h | 6 +- src/lastfmservice.cpp | 3 +- src/lastfmservice.h | 1 + src/magnatuneservice.cpp | 3 +- src/main.cpp | 11 ++-- src/mainwindow.cpp | 4 +- src/mainwindow.h | 5 +- src/networkaccessmanager.cpp | 61 ++++++++++++++++++ src/networkaccessmanager.h | 45 +++++++++++++ src/osd.cpp | 39 +++++++++-- src/osd.h | 18 +++++- src/radiomodel.cpp | 2 +- src/radiomodel.h | 9 ++- src/somafmservice.cpp | 3 +- src/song.cpp | 11 ---- src/song.h | 6 -- 22 files changed, 312 insertions(+), 82 deletions(-) create mode 100644 src/networkaccessmanager.cpp create mode 100644 src/networkaccessmanager.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7313ed0f0..0d4499f01 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -87,6 +87,7 @@ set(CLEMENTINE-SOURCES mergedproxymodel.cpp libraryfilterwidget.cpp radioviewcontainer.cpp + networkaccessmanager.cpp ) # Header files that have Q_OBJECT in @@ -159,6 +160,7 @@ set(CLEMENTINE-MOC-HEADERS mergedproxymodel.h libraryfilterwidget.h radioviewcontainer.h + networkaccessmanager.h ) # lists of engine source files diff --git a/src/albumcoverfetcher.cpp b/src/albumcoverfetcher.cpp index 7322f43f2..9c225f385 100644 --- a/src/albumcoverfetcher.cpp +++ b/src/albumcoverfetcher.cpp @@ -15,6 +15,7 @@ */ #include "albumcoverfetcher.h" +#include "networkaccessmanager.h" #include #include @@ -25,9 +26,9 @@ const int AlbumCoverFetcher::kMaxConcurrentRequests = 5; -AlbumCoverFetcher::AlbumCoverFetcher(QNetworkAccessManager* network, QObject* parent) +AlbumCoverFetcher::AlbumCoverFetcher(NetworkAccessManager* network, QObject* parent) : QObject(parent), - network_(network), + network_(network->network()), next_id_(0), request_starter_(new QTimer(this)) { diff --git a/src/albumcoverfetcher.h b/src/albumcoverfetcher.h index b2aaff484..f0625839e 100644 --- a/src/albumcoverfetcher.h +++ b/src/albumcoverfetcher.h @@ -30,11 +30,13 @@ class QNetworkReply; class QString; +class NetworkAccessManager; + class AlbumCoverFetcher : public QObject { Q_OBJECT public: - AlbumCoverFetcher(QNetworkAccessManager* network, QObject* parent = 0); + AlbumCoverFetcher(NetworkAccessManager* network, QObject* parent = 0); virtual ~AlbumCoverFetcher() {} static const int kMaxConcurrentRequests; diff --git a/src/albumcoverloader.cpp b/src/albumcoverloader.cpp index 1705db349..18d72aa72 100644 --- a/src/albumcoverloader.cpp +++ b/src/albumcoverloader.cpp @@ -15,10 +15,13 @@ */ #include "albumcoverloader.h" +#include "networkaccessmanager.h" #include #include #include +#include +#include const char* AlbumCoverLoader::kManuallyUnsetCover = "(unset)"; @@ -26,7 +29,8 @@ AlbumCoverLoader::AlbumCoverLoader(QObject* parent) : QObject(parent), stop_requested_(false), height_(120), - next_id_(0) + next_id_(0), + network_(NULL) { } @@ -41,10 +45,11 @@ void AlbumCoverLoader::Clear() { } quint64 AlbumCoverLoader::LoadImageAsync(const QString& art_automatic, - const QString& art_manual) { + const QString& art_manual) { Task task; task.art_automatic = art_automatic; task.art_manual = art_manual; + task.state = State_TryingManual; { QMutexLocker l(&mutex_); @@ -68,38 +73,93 @@ void AlbumCoverLoader::ProcessTasks() { task = tasks_.dequeue(); } - // Try to load the image - QImage image(TryLoadImage(task.art_automatic, task.art_manual)); - - if (!image.isNull()) { - // Scale the image down - image = image.scaled(QSize(height_, height_), Qt::KeepAspectRatio, Qt::SmoothTransformation); - - // Pad the image to height_ x height_ - QImage bigger_image(height_, height_, QImage::Format_ARGB32); - bigger_image.fill(0); - - QPainter p(&bigger_image); - p.drawImage((height_ - image.width()) / 2, (height_ - image.height()) / 2, - image); - p.end(); - - image = bigger_image; - } - - emit ImageLoaded(task.id, image); + ProcessTask(&task); } } -QImage AlbumCoverLoader::TryLoadImage(const QString &automatic, const QString &manual) { - QImage ret; - if (manual == kManuallyUnsetCover) - return ret; - if (!manual.isEmpty()) - ret.load(manual); - if (!automatic.isEmpty() && ret.isNull()) - ret.load(automatic); - return ret; +void AlbumCoverLoader::ProcessTask(Task *task) { + TryLoadResult result = TryLoadImage(*task); + if (result.started_async) { + // The image is being loaded from a remote URL, we'll carry on later + // when it's done + return; + } + + if (result.loaded_success) { + emit ImageLoaded(task->id, ScaleAndPad(result.image)); + return; + } + + NextState(task); +} + +void AlbumCoverLoader::NextState(Task* task) { + if (task->state == State_TryingManual) { + // Try the automatic one next + task->state = State_TryingAuto; + ProcessTask(task); + } else { + // Give up + emit ImageLoaded(task->id, QImage()); + } +} + +AlbumCoverLoader::TryLoadResult AlbumCoverLoader::TryLoadImage( + const Task& task) { + QString filename; + switch (task.state) { + case State_TryingAuto: filename = task.art_automatic; break; + case State_TryingManual: filename = task.art_manual; break; + } + + if (filename == kManuallyUnsetCover) + return TryLoadResult(false, true, QImage()); + + if (filename.toLower().startsWith("http://")) { + network_->Get(QUrl(filename), this, "RemoteFetchFinished", task.id, true); + + remote_tasks_.insert(task.id, task); + return TryLoadResult(true, false, QImage()); + } + + QImage image(filename); + return TryLoadResult(false, !image.isNull(), image); +} + +void AlbumCoverLoader::RemoteFetchFinished(quint64 id, QNetworkReply* reply) { + reply->deleteLater(); + Task task = remote_tasks_.take(id); + + if (reply->error() == QNetworkReply::NoError) { + // Try to load the image + QImage image; + if (image.load(reply, 0)) { + emit ImageLoaded(task.id, ScaleAndPad(image)); + return; + } + } + + NextState(&task); +} + +QImage AlbumCoverLoader::ScaleAndPad(const QImage &image) const { + if (image.isNull()) + return image; + + // Scale the image down + QImage copy = image.scaled(QSize(height_, height_), + Qt::KeepAspectRatio, Qt::SmoothTransformation); + + // Pad the image to height_ x height_ + QImage bigger_image(height_, height_, QImage::Format_ARGB32); + bigger_image.fill(0); + + QPainter p(&bigger_image); + p.drawImage((height_ - copy.width()) / 2, (height_ - copy.height()) / 2, + copy); + p.end(); + + return bigger_image; } QPixmap AlbumCoverLoader::TryLoadPixmap(const QString &automatic, const QString &manual) { diff --git a/src/albumcoverloader.h b/src/albumcoverloader.h index b1e882ec1..65a17c710 100644 --- a/src/albumcoverloader.h +++ b/src/albumcoverloader.h @@ -24,11 +24,16 @@ #include #include +class NetworkAccessManager; +class QNetworkReply; + class AlbumCoverLoader : public QObject { Q_OBJECT public: AlbumCoverLoader(QObject* parent = 0); + + void SetNetwork(NetworkAccessManager* network) { network_ = network; } void Stop() { stop_requested_ = true; } @@ -39,7 +44,6 @@ class AlbumCoverLoader : public QObject { void Clear(); - static QImage TryLoadImage(const QString& automatic, const QString& manual); static QPixmap TryLoadPixmap(const QString& automatic, const QString& manual); static const char* kManuallyUnsetCover; @@ -49,21 +53,45 @@ class AlbumCoverLoader : public QObject { private slots: void ProcessTasks(); + void RemoteFetchFinished(quint64 id, QNetworkReply* reply); private: + enum State { + State_TryingManual, + State_TryingAuto, + }; + struct Task { quint64 id; QString art_automatic; QString art_manual; + State state; }; + struct TryLoadResult { + TryLoadResult(bool async, bool success, const QImage i) + : started_async(async), loaded_success(success), image(i) {} + + bool started_async; + bool loaded_success; + QImage image; + }; + + void ProcessTask(Task* task); + void NextState(Task* task); + TryLoadResult TryLoadImage(const Task& task); + QImage ScaleAndPad(const QImage& image) const; + bool stop_requested_; int height_; QMutex mutex_; QQueue tasks_; + QMap remote_tasks_; quint64 next_id_; + + NetworkAccessManager* network_; }; #endif // ALBUMCOVERLOADER_H diff --git a/src/albumcovermanager.cpp b/src/albumcovermanager.cpp index a0c8a5613..158c73640 100644 --- a/src/albumcovermanager.cpp +++ b/src/albumcovermanager.cpp @@ -35,11 +35,12 @@ const char* AlbumCoverManager::kSettingsGroup = "CoverManager"; -AlbumCoverManager::AlbumCoverManager(QNetworkAccessManager* network, +AlbumCoverManager::AlbumCoverManager(NetworkAccessManager* network, LibraryBackend* backend, QWidget *parent) : QDialog(parent), constructed_(false), backend_(backend), + network_(network), cover_loader_(new BackgroundThreadImplementation(this)), cover_fetcher_(new AlbumCoverFetcher(network, this)), artist_icon_(":/artist.png"), @@ -117,6 +118,7 @@ void AlbumCoverManager::Init() { } void AlbumCoverManager::CoverLoaderInitialised() { + cover_loader_->Worker()->SetNetwork(network_); connect(cover_loader_->Worker().get(), SIGNAL(ImageLoaded(quint64,QImage)), SLOT(CoverImageLoaded(quint64,QImage))); } diff --git a/src/albumcovermanager.h b/src/albumcovermanager.h index c7d54d705..d68dce8dd 100644 --- a/src/albumcovermanager.h +++ b/src/albumcovermanager.h @@ -28,13 +28,12 @@ class LibraryBackend; class AlbumCoverFetcher; - -class QNetworkAccessManager; +class NetworkAccessManager; class AlbumCoverManager : public QDialog { Q_OBJECT public: - AlbumCoverManager(QNetworkAccessManager* network, LibraryBackend* backend, + AlbumCoverManager(NetworkAccessManager* network, LibraryBackend* backend, QWidget *parent = 0); ~AlbumCoverManager(); @@ -100,6 +99,7 @@ class AlbumCoverManager : public QDialog { QAction* filter_with_covers_; QAction* filter_without_covers_; + NetworkAccessManager* network_; BackgroundThread* cover_loader_; QMap cover_loading_tasks_; diff --git a/src/lastfmservice.cpp b/src/lastfmservice.cpp index 1012dfbe1..32c253299 100644 --- a/src/lastfmservice.cpp +++ b/src/lastfmservice.cpp @@ -20,6 +20,7 @@ #include "lastfmstationdialog.h" #include "lastfmconfigdialog.h" #include "radiomodel.h" +#include "networkaccessmanager.h" #include @@ -59,7 +60,7 @@ LastFMService::LastFMService(RadioModel* parent) tag_list_(NULL), friends_list_(NULL), neighbours_list_(NULL), - network_(parent->network()) + network_(parent->network()->network()) { ReloadSettings(); diff --git a/src/lastfmservice.h b/src/lastfmservice.h index 26dd75d11..495e23f12 100644 --- a/src/lastfmservice.h +++ b/src/lastfmservice.h @@ -41,6 +41,7 @@ uint qHash(const lastfm::Track& track); #include class QAction; + class QNetworkAccessManager; class LastFMService : public RadioService { diff --git a/src/magnatuneservice.cpp b/src/magnatuneservice.cpp index b3f02dbf0..100032966 100644 --- a/src/magnatuneservice.cpp +++ b/src/magnatuneservice.cpp @@ -21,6 +21,7 @@ #include "librarymodel.h" #include "librarybackend.h" #include "libraryfilterwidget.h" +#include "networkaccessmanager.h" #include #include @@ -49,7 +50,7 @@ MagnatuneService::MagnatuneService(RadioModel* parent) library_model_(new LibraryModel(library_backend_, this)), library_sort_model_(new QSortFilterProxyModel(this)), total_song_count_(0), - network_(parent->network()) + network_(parent->network()->network()) { connect(library_backend_, SIGNAL(TotalSongCountUpdated(int)), SLOT(UpdateTotalSongCount(int))); diff --git a/src/main.cpp b/src/main.cpp index 7e76d0592..e970158be 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -30,14 +30,13 @@ #include "commandlineoptions.h" #include "engines/enginebase.h" #include "config.h" +#include "networkaccessmanager.h" #include #include #include #include #include -#include -#include #include @@ -98,6 +97,8 @@ int main(int argc, char *argv[]) { qRegisterMetaType("Engine::SimpleMetaBundle"); qRegisterMetaType("Equalizer::Params"); qRegisterMetaTypeStreamOperators("Equalizer::Params"); + qRegisterMetaType("const char*"); + qRegisterMetaType("QNetworkReply*"); lastfm::ws::ApiKey = LastFMService::kApiKey; @@ -135,11 +136,7 @@ int main(int argc, char *argv[]) { // Couldn't send the message so start anyway } - QNetworkAccessManager network; - QNetworkDiskCache network_cache; - network_cache.setCacheDirectory(QString("%1/.config/%2/networkcache/") - .arg(QDir::homePath(), QCoreApplication::organizationName())); - network.setCache(&network_cache); + NetworkAccessManager network; // MPRIS DBus interface. #ifdef Q_WS_X11 diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 59613cffa..6f85684bb 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -84,10 +84,10 @@ const char* MainWindow::kPlaylistFilterSpec = const char* MainWindow::kAllFilesFilterSpec = QT_TR_NOOP("All Files (*)"); -MainWindow::MainWindow(QNetworkAccessManager* network, Engine::Type engine, QWidget *parent) +MainWindow::MainWindow(NetworkAccessManager* network, Engine::Type engine, QWidget *parent) : QMainWindow(parent), tray_icon_(new SystemTrayIcon(this)), - osd_(new OSD(tray_icon_, this)), + osd_(new OSD(tray_icon_, network, this)), track_slider_(new TrackSlider(this)), playlist_sequence_(new PlaylistSequence(this)), edit_tag_dialog_(new EditTagDialog), diff --git a/src/mainwindow.h b/src/mainwindow.h index 7f48c8a6f..f609dbbf4 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -49,17 +49,16 @@ class Equalizer; class CommandlineOptions; class TranscodeDialog; class Database; +class NetworkAccessManager; class QSortFilterProxyModel; class SystemTrayIcon; -class QNetworkAccessManager; - class MainWindow : public QMainWindow { Q_OBJECT public: - MainWindow(QNetworkAccessManager* network, Engine::Type engine, QWidget *parent = 0); + MainWindow(NetworkAccessManager* network, Engine::Type engine, QWidget *parent = 0); ~MainWindow(); static const char* kSettingsGroup; diff --git a/src/networkaccessmanager.cpp b/src/networkaccessmanager.cpp new file mode 100644 index 000000000..770e770d1 --- /dev/null +++ b/src/networkaccessmanager.cpp @@ -0,0 +1,61 @@ +#include "networkaccessmanager.h" + +#include +#include +#include +#include +#include +#include + +#include + +NetworkAccessManager::NetworkAccessManager(QObject* parent) + : QObject(parent), + network_(new QNetworkAccessManager(this)), + cache_(new QNetworkDiskCache(this)) +{ + cache_->setCacheDirectory(QString("%1/.config/%2/networkcache/") + .arg(QDir::homePath(), QCoreApplication::organizationName())); + network_->setCache(cache_); +} + +void NetworkAccessManager::Get(const QUrl &url, QObject *receiver, + const char *slot, quint64 id, bool force_cache) { + QMetaObject::invokeMethod( + this, "RunGet", Qt::QueuedConnection, + Q_ARG(QUrl, url), Q_ARG(QObject*, receiver), + Q_ARG(const char*, slot), + Q_ARG(quint64, id), Q_ARG(bool, force_cache)); +} + +void NetworkAccessManager::RunGet(const QUrl &url, QObject *receiver, + const char *slot, quint64 id, bool force_cache) { + QNetworkRequest req(url); + req.setRawHeader("User-Agent", QString("%1 %2").arg( + QCoreApplication::applicationName(), + QCoreApplication::applicationVersion()).toUtf8()); + + if (force_cache) { + req.setAttribute(QNetworkRequest::CacheLoadControlAttribute, + QNetworkRequest::PreferCache); + } + + QNetworkReply* reply = network_->get(req); + connect(reply, SIGNAL(finished()), SLOT(RequestFinished())); + + Receiver r; + r.receiver = receiver; + r.slot = slot; + r.id = id; + + pending_replies_.insert(reply, r); +} + +void NetworkAccessManager::RequestFinished() { + QNetworkReply* reply = static_cast(sender()); + Receiver r = pending_replies_.take(reply); + + QMetaObject::invokeMethod(r.receiver, r.slot, + Q_ARG(quint64, r.id), + Q_ARG(QNetworkReply*, reply)); +} diff --git a/src/networkaccessmanager.h b/src/networkaccessmanager.h new file mode 100644 index 000000000..d7c57bc19 --- /dev/null +++ b/src/networkaccessmanager.h @@ -0,0 +1,45 @@ +#ifndef NETWORKACCESSMANAGER_H +#define NETWORKACCESSMANAGER_H + +#include +#include + +class QNetworkAccessManager; +class QNetworkDiskCache; +class QNetworkReply; +class QUrl; + +// It's like QNetworkAccessManager, but threadsafe, and sets our User-Agent +// on all requests +class NetworkAccessManager : public QObject { + Q_OBJECT + + public: + NetworkAccessManager(QObject* parent = 0); + + // Only use this from the main thread + QNetworkAccessManager* network() const { return network_; } + + // Thread-safe. slot should take (quint64, QNetworkReply*) + void Get(const QUrl& url, QObject* receiver, const char* slot, + quint64 id, bool force_cache = false); + + private slots: + void RunGet(const QUrl& url, QObject* receiver, const char* slot, + quint64 id, bool force_cache); + void RequestFinished(); + + private: + QNetworkAccessManager* network_; + QNetworkDiskCache* cache_; + + struct Receiver { + QObject* receiver; + const char* slot; + quint64 id; + }; + + QMap pending_replies_; +}; + +#endif // NETWORKACCESSMANAGER_H diff --git a/src/osd.cpp b/src/osd.cpp index 7c6374d96..0842b4487 100644 --- a/src/osd.cpp +++ b/src/osd.cpp @@ -23,7 +23,7 @@ const char* OSD::kSettingsGroup = "OSD"; -OSD::OSD(QSystemTrayIcon* tray_icon, QObject* parent) +OSD::OSD(QSystemTrayIcon* tray_icon, NetworkAccessManager* network, QObject* parent) : QObject(parent), tray_icon_(tray_icon), timeout_msec_(5000), @@ -32,8 +32,14 @@ OSD::OSD(QSystemTrayIcon* tray_icon, QObject* parent) show_art_(true), force_show_next_(false), ignore_next_stopped_(false), - pretty_popup_(new OSDPretty(OSDPretty::Mode_Popup)) + pretty_popup_(new OSDPretty(OSDPretty::Mode_Popup)), + network_(network), + cover_loader_(new BackgroundThreadImplementation(this)) { + cover_loader_->Start(); + + connect(cover_loader_, SIGNAL(Initialised()), SLOT(CoverLoaderInitialised())); + ReloadSettings(); Init(); } @@ -42,6 +48,12 @@ OSD::~OSD() { delete pretty_popup_; } +void OSD::CoverLoaderInitialised() { + cover_loader_->Worker()->SetNetwork(network_); + connect(cover_loader_->Worker().get(), SIGNAL(ImageLoaded(quint64,QImage)), + SLOT(AlbumArtLoaded(quint64,QImage))); +} + void OSD::ReloadSettings() { QSettings s; s.beginGroup(kSettingsGroup); @@ -72,8 +84,27 @@ void OSD::SongChanged(const Song &song) { if (song.track() > 0) message_parts << tr("track %1").arg(song.track()); - ShowMessage(summary, message_parts.join(", "), "notification-audio-play", - show_art_ ? song.GetBestImage() : QImage()); + WaitingForAlbumArt waiting; + waiting.icon = "notification-audio-play"; + waiting.summary = summary; + waiting.message = message_parts.join(", "); + + if (show_art_) { + quint64 id = cover_loader_->Worker()->LoadImageAsync( + song.art_automatic(), song.art_manual()); + waiting_for_album_art_.insert(id, waiting); + } else { + AlbumArtLoaded(waiting, QImage()); + } +} + +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); } void OSD::Paused() { diff --git a/src/osd.h b/src/osd.h index 43680e0d1..965d527b4 100644 --- a/src/osd.h +++ b/src/osd.h @@ -23,8 +23,11 @@ #include "engines/engine_fwd.h" #include "song.h" +#include "backgroundthread.h" +#include "albumcoverloader.h" class OSDPretty; +class NetworkAccessManager; class QDBusPendingCallWatcher; @@ -41,7 +44,7 @@ class OSD : public QObject { Q_OBJECT public: - OSD(QSystemTrayIcon* tray_icon, QObject* parent = 0); + OSD(QSystemTrayIcon* tray_icon, NetworkAccessManager* network, QObject* parent = 0); ~OSD(); static const char* kSettingsGroup; @@ -68,6 +71,12 @@ class OSD : public QObject { void VolumeChanged(int value); private: + struct WaitingForAlbumArt { + QString summary; + QString message; + QString icon; + }; + void ShowMessage(const QString& summary, const QString& message = QString(), const QString& icon = QString(), @@ -82,6 +91,9 @@ class OSD : public QObject { private slots: void CallFinished(QDBusPendingCallWatcher* watcher); + void CoverLoaderInitialised(); + void AlbumArtLoaded(quint64 id, const QImage& image); + void AlbumArtLoaded(const WaitingForAlbumArt info, const QImage& image); private: QSystemTrayIcon* tray_icon_; @@ -95,6 +107,10 @@ class OSD : public QObject { OSDPretty* pretty_popup_; + NetworkAccessManager* network_; + BackgroundThread* cover_loader_; + QMap waiting_for_album_art_; + #ifdef Q_OS_DARWIN class GrowlNotificationWrapper; GrowlNotificationWrapper* wrapper_; diff --git a/src/radiomodel.cpp b/src/radiomodel.cpp index 98faa755d..d2aad0865 100644 --- a/src/radiomodel.cpp +++ b/src/radiomodel.cpp @@ -28,7 +28,7 @@ QMap RadioModel::sServices; -RadioModel::RadioModel(Database* db, QNetworkAccessManager* network, QObject* parent) +RadioModel::RadioModel(Database* db, NetworkAccessManager* network, QObject* parent) : SimpleTreeModel(new RadioItem(this), parent), db_(db), merged_model_(new MergedProxyModel(this)), diff --git a/src/radiomodel.h b/src/radiomodel.h index 1a9e38a1a..440a5873a 100644 --- a/src/radiomodel.h +++ b/src/radiomodel.h @@ -22,8 +22,7 @@ #include "multiloadingindicator.h" #include "song.h" -class QNetworkAccessManager; - +class NetworkAccessManager; class RadioService; class LastFMService; class MergedProxyModel; @@ -33,7 +32,7 @@ class RadioModel : public SimpleTreeModel { Q_OBJECT public: - RadioModel(Database* db, QNetworkAccessManager* network, QObject* parent = 0); + RadioModel(Database* db, NetworkAccessManager* network, QObject* parent = 0); enum { Role_Type = Qt::UserRole + 1, @@ -59,7 +58,7 @@ class RadioModel : public SimpleTreeModel { Database* db() const { return db_; } MergedProxyModel* merged_model() const { return merged_model_; } - QNetworkAccessManager* network() const { return network_; } + NetworkAccessManager* network() const { return network_; } signals: void TaskStarted(MultiLoadingIndicator::TaskType); @@ -83,7 +82,7 @@ class RadioModel : public SimpleTreeModel { static QMap sServices; Database* db_; MergedProxyModel* merged_model_; - QNetworkAccessManager* network_; + NetworkAccessManager* network_; }; #endif // RADIOMODEL_H diff --git a/src/somafmservice.cpp b/src/somafmservice.cpp index 6c83c05d4..8dcc1a345 100644 --- a/src/somafmservice.cpp +++ b/src/somafmservice.cpp @@ -16,6 +16,7 @@ #include "somafmservice.h" #include "radiomodel.h" +#include "networkaccessmanager.h" #include #include @@ -36,7 +37,7 @@ SomaFMService::SomaFMService(RadioModel* parent) : RadioService(kServiceName, parent), root_(NULL), context_menu_(new QMenu), - network_(parent->network()) + network_(parent->network()->network()) { context_menu_->addAction(QIcon(":media-playback-start.png"), tr("Add to playlist"), this, SLOT(AddToPlaylist())); context_menu_->addSeparator(); diff --git a/src/song.cpp b/src/song.cpp index 263b07b96..bb70d6072 100644 --- a/src/song.cpp +++ b/src/song.cpp @@ -535,14 +535,3 @@ bool Song::Save() const { return ret; } - -QImage Song::GetBestImage() const { - if (!d->image_.isNull()) - return d->image_; - - QImage art(AlbumCoverLoader::TryLoadImage(d->art_automatic_, d->art_manual_)); - if (!art.isNull()) - return art; - - return QImage(":/nocover.png"); -} diff --git a/src/song.h b/src/song.h index 42a81ea41..d72110df9 100644 --- a/src/song.h +++ b/src/song.h @@ -133,12 +133,6 @@ class Song { QString PrettyTitleWithArtist() const; QString PrettyLength() const; - // Loads and returns some album art for the song. Tries, in this order: - // 1) An image set explicitly with set_image (eg. last.fm radio) - // 2) An image set by the user with set_art_manual - // 3) An image found by the library scanner - QImage GetBestImage() const; - // Setters bool IsEditable() const { return d->valid_ && !d->filename_.isNull(); } bool Save() const;