Add Subsonic support (#180)

This commit is contained in:
Jonas Kvinge
2019-06-17 23:54:24 +02:00
committed by GitHub
parent a9da8811fc
commit 7b54cef23b
44 changed files with 2656 additions and 43 deletions

View File

@@ -54,7 +54,7 @@ class InternetCollectionView : public AutoExpandingTreeView {
public:
InternetCollectionView(QWidget *parent = nullptr);
~InternetCollectionView();
void Init(Application *app, CollectionBackend *backend, CollectionModel *model);
// Returns Songs currently selected in the collection view.

View File

@@ -54,5 +54,4 @@ InternetCollectionViewContainer::InternetCollectionViewContainer(QWidget *parent
InternetCollectionViewContainer::~InternetCollectionViewContainer() { delete ui_; }
void InternetCollectionViewContainer::contextMenuEvent(QContextMenuEvent *e) {
}
void InternetCollectionViewContainer::contextMenuEvent(QContextMenuEvent *e) {}

View File

@@ -29,13 +29,6 @@
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QPushButton" name="refresh">
<property name="text">
<string>Refresh catalogue</string>
</property>
</widget>
</item>
<item>
<widget class="QStackedWidget" name="stacked">
<widget class="QWidget" name="help_page">
@@ -135,6 +128,13 @@
<item>
<widget class="CollectionFilterWidget" name="filter" native="true"/>
</item>
<item>
<widget class="QPushButton" name="refresh">
<property name="text">
<string>Refresh catalogue</string>
</property>
</widget>
</item>
<item>
<widget class="InternetCollectionView" name="view"/>
</item>

View File

@@ -24,11 +24,11 @@
#include <QString>
#include <QUrl>
#include <QIcon>
#include <QSortFilterProxyModel>
#include "core/song.h"
#include "internetsearch.h"
class QSortFilterProxyModel;
class Application;
class CollectionBackend;
class CollectionModel;
@@ -38,6 +38,7 @@ class InternetService : public QObject {
public:
InternetService(Song::Source source, const QString &name, const QString &url_scheme, Application *app, QObject *parent = nullptr);
virtual ~InternetService() {}
virtual Song::Source source() const { return source_; }
@@ -47,40 +48,45 @@ class InternetService : public QObject {
virtual void InitialLoadSettings() {}
virtual void ReloadSettings() {}
virtual QIcon Icon() { return Song::IconForSource(source_); }
virtual const bool oauth() = 0;
virtual const bool authenticated() = 0;
virtual int Search(const QString &query, InternetSearch::SearchType type) = 0;
virtual void CancelSearch() = 0;
virtual const bool oauth() { return false; }
virtual const bool authenticated() { return false; }
virtual int Search(const QString &query, InternetSearch::SearchType type) { return 0; }
virtual void CancelSearch() {}
virtual CollectionBackend *artists_collection_backend() = 0;
virtual CollectionBackend *albums_collection_backend() = 0;
virtual CollectionBackend *songs_collection_backend() = 0;
virtual CollectionBackend *artists_collection_backend() { return nullptr; }
virtual CollectionBackend *albums_collection_backend() { return nullptr; }
virtual CollectionBackend *songs_collection_backend() { return nullptr; }
virtual CollectionModel *artists_collection_model() = 0;
virtual CollectionModel *albums_collection_model() = 0;
virtual CollectionModel *songs_collection_model() = 0;
virtual CollectionModel *artists_collection_model() { return nullptr; }
virtual CollectionModel *albums_collection_model() { return nullptr; }
virtual CollectionModel *songs_collection_model() { return nullptr; }
virtual QSortFilterProxyModel *artists_collection_sort_model() = 0;
virtual QSortFilterProxyModel *albums_collection_sort_model() = 0;
virtual QSortFilterProxyModel *songs_collection_sort_model() = 0;
virtual QSortFilterProxyModel *artists_collection_sort_model() { return nullptr; }
virtual QSortFilterProxyModel *albums_collection_sort_model() { return nullptr; }
virtual QSortFilterProxyModel *songs_collection_sort_model() { return nullptr; }
public slots:
virtual void ShowConfig() {}
virtual void GetArtists() = 0;
virtual void GetAlbums() = 0;
virtual void GetSongs() = 0;
virtual void ResetArtistsRequest() = 0;
virtual void ResetAlbumsRequest() = 0;
virtual void ResetSongsRequest() = 0;
virtual void GetArtists() {}
virtual void GetAlbums() {}
virtual void GetSongs() {}
virtual void ResetArtistsRequest() {}
virtual void ResetAlbumsRequest() {}
virtual void ResetSongsRequest() {}
signals:
void Login();
void Logout();
void Login(const QString &username, const QString &password, const QString &token);
void Login(const QString &hostname, const int, const QString &username, const QString &password);
void LoginSuccess();
void LoginFailure(QString failure_reason);
void LoginComplete(bool success, QString error = QString());
void TestSuccess();
void TestFailure(QString failure_reason);
void TestComplete(bool success, QString error = QString());
void Error(QString message);
void Results(SongList songs);
void UpdateStatus(QString text);

View File

@@ -0,0 +1,124 @@
/*
* Strawberry Music Player
* Copyright 2018, Jonas Kvinge <jonas@jkvinge.net>
*
* Strawberry 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.
*
* Strawberry 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 Strawberry. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "config.h"
#include <QtGlobal>
#include <QWidget>
#include <QString>
#include <QStackedWidget>
#include <QContextMenuEvent>
#include <QSortFilterProxyModel>
#include "core/application.h"
#include "collection/collectionbackend.h"
#include "collection/collectionfilterwidget.h"
#include "internetservice.h"
#include "internetsongsview.h"
#include "ui_internetcollectionviewcontainer.h"
InternetSongsView::InternetSongsView(Application *app, InternetService *service, const QString &settings_group, const SettingsDialog::Page settings_page, QWidget *parent)
: QWidget(parent),
app_(app),
service_(service),
settings_group_(settings_group),
settings_page_(settings_page),
ui_(new Ui_InternetCollectionViewContainer)
{
ui_->setupUi(this);
ui_->stacked->setCurrentWidget(ui_->internetcollection_page);
ui_->view->Init(app_, service_->songs_collection_backend(), service_->songs_collection_model());
ui_->view->setModel(service_->songs_collection_sort_model());
ui_->view->SetFilter(ui_->filter);
ui_->filter->SetSettingsGroup(settings_group);
ui_->filter->SetCollectionModel(service_->songs_collection_model());
connect(ui_->view, SIGNAL(GetSongs()), SLOT(GetSongs()));
connect(ui_->view, SIGNAL(RemoveSongs(const SongList&)), service_, SIGNAL(RemoveSongs(const SongList&)));
connect(ui_->refresh, SIGNAL(clicked()), SLOT(GetSongs()));
connect(ui_->close, SIGNAL(clicked()), SLOT(AbortGetSongs()));
connect(ui_->abort, SIGNAL(clicked()), SLOT(AbortGetSongs()));
connect(service_, SIGNAL(SongsResults(SongList)), SLOT(SongsFinished(SongList)));
connect(service_, SIGNAL(SongsError(QString)), SLOT(SongsError(QString)));
connect(service_, SIGNAL(SongsUpdateStatus(QString)), ui_->status, SLOT(setText(QString)));
connect(service_, SIGNAL(SongsProgressSetMaximum(int)), ui_->progressbar, SLOT(setMaximum(int)));
connect(service_, SIGNAL(SongsUpdateProgress(int)), ui_->progressbar, SLOT(setValue(int)));
connect(service_->songs_collection_model(), SIGNAL(TotalArtistCountUpdated(int)), ui_->view, SLOT(TotalArtistCountUpdated(int)));
connect(service_->songs_collection_model(), SIGNAL(TotalAlbumCountUpdated(int)), ui_->view, SLOT(TotalAlbumCountUpdated(int)));
connect(service_->songs_collection_model(), SIGNAL(TotalSongCountUpdated(int)), ui_->view, SLOT(TotalSongCountUpdated(int)));
connect(service_->songs_collection_model(), SIGNAL(modelAboutToBeReset()), ui_->view, SLOT(SaveFocus()));
connect(service_->songs_collection_model(), SIGNAL(modelReset()), ui_->view, SLOT(RestoreFocus()));
ReloadSettings();
}
InternetSongsView::~InternetSongsView() { delete ui_; }
void InternetSongsView::ReloadSettings() {}
void InternetSongsView::contextMenuEvent(QContextMenuEvent *e) {}
void InternetSongsView::GetSongs() {
if (!service_->authenticated() && service_->oauth()) {
service_->ShowConfig();
return;
}
ui_->status->clear();
ui_->progressbar->show();
ui_->abort->show();
ui_->close->hide();
ui_->stacked->setCurrentWidget(ui_->help_page);
service_->GetSongs();
}
void InternetSongsView::AbortGetSongs() {
service_->ResetSongsRequest();
ui_->progressbar->setValue(0);
ui_->status->clear();
ui_->stacked->setCurrentWidget(ui_->internetcollection_page);
}
void InternetSongsView::SongsError(QString error) {
ui_->status->setText(error);
ui_->progressbar->setValue(0);
ui_->progressbar->hide();
ui_->abort->hide();
ui_->close->show();
}
void InternetSongsView::SongsFinished(SongList songs) {
service_->songs_collection_backend()->DeleteAll();
ui_->stacked->setCurrentWidget(ui_->internetcollection_page);
ui_->status->clear();
service_->songs_collection_backend()->AddOrUpdateSongs(songs);
}

View File

@@ -0,0 +1,67 @@
/*
* Strawberry Music Player
* Copyright 2018, Jonas Kvinge <jonas@jkvinge.net>
*
* Strawberry 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.
*
* Strawberry 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 Strawberry. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef INTERNETSONGSVIEW_H
#define INTERNETSONGSVIEW_H
#include "config.h"
#include <QWidget>
#include <QString>
#include "settings/settingsdialog.h"
#include "internetcollectionviewcontainer.h"
#include "ui_internetcollectionviewcontainer.h"
#include "core/song.h"
class QContextMenuEvent;
class Application;
class InternetService;
class Ui_InternetCollectionViewContainer;
class InternetCollectionView;
class InternetSongsView : public QWidget {
Q_OBJECT
public:
InternetSongsView(Application *app, InternetService *service, const QString &settings_group, const SettingsDialog::Page settings_page, QWidget *parent = nullptr);
~InternetSongsView();
void ReloadSettings();
InternetCollectionView *view() const { return ui_->view; }
private slots:
void contextMenuEvent(QContextMenuEvent *e);
void GetSongs();
void AbortGetSongs();;
void SongsError(QString error);
void SongsFinished(SongList songs);
private:
Application *app_;
InternetService *service_;
QString settings_group_;
SettingsDialog::Page settings_page_;
Ui_InternetCollectionViewContainer *ui_;
};
#endif // INTERNETSONGSVIEW_H

View File

@@ -33,7 +33,7 @@
#include "internettabsview.h"
#include "ui_internettabsview.h"
InternetTabsView::InternetTabsView(Application *app, InternetService *service, InternetSearch *engine, QString settings_group, SettingsDialog::Page settings_page, QWidget *parent)
InternetTabsView::InternetTabsView(Application *app, InternetService *service, InternetSearch *engine, const QString &settings_group, const SettingsDialog::Page settings_page, QWidget *parent)
: QWidget(parent),
app_(app),
service_(service),

View File

@@ -44,7 +44,7 @@ class InternetTabsView : public QWidget {
Q_OBJECT
public:
InternetTabsView(Application *app, InternetService *service, InternetSearch *engine, QString settings_group, SettingsDialog::Page settings_page, QWidget *parent = nullptr);
InternetTabsView(Application *app, InternetService *service, InternetSearch *engine, const QString &settings_group, const SettingsDialog::Page settings_page, QWidget *parent = nullptr);
~InternetTabsView();
void ReloadSettings();