mirror of
https://github.com/clementine-player/Clementine
synced 2025-02-07 06:35:15 +01:00
Fix some style issues in subsonic.
This commit is contained in:
parent
fe2fb788d3
commit
0d743a2065
@ -1,27 +1,29 @@
|
||||
#include "subsonicurlhandler.h"
|
||||
#include "subsonicservice.h"
|
||||
#include "internetmodel.h"
|
||||
#include "core/application.h"
|
||||
#include "core/logging.h"
|
||||
#include "core/player.h"
|
||||
#include "core/utilities.h"
|
||||
#include "ui/iconloader.h"
|
||||
#include "library/librarybackend.h"
|
||||
#include "library/libraryfilterwidget.h"
|
||||
#include "core/mergedproxymodel.h"
|
||||
#include "core/database.h"
|
||||
#include "core/closure.h"
|
||||
#include "core/taskmanager.h"
|
||||
#include "globalsearch/globalsearch.h"
|
||||
#include "globalsearch/librarysearchprovider.h"
|
||||
|
||||
#include <QMenu>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkReply>
|
||||
#include <QNetworkCookieJar>
|
||||
#include <QNetworkReply>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QSslConfiguration>
|
||||
#include <QXmlStreamReader>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QMenu>
|
||||
|
||||
#include "core/application.h"
|
||||
#include "core/closure.h"
|
||||
#include "core/database.h"
|
||||
#include "core/logging.h"
|
||||
#include "core/mergedproxymodel.h"
|
||||
#include "core/player.h"
|
||||
#include "core/taskmanager.h"
|
||||
#include "core/timeconstants.h"
|
||||
#include "core/utilities.h"
|
||||
#include "globalsearch/globalsearch.h"
|
||||
#include "globalsearch/librarysearchprovider.h"
|
||||
#include "internet/internetmodel.h"
|
||||
#include "internet/subsonicurlhandler.h"
|
||||
#include "library/librarybackend.h"
|
||||
#include "library/libraryfilterwidget.h"
|
||||
#include "ui/iconloader.h"
|
||||
|
||||
const char* SubsonicService::kServiceName = "Subsonic";
|
||||
const char* SubsonicService::kSettingsGroup = "Subsonic";
|
||||
@ -31,7 +33,7 @@ const char* SubsonicService::kApiClientName = "Clementine";
|
||||
const char* SubsonicService::kSongsTable = "subsonic_songs";
|
||||
const char* SubsonicService::kFtsTable = "subsonic_songs_fts";
|
||||
|
||||
SubsonicService::SubsonicService(Application* app, InternetModel *parent)
|
||||
SubsonicService::SubsonicService(Application* app, InternetModel* parent)
|
||||
: InternetService(kServiceName, app, parent, parent),
|
||||
network_(new QNetworkAccessManager(this)),
|
||||
url_handler_(new SubsonicUrlHandler(this, this)),
|
||||
@ -44,8 +46,7 @@ SubsonicService::SubsonicService(Application* app, InternetModel *parent)
|
||||
library_filter_(NULL),
|
||||
library_sort_model_(new QSortFilterProxyModel(this)),
|
||||
total_song_count_(0),
|
||||
login_state_(LoginState_OtherError)
|
||||
{
|
||||
login_state_(LoginState_OtherError) {
|
||||
app_->player()->RegisterUrlHandler(url_handler_);
|
||||
|
||||
connect(scanner_, SIGNAL(ScanFinished()),
|
||||
@ -77,14 +78,19 @@ SubsonicService::SubsonicService(Application* app, InternetModel *parent)
|
||||
library_sort_model_->sort(0);
|
||||
|
||||
connect(this, SIGNAL(LoginStateChanged(SubsonicService::LoginState)),
|
||||
SLOT(onLoginStateChanged(SubsonicService::LoginState)));
|
||||
SLOT(OnLoginStateChanged(SubsonicService::LoginState)));
|
||||
|
||||
context_menu_ = new QMenu;
|
||||
context_menu_->addActions(GetPlaylistActions());
|
||||
context_menu_->addSeparator();
|
||||
context_menu_->addAction(IconLoader::Load("view-refresh"), tr("Refresh catalogue"), this, SLOT(ReloadDatabase()));
|
||||
QAction* config_action = context_menu_->addAction(IconLoader::Load("configure"),
|
||||
tr("Configure Subsonic..."), this, SLOT(ShowConfig()));
|
||||
context_menu_->addAction(
|
||||
IconLoader::Load("view-refresh"),
|
||||
tr("Refresh catalogue"),
|
||||
this, SLOT(ReloadDatabase()));
|
||||
QAction* config_action = context_menu_->addAction(
|
||||
IconLoader::Load("configure"),
|
||||
tr("Configure Subsonic..."),
|
||||
this, SLOT(ShowConfig()));
|
||||
context_menu_->addSeparator();
|
||||
context_menu_->addMenu(library_filter_->menu());
|
||||
|
||||
@ -98,38 +104,33 @@ SubsonicService::SubsonicService(Application* app, InternetModel *parent)
|
||||
true, app_, this));
|
||||
}
|
||||
|
||||
SubsonicService::~SubsonicService()
|
||||
{
|
||||
SubsonicService::~SubsonicService() {
|
||||
}
|
||||
|
||||
QStandardItem* SubsonicService::CreateRootItem()
|
||||
{
|
||||
QStandardItem* SubsonicService::CreateRootItem() {
|
||||
root_ = new QStandardItem(QIcon(":providers/subsonic.png"), kServiceName);
|
||||
root_->setData(true, InternetModel::Role_CanLazyLoad);
|
||||
return root_;
|
||||
}
|
||||
|
||||
void SubsonicService::LazyPopulate(QStandardItem *item)
|
||||
{
|
||||
switch (item->data(InternetModel::Role_Type).toInt())
|
||||
{
|
||||
case InternetModel::Type_Service:
|
||||
library_model_->Init();
|
||||
if (login_state() != LoginState_Loggedin) {
|
||||
ShowConfig();
|
||||
} else if (total_song_count_ == 0 && !load_database_task_id_) {
|
||||
ReloadDatabase();
|
||||
}
|
||||
model()->merged_model()->AddSubModel(item->index(), library_sort_model_);
|
||||
break;
|
||||
void SubsonicService::LazyPopulate(QStandardItem* item) {
|
||||
switch (item->data(InternetModel::Role_Type).toInt()) {
|
||||
case InternetModel::Type_Service:
|
||||
library_model_->Init();
|
||||
if (login_state() != LoginState_Loggedin) {
|
||||
ShowConfig();
|
||||
} else if (total_song_count_ == 0 && !load_database_task_id_) {
|
||||
ReloadDatabase();
|
||||
}
|
||||
model()->merged_model()->AddSubModel(item->index(), library_sort_model_);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SubsonicService::ShowContextMenu(const QPoint &global_pos)
|
||||
{
|
||||
void SubsonicService::ShowContextMenu(const QPoint& global_pos) {
|
||||
const bool is_valid = model()->current_index().model() == library_sort_model_;
|
||||
|
||||
GetAppendToPlaylistAction()->setEnabled(is_valid);
|
||||
@ -138,13 +139,11 @@ void SubsonicService::ShowContextMenu(const QPoint &global_pos)
|
||||
context_menu_->popup(global_pos);
|
||||
}
|
||||
|
||||
QWidget* SubsonicService::HeaderWidget() const
|
||||
{
|
||||
QWidget* SubsonicService::HeaderWidget() const {
|
||||
return library_filter_;
|
||||
}
|
||||
|
||||
void SubsonicService::ReloadSettings()
|
||||
{
|
||||
void SubsonicService::ReloadSettings() {
|
||||
QSettings s;
|
||||
s.beginGroup(kSettingsGroup);
|
||||
|
||||
@ -155,8 +154,7 @@ void SubsonicService::ReloadSettings()
|
||||
Login();
|
||||
}
|
||||
|
||||
void SubsonicService::Login()
|
||||
{
|
||||
void SubsonicService::Login() {
|
||||
// Forget session ID
|
||||
network_->setCookieJar(new QNetworkCookieJar(network_));
|
||||
// Forget login state whilst waiting
|
||||
@ -165,24 +163,22 @@ void SubsonicService::Login()
|
||||
Ping();
|
||||
}
|
||||
|
||||
void SubsonicService::Login(const QString &server, const QString &username, const QString &password)
|
||||
{
|
||||
server_ = QString(server);
|
||||
username_ = QString(username);
|
||||
password_ = QString(password);
|
||||
void SubsonicService::Login(
|
||||
const QString& server, const QString& username, const QString& password) {
|
||||
server_ = server;
|
||||
username_ = username;
|
||||
password_ = password;
|
||||
Login();
|
||||
}
|
||||
|
||||
void SubsonicService::Ping()
|
||||
{
|
||||
void SubsonicService::Ping() {
|
||||
QNetworkReply* reply = Send(BuildRequestUrl("ping"));
|
||||
NewClosure(reply, SIGNAL(finished()),
|
||||
this, SLOT(onPingFinished(QNetworkReply*)),
|
||||
this, SLOT(OnPingFinished(QNetworkReply*)),
|
||||
reply);
|
||||
}
|
||||
|
||||
QUrl SubsonicService::BuildRequestUrl(const QString &view)
|
||||
{
|
||||
QUrl SubsonicService::BuildRequestUrl(const QString& view) const {
|
||||
QUrl url(server_ + "rest/" + view + ".view");
|
||||
url.addQueryItem("v", kApiVersion);
|
||||
url.addQueryItem("c", kApiClientName);
|
||||
@ -191,8 +187,7 @@ QUrl SubsonicService::BuildRequestUrl(const QString &view)
|
||||
return url;
|
||||
}
|
||||
|
||||
QNetworkReply* SubsonicService::Send(const QUrl &url)
|
||||
{
|
||||
QNetworkReply* SubsonicService::Send(const QUrl& url) {
|
||||
QNetworkRequest request(url);
|
||||
// Don't try and check the authenticity of the SSL certificate - it'll almost
|
||||
// certainly be self-signed.
|
||||
@ -203,20 +198,19 @@ QNetworkReply* SubsonicService::Send(const QUrl &url)
|
||||
return reply;
|
||||
}
|
||||
|
||||
void SubsonicService::UpdateTotalSongCount(int count)
|
||||
{
|
||||
void SubsonicService::UpdateTotalSongCount(int count) {
|
||||
total_song_count_ = count;
|
||||
}
|
||||
|
||||
void SubsonicService::ReloadDatabase()
|
||||
{
|
||||
if (!load_database_task_id_)
|
||||
load_database_task_id_ = app_->task_manager()->StartTask(tr("Fetching Subsonic library"));
|
||||
void SubsonicService::ReloadDatabase() {
|
||||
if (!load_database_task_id_) {
|
||||
load_database_task_id_ = app_->task_manager()->StartTask(
|
||||
tr("Fetching Subsonic library"));
|
||||
}
|
||||
scanner_->Scan();
|
||||
}
|
||||
|
||||
void SubsonicService::ReloadDatabaseFinished()
|
||||
{
|
||||
void SubsonicService::ReloadDatabaseFinished() {
|
||||
app_->task_manager()->SetTaskFinished(load_database_task_id_);
|
||||
load_database_task_id_ = 0;
|
||||
|
||||
@ -225,57 +219,48 @@ void SubsonicService::ReloadDatabaseFinished()
|
||||
library_model_->Reset();
|
||||
}
|
||||
|
||||
void SubsonicService::onLoginStateChanged(SubsonicService::LoginState newstate)
|
||||
{
|
||||
void SubsonicService::OnLoginStateChanged(SubsonicService::LoginState newstate) {
|
||||
// TODO: library refresh logic?
|
||||
}
|
||||
|
||||
void SubsonicService::onPingFinished(QNetworkReply *reply)
|
||||
{
|
||||
void SubsonicService::OnPingFinished(QNetworkReply* reply) {
|
||||
reply->deleteLater();
|
||||
|
||||
if (reply->error() != QNetworkReply::NoError)
|
||||
{
|
||||
if (reply->error() != QNetworkReply::NoError) {
|
||||
login_state_ = LoginState_BadServer;
|
||||
qLog(Error) << "Failed to connect ("
|
||||
<< Utilities::EnumToString(QNetworkReply::staticMetaObject, "NetworkError", reply->error())
|
||||
<< "):" << reply->errorString();
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
QXmlStreamReader reader(reply);
|
||||
reader.readNextStartElement();
|
||||
QStringRef status = reader.attributes().value("status");
|
||||
if (status == "ok")
|
||||
{
|
||||
if (status == "ok") {
|
||||
login_state_ = LoginState_Loggedin;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
reader.readNextStartElement();
|
||||
int error = reader.attributes().value("code").toString().toInt();
|
||||
qLog(Error) << "Subsonic error ("
|
||||
<< Utilities::EnumToString(SubsonicService::staticMetaObject, "ApiError", error)
|
||||
<< "):" << reader.attributes().value("message").toString();
|
||||
switch (error)
|
||||
{
|
||||
// "Parameter missing" for "ping" is always blank username or password
|
||||
case ApiError_ParameterMissing:
|
||||
case ApiError_BadCredentials:
|
||||
login_state_ = LoginState_BadCredentials;
|
||||
break;
|
||||
case ApiError_OutdatedClient:
|
||||
login_state_ = LoginState_OutdatedClient;
|
||||
break;
|
||||
case ApiError_OutdatedServer:
|
||||
login_state_ = LoginState_OutdatedServer;
|
||||
break;
|
||||
case ApiError_Unlicensed:
|
||||
login_state_ = LoginState_Unlicensed;
|
||||
break;
|
||||
default:
|
||||
login_state_ = LoginState_OtherError;
|
||||
break;
|
||||
switch (error) {
|
||||
// "Parameter missing" for "ping" is always blank username or password
|
||||
case ApiError_ParameterMissing:
|
||||
case ApiError_BadCredentials:
|
||||
login_state_ = LoginState_BadCredentials;
|
||||
break;
|
||||
case ApiError_OutdatedClient:
|
||||
login_state_ = LoginState_OutdatedClient;
|
||||
break;
|
||||
case ApiError_OutdatedServer:
|
||||
login_state_ = LoginState_OutdatedServer;
|
||||
break;
|
||||
case ApiError_Unlicensed:
|
||||
login_state_ = LoginState_Unlicensed;
|
||||
break;
|
||||
default:
|
||||
login_state_ = LoginState_OtherError;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -284,8 +269,7 @@ void SubsonicService::onPingFinished(QNetworkReply *reply)
|
||||
emit LoginStateChanged(login_state_);
|
||||
}
|
||||
|
||||
void SubsonicService::ShowConfig()
|
||||
{
|
||||
void SubsonicService::ShowConfig() {
|
||||
app_->OpenSettingsDialogAtPage(SettingsDialog::Page_Subsonic);
|
||||
}
|
||||
|
||||
@ -293,21 +277,20 @@ void SubsonicService::ShowConfig()
|
||||
const int SubsonicLibraryScanner::kAlbumChunkSize = 500;
|
||||
const int SubsonicLibraryScanner::kConcurrentRequests = 8;
|
||||
|
||||
SubsonicLibraryScanner::SubsonicLibraryScanner(SubsonicService* service, QObject* parent)
|
||||
SubsonicLibraryScanner::SubsonicLibraryScanner(
|
||||
SubsonicService* service, QObject* parent)
|
||||
: QObject(parent),
|
||||
service_(service),
|
||||
scanning_(false)
|
||||
{
|
||||
scanning_(false) {
|
||||
}
|
||||
|
||||
SubsonicLibraryScanner::~SubsonicLibraryScanner()
|
||||
{
|
||||
SubsonicLibraryScanner::~SubsonicLibraryScanner() {
|
||||
}
|
||||
|
||||
void SubsonicLibraryScanner::Scan()
|
||||
{
|
||||
if (scanning_)
|
||||
void SubsonicLibraryScanner::Scan() {
|
||||
if (scanning_) {
|
||||
return;
|
||||
}
|
||||
|
||||
album_queue_.clear();
|
||||
pending_requests_.clear();
|
||||
@ -316,8 +299,8 @@ void SubsonicLibraryScanner::Scan()
|
||||
GetAlbumList(0);
|
||||
}
|
||||
|
||||
void SubsonicLibraryScanner::onGetAlbumListFinished(QNetworkReply *reply, int offset)
|
||||
{
|
||||
void SubsonicLibraryScanner::OnGetAlbumListFinished(
|
||||
QNetworkReply* reply, int offset) {
|
||||
reply->deleteLater();
|
||||
|
||||
QXmlStreamReader reader(reply);
|
||||
@ -353,8 +336,7 @@ void SubsonicLibraryScanner::onGetAlbumListFinished(QNetworkReply *reply, int of
|
||||
}
|
||||
}
|
||||
|
||||
void SubsonicLibraryScanner::onGetAlbumFinished(QNetworkReply *reply)
|
||||
{
|
||||
void SubsonicLibraryScanner::OnGetAlbumFinished(QNetworkReply* reply) {
|
||||
reply->deleteLater();
|
||||
pending_requests_.remove(reply);
|
||||
|
||||
@ -385,7 +367,7 @@ void SubsonicLibraryScanner::onGetAlbumFinished(QNetworkReply *reply)
|
||||
song.set_year(reader.attributes().value("year").toString().toInt());
|
||||
song.set_genre(reader.attributes().value("genre").toString());
|
||||
qint64 length = reader.attributes().value("duration").toString().toInt();
|
||||
length *= 1000000000;
|
||||
length *= kNsecPerSec;
|
||||
song.set_length_nanosec(length);
|
||||
QUrl url = QUrl(QString("subsonic://%1").arg(id));
|
||||
song.set_url(url);
|
||||
@ -399,8 +381,9 @@ void SubsonicLibraryScanner::onGetAlbumFinished(QNetworkReply *reply)
|
||||
}
|
||||
|
||||
// Start the next request if albums remain
|
||||
if (!album_queue_.empty())
|
||||
if (!album_queue_.empty()) {
|
||||
GetAlbum(album_queue_.dequeue());
|
||||
}
|
||||
|
||||
// If this was the last response, we're done!
|
||||
if (album_queue_.empty() && pending_requests_.empty()) {
|
||||
@ -409,25 +392,23 @@ void SubsonicLibraryScanner::onGetAlbumFinished(QNetworkReply *reply)
|
||||
}
|
||||
}
|
||||
|
||||
void SubsonicLibraryScanner::GetAlbumList(int offset)
|
||||
{
|
||||
void SubsonicLibraryScanner::GetAlbumList(int offset) {
|
||||
QUrl url = service_->BuildRequestUrl("getAlbumList2");
|
||||
url.addQueryItem("type", "alphabeticalByName");
|
||||
url.addQueryItem("size", QString::number(kAlbumChunkSize));
|
||||
url.addQueryItem("offset", QString::number(offset));
|
||||
QNetworkReply* reply = service_->Send(url);
|
||||
NewClosure(reply, SIGNAL(finished()),
|
||||
this, SLOT(onGetAlbumListFinished(QNetworkReply*,int)),
|
||||
this, SLOT(OnGetAlbumListFinished(QNetworkReply*,int)),
|
||||
reply, offset);
|
||||
}
|
||||
|
||||
void SubsonicLibraryScanner::GetAlbum(QString id)
|
||||
{
|
||||
void SubsonicLibraryScanner::GetAlbum(const QString& id) {
|
||||
QUrl url = service_->BuildRequestUrl("getAlbum");
|
||||
url.addQueryItem("id", id);
|
||||
QNetworkReply* reply = service_->Send(url);
|
||||
NewClosure(reply, SIGNAL(finished()),
|
||||
this, SLOT(onGetAlbumFinished(QNetworkReply*)),
|
||||
this, SLOT(OnGetAlbumFinished(QNetworkReply*)),
|
||||
reply);
|
||||
pending_requests_.insert(reply);
|
||||
}
|
||||
|
@ -1,15 +1,15 @@
|
||||
#ifndef SUBSONICSERVICE_H
|
||||
#define SUBSONICSERVICE_H
|
||||
|
||||
#include "internetmodel.h"
|
||||
#include "internetservice.h"
|
||||
|
||||
#include <QQueue>
|
||||
|
||||
#include "internet/internetmodel.h"
|
||||
#include "internet/internetservice.h"
|
||||
|
||||
class QNetworkAccessManager;
|
||||
class QXmlStreamReader;
|
||||
class QSortFilterProxyModel;
|
||||
class QNetworkReply;
|
||||
class QSortFilterProxyModel;
|
||||
class QXmlStreamReader;
|
||||
|
||||
class SubsonicUrlHandler;
|
||||
class SubsonicLibraryScanner;
|
||||
@ -65,15 +65,16 @@ class SubsonicService : public InternetService
|
||||
void ReloadSettings();
|
||||
|
||||
void Login();
|
||||
void Login(const QString &server, const QString &username, const QString &password);
|
||||
void Login(
|
||||
const QString &server, const QString &username, const QString &password);
|
||||
LoginState login_state() const { return login_state_; }
|
||||
|
||||
// Subsonic API methods
|
||||
void Ping();
|
||||
|
||||
QUrl BuildRequestUrl(const QString &view);
|
||||
QUrl BuildRequestUrl(const QString& view) const;
|
||||
// Convenience function to reduce QNetworkRequest/QSslConfiguration boilerplate
|
||||
QNetworkReply* Send(const QUrl &url);
|
||||
QNetworkReply* Send(const QUrl& url);
|
||||
|
||||
static const char* kServiceName;
|
||||
static const char* kSettingsGroup;
|
||||
@ -115,8 +116,8 @@ class SubsonicService : public InternetService
|
||||
void UpdateTotalSongCount(int count);
|
||||
void ReloadDatabase();
|
||||
void ReloadDatabaseFinished();
|
||||
void onLoginStateChanged(SubsonicService::LoginState newstate);
|
||||
void onPingFinished(QNetworkReply* reply);
|
||||
void OnLoginStateChanged(SubsonicService::LoginState newstate);
|
||||
void OnPingFinished(QNetworkReply* reply);
|
||||
|
||||
void ShowConfig();
|
||||
};
|
||||
@ -125,7 +126,7 @@ class SubsonicLibraryScanner : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SubsonicLibraryScanner(SubsonicService* service, QObject* parent=0);
|
||||
SubsonicLibraryScanner(SubsonicService* service, QObject* parent = 0);
|
||||
~SubsonicLibraryScanner();
|
||||
|
||||
void Scan();
|
||||
@ -139,13 +140,13 @@ class SubsonicLibraryScanner : public QObject {
|
||||
|
||||
private slots:
|
||||
// Step 1: use getAlbumList2 type=alphabeticalByName to list all albums
|
||||
void onGetAlbumListFinished(QNetworkReply* reply, int offset);
|
||||
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);
|
||||
|
||||
private:
|
||||
void GetAlbumList(int offset);
|
||||
void GetAlbum(QString id);
|
||||
void GetAlbum(const QString& id);
|
||||
|
||||
SubsonicService* service_;
|
||||
bool scanning_;
|
||||
|
Loading…
x
Reference in New Issue
Block a user