Adding support for subsonic cover art download
This commit is contained in:
parent
9252925a56
commit
e4efde900a
@ -35,13 +35,15 @@
|
||||
#include "core/utilities.h"
|
||||
#include "internet/core/internetmodel.h"
|
||||
#include "internet/spotify/spotifyservice.h"
|
||||
#include "internet/subsonic/subsonicservice.h"
|
||||
|
||||
AlbumCoverLoader::AlbumCoverLoader(QObject* parent)
|
||||
: QObject(parent),
|
||||
stop_requested_(false),
|
||||
next_id_(1),
|
||||
network_(new NetworkAccessManager(this)),
|
||||
connected_spotify_(false) {}
|
||||
connected_spotify_(false),
|
||||
connected_subsonic_(false) {}
|
||||
|
||||
QString AlbumCoverLoader::ImageCacheDir() {
|
||||
return Utilities::GetConfigPath(Utilities::Path_AlbumCovers);
|
||||
@ -196,6 +198,26 @@ AlbumCoverLoader::TryLoadResult AlbumCoverLoader::TryLoadImage(
|
||||
QMetaObject::invokeMethod(spotify, "LoadImage", Qt::QueuedConnection,
|
||||
Q_ARG(QString, id));
|
||||
return TryLoadResult(true, false, QImage());
|
||||
} else if (filename.toLower().startsWith("subsonic://image/")) {
|
||||
// HACK: we should add generic image URL handlers
|
||||
SubsonicService* subsonic = InternetModel::Service<SubsonicService>();
|
||||
|
||||
if (!connected_subsonic_) {
|
||||
connect(subsonic, SIGNAL(ImageLoaded(QString, QImage)),
|
||||
SLOT(SubsonicImageLoaded(QString, QImage)));
|
||||
connected_subsonic_ = true;
|
||||
}
|
||||
|
||||
QString id = QUrl(filename).path();
|
||||
if (id.startsWith('/')) {
|
||||
id.remove(0, 1);
|
||||
}
|
||||
remote_subsonic_tasks_.insert(id, task);
|
||||
|
||||
// Need to schedule this in the subsonic service's thread
|
||||
QMetaObject::invokeMethod(subsonic, "LoadImage", Qt::QueuedConnection,
|
||||
Q_ARG(QString, id));
|
||||
return TryLoadResult(true, false, QImage());
|
||||
}
|
||||
|
||||
QImage image(filename);
|
||||
@ -214,6 +236,16 @@ void AlbumCoverLoader::SpotifyImageLoaded(const QString& id,
|
||||
emit ImageLoaded(task.id, scaled, image);
|
||||
}
|
||||
|
||||
void AlbumCoverLoader::SubsonicImageLoaded(const QString& id,
|
||||
const QImage& image) {
|
||||
if (!remote_subsonic_tasks_.contains(id)) return;
|
||||
|
||||
Task task = remote_subsonic_tasks_.take(id);
|
||||
QImage scaled = ScaleAndPad(task.options, image);
|
||||
emit ImageLoaded(task.id, scaled);
|
||||
emit ImageLoaded(task.id, scaled, image);
|
||||
}
|
||||
|
||||
void AlbumCoverLoader::RemoteFetchFinished(QNetworkReply* reply) {
|
||||
reply->deleteLater();
|
||||
|
||||
|
@ -67,6 +67,7 @@ class AlbumCoverLoader : public QObject {
|
||||
void ProcessTasks();
|
||||
void RemoteFetchFinished(QNetworkReply* reply);
|
||||
void SpotifyImageLoaded(const QString& url, const QImage& image);
|
||||
void SubsonicImageLoaded(const QString& url, const QImage& image);
|
||||
|
||||
protected:
|
||||
enum State { State_TryingManual, State_TryingAuto, };
|
||||
@ -104,11 +105,12 @@ class AlbumCoverLoader : public QObject {
|
||||
QQueue<Task> tasks_;
|
||||
QMap<QNetworkReply*, Task> remote_tasks_;
|
||||
QMap<QString, Task> remote_spotify_tasks_;
|
||||
QMap<QString, Task> remote_subsonic_tasks_;
|
||||
quint64 next_id_;
|
||||
|
||||
NetworkAccessManager* network_;
|
||||
|
||||
bool connected_spotify_;
|
||||
bool connected_spotify_, connected_subsonic_;
|
||||
|
||||
static const int kMaxRedirects = 3;
|
||||
};
|
||||
|
@ -490,7 +490,7 @@ void SubsonicLibraryScanner::OnGetAlbumListFinished(QNetworkReply* reply,
|
||||
}
|
||||
}
|
||||
|
||||
void SubsonicLibraryScanner::OnGetAlbumFinished(QNetworkReply* reply) {
|
||||
void SubsonicLibraryScanner::OnGetAlbumFinished(QNetworkReply* reply, QString albumid) {
|
||||
reply->deleteLater();
|
||||
pending_requests_.remove(reply);
|
||||
|
||||
@ -534,6 +534,7 @@ void SubsonicLibraryScanner::OnGetAlbumFinished(QNetworkReply* reply) {
|
||||
song.set_bitrate(reader.attributes().value("bitRate").toString().toInt());
|
||||
song.set_year(reader.attributes().value("year").toString().toInt());
|
||||
song.set_genre(reader.attributes().value("genre").toString());
|
||||
song.set_art_automatic(QString("subsonic://image/%1").arg(albumid));
|
||||
qint64 length = reader.attributes().value("duration").toString().toInt();
|
||||
length *= kNsecPerSec;
|
||||
song.set_length_nanosec(length);
|
||||
@ -566,6 +567,15 @@ void SubsonicLibraryScanner::OnGetAlbumFinished(QNetworkReply* reply) {
|
||||
}
|
||||
}
|
||||
|
||||
void SubsonicLibraryScanner::OnGetAlbumCoverFinished(QNetworkReply* reply, QString albumid) {
|
||||
reply->deleteLater();
|
||||
pending_requests_.remove(reply);
|
||||
|
||||
QByteArray image = reply->readAll();
|
||||
|
||||
service_->emitImageLoaded(albumid, QImage::fromData(image));
|
||||
}
|
||||
|
||||
void SubsonicLibraryScanner::GetAlbumList(int offset) {
|
||||
QUrl url = service_->BuildRequestUrl("getAlbumList2");
|
||||
url.addQueryItem("type", "alphabeticalByName");
|
||||
@ -576,6 +586,24 @@ void SubsonicLibraryScanner::GetAlbumList(int offset) {
|
||||
SLOT(OnGetAlbumListFinished(QNetworkReply*, int)), reply, offset);
|
||||
}
|
||||
|
||||
void SubsonicLibraryScanner::GetAlbumCover(const QString& id) {
|
||||
QUrl url = service_->BuildRequestUrl("getCoverArt");
|
||||
url.addQueryItem("id", id);
|
||||
url.addQueryItem("size", "1024");
|
||||
QNetworkReply* reply = service_->Send(url);
|
||||
NewClosure(reply, SIGNAL(finished()), this,
|
||||
SLOT(OnGetAlbumCoverFinished(QNetworkReply*,QString)), reply, id);
|
||||
pending_requests_.insert(reply);
|
||||
}
|
||||
|
||||
void SubsonicService::LoadImage(const QString& id) {
|
||||
scanner_->GetAlbumCover(id);
|
||||
}
|
||||
|
||||
void SubsonicService::emitImageLoaded(const QString& id, const QImage& image) {
|
||||
emit ImageLoaded(id, image);
|
||||
}
|
||||
|
||||
void SubsonicLibraryScanner::GetAlbum(const QString& id) {
|
||||
QUrl url = service_->BuildRequestUrl("getAlbum");
|
||||
url.addQueryItem("id", id);
|
||||
@ -584,7 +612,7 @@ void SubsonicLibraryScanner::GetAlbum(const QString& id) {
|
||||
}
|
||||
QNetworkReply* reply = service_->Send(url);
|
||||
NewClosure(reply, SIGNAL(finished()), this,
|
||||
SLOT(OnGetAlbumFinished(QNetworkReply*)), reply);
|
||||
SLOT(OnGetAlbumFinished(QNetworkReply*, QString)), reply, id);
|
||||
pending_requests_.insert(reply);
|
||||
}
|
||||
|
||||
|
@ -101,6 +101,9 @@ class SubsonicService : public InternetService {
|
||||
|
||||
LoginState login_state() const { return login_state_; }
|
||||
|
||||
Q_INVOKABLE void LoadImage(const QString& id);
|
||||
void emitImageLoaded(const QString& id, const QImage& image);
|
||||
|
||||
// Subsonic API methods
|
||||
void Ping();
|
||||
|
||||
@ -125,6 +128,7 @@ class SubsonicService : public InternetService {
|
||||
|
||||
signals:
|
||||
void LoginStateChanged(SubsonicService::LoginState newstate);
|
||||
void ImageLoaded(const QString& id, const QImage& image);
|
||||
|
||||
private:
|
||||
void EnsureMenuCreated();
|
||||
@ -182,6 +186,8 @@ class SubsonicLibraryScanner : public QObject {
|
||||
static const int kAlbumChunkSize;
|
||||
static const int kConcurrentRequests;
|
||||
|
||||
void GetAlbumCover(const QString& id);
|
||||
|
||||
signals:
|
||||
void ScanFinished();
|
||||
|
||||
@ -189,7 +195,8 @@ signals:
|
||||
// Step 1: use getAlbumList2 type=alphabeticalByName to list all albums
|
||||
void OnGetAlbumListFinished(QNetworkReply* reply, int offset);
|
||||
// Step 2: use getAlbum id=? to list all songs for each album
|
||||
void OnGetAlbumFinished(QNetworkReply* reply);
|
||||
void OnGetAlbumFinished(QNetworkReply* reply, QString albumid);
|
||||
void OnGetAlbumCoverFinished(QNetworkReply* reply, QString albumid);
|
||||
|
||||
private:
|
||||
void GetAlbumList(int offset);
|
||||
|
Loading…
x
Reference in New Issue
Block a user