Add Deezer support

This commit is contained in:
Jonas Kvinge
2018-10-14 00:08:33 +02:00
parent 4aad44cb62
commit 0a81fa99fc
78 changed files with 5309 additions and 630 deletions

View File

@@ -60,6 +60,7 @@
#include "internet/internetmodel.h"
#include "tidal/tidalsearch.h"
#include "deezer/deezersearch.h"
bool Application::kIsPortable = false;
@@ -108,15 +109,16 @@ class ApplicationImpl {
return loader;
}),
current_art_loader_([=]() { return new CurrentArtLoader(app, app); }),
internet_model_([=]() { return new InternetModel(app, app); }),
tidal_search_([=]() { return new TidalSearch(app, app); }),
lyrics_providers_([=]() {
LyricsProviders *lyrics_providers = new LyricsProviders(app);
lyrics_providers->AddProvider(new AuddLyricsProvider(app));
lyrics_providers->AddProvider(new APISeedsLyricsProvider(app));
return lyrics_providers;
})
{ }
lyrics_providers->AddProvider(new APISeedsLyricsProvider(app));
return lyrics_providers;
}),
internet_model_([=]() { return new InternetModel(app, app); }),
tidal_search_([=]() { return new TidalSearch(app, app); }),
deezer_search_([=]() { return new DeezerSearch(app, app); })
{}
Lazy<TagReaderClient> tag_reader_client_;
Lazy<Database> database_;
@@ -133,9 +135,10 @@ class ApplicationImpl {
Lazy<CoverProviders> cover_providers_;
Lazy<AlbumCoverLoader> album_cover_loader_;
Lazy<CurrentArtLoader> current_art_loader_;
Lazy<LyricsProviders> lyrics_providers_;
Lazy<InternetModel> internet_model_;
Lazy<TidalSearch> tidal_search_;
Lazy<LyricsProviders> lyrics_providers_;
Lazy<DeezerSearch> deezer_search_;
};
@@ -181,73 +184,27 @@ void Application::MoveToThread(QObject *object, QThread *thread) {
}
void Application::AddError(const QString& message) { emit ErrorAdded(message); }
void Application::ReloadSettings() { emit SettingsChanged(); }
void Application::OpenSettingsDialogAtPage(SettingsDialog::Page page) { emit SettingsDialogRequested(page); }
void Application::OpenSettingsDialogAtPage(SettingsDialog::Page page) {
emit SettingsDialogRequested(page);
}
AlbumCoverLoader *Application::album_cover_loader() const {
return p_->album_cover_loader_.get();
}
TagReaderClient *Application::tag_reader_client() const { return p_->tag_reader_client_.get(); }
Appearance *Application::appearance() const { return p_->appearance_.get(); }
CoverProviders *Application::cover_providers() const {
return p_->cover_providers_.get();
}
CurrentArtLoader *Application::current_art_loader() const {
return p_->current_art_loader_.get();
}
Database *Application::database() const { return p_->database_.get(); }
#ifndef Q_OS_WIN
DeviceManager *Application::device_manager() const {
return p_->device_manager_.get();
}
#endif
SCollection *Application::collection() const { return p_->collection_.get(); }
CollectionBackend *Application::collection_backend() const {
return collection()->backend();
}
CollectionModel *Application::collection_model() const { return collection()->model(); }
TaskManager *Application::task_manager() const { return p_->task_manager_.get(); }
Player *Application::player() const { return p_->player_.get(); }
PlaylistBackend *Application::playlist_backend() const {
return p_->playlist_backend_.get();
}
PlaylistManager *Application::playlist_manager() const {
return p_->playlist_manager_.get();
}
TagReaderClient *Application::tag_reader_client() const {
return p_->tag_reader_client_.get();
}
TaskManager *Application::task_manager() const {
return p_->task_manager_.get();
}
EngineDevice *Application::enginedevice() const {
return p_->enginedevice_.get();
}
InternetModel* Application::internet_model() const {
return p_->internet_model_.get();
}
TidalSearch* Application::tidal_search() const {
return p_->tidal_search_.get();
}
LyricsProviders *Application::lyrics_providers() const {
return p_->lyrics_providers_.get();
}
EngineDevice *Application::enginedevice() const { return p_->enginedevice_.get(); }
#ifndef Q_OS_WIN
DeviceManager *Application::device_manager() const { return p_->device_manager_.get(); }
#endif
SCollection *Application::collection() const { return p_->collection_.get(); }
CollectionBackend *Application::collection_backend() const { return collection()->backend(); }
CollectionModel *Application::collection_model() const { return collection()->model(); }
AlbumCoverLoader *Application::album_cover_loader() const { return p_->album_cover_loader_.get(); }
CoverProviders *Application::cover_providers() const { return p_->cover_providers_.get(); }
CurrentArtLoader *Application::current_art_loader() const { return p_->current_art_loader_.get(); }
LyricsProviders *Application::lyrics_providers() const { return p_->lyrics_providers_.get(); }
PlaylistBackend *Application::playlist_backend() const { return p_->playlist_backend_.get(); }
PlaylistManager *Application::playlist_manager() const { return p_->playlist_manager_.get(); }
InternetModel *Application::internet_model() const { return p_->internet_model_.get(); }
TidalSearch *Application::tidal_search() const { return p_->tidal_search_.get(); }
DeezerSearch *Application::deezer_search() const { return p_->deezer_search_.get(); }

View File

@@ -51,9 +51,10 @@ class DeviceManager;
class CoverProviders;
class AlbumCoverLoader;
class CurrentArtLoader;
class LyricsProviders;
class InternetModel;
class TidalSearch;
class LyricsProviders;
class DeezerSearch;
class Application : public QObject {
Q_OBJECT
@@ -75,6 +76,8 @@ class Application : public QObject {
#endif
SCollection *collection() const;
CollectionBackend *collection_backend() const;
CollectionModel *collection_model() const;
PlaylistBackend *playlist_backend() const;
PlaylistManager *playlist_manager() const;
@@ -83,13 +86,11 @@ class Application : public QObject {
AlbumCoverLoader *album_cover_loader() const;
CurrentArtLoader *current_art_loader() const;
CollectionBackend *collection_backend() const;
CollectionModel *collection_model() const;
LyricsProviders *lyrics_providers() const;
InternetModel *internet_model() const;
TidalSearch *tidal_search() const;
LyricsProviders *lyrics_providers() const;
DeezerSearch *deezer_search() const;
void MoveToNewThread(QObject *object);
void MoveToThread(QObject *object, QThread *thread);

View File

@@ -200,6 +200,7 @@ int main(int argc, char* argv[]) {
// Resources
Q_INIT_RESOURCE(data);
Q_INIT_RESOURCE(icons);
Application app;

View File

@@ -134,7 +134,11 @@
#include "settings/playlistsettingspage.h"
#include "settings/settingsdialog.h"
#include "internet/internetmodel.h"
#include "internet/internetservice.h"
#include "tidal/tidalsearchview.h"
#include "deezer/deezersearchview.h"
#if defined(HAVE_GSTREAMER) && defined(HAVE_CHROMAPRINT)
# include "musicbrainz/tagfetcher.h"
@@ -200,6 +204,7 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
return manager;
}),
tidal_search_view_(new TidalSearchView(app_, this)),
deezer_search_view_(new DeezerSearchView(app_, this)),
playlist_menu_(new QMenu(this)),
playlist_add_to_another_(nullptr),
playlistitem_actions_separator_(nullptr),
@@ -243,7 +248,7 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
ui_->volume->setValue(volume);
VolumeChanged(volume);
// Initialise the tidal search widget
// Initialise the search widget
StyleHelper::setBaseColor(palette().color(QPalette::Highlight).darker());
// Add tabs to the fancy tab widget
@@ -255,6 +260,7 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
ui_->tabs->addTab(device_view_, IconLoader::Load("device"), tr("Devices"));
#endif
ui_->tabs->addTab(tidal_search_view_, IconLoader::Load("tidal"), tr("Tidal", "Tidal"));
ui_->tabs->addTab(deezer_search_view_, IconLoader::Load("deezer"), tr("Deezer", "Deezer"));
//ui_->tabs->AddSpacer();
// Add the playing widget to the fancy tab widget
@@ -515,6 +521,8 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
// Tidal
connect(tidal_search_view_, SIGNAL(AddToPlaylist(QMimeData*)), SLOT(AddToPlaylist(QMimeData*)));
// Deezer
connect(deezer_search_view_, SIGNAL(AddToPlaylist(QMimeData*)), SLOT(AddToPlaylist(QMimeData*)));
// Playlist menu
playlist_play_pause_ = playlist_menu_->addAction(tr("Play"), this, SLOT(PlaylistPlay()));
@@ -710,12 +718,6 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
ReloadSettings();
// Tidal search shortcut
QAction *tidal_search_action = new QAction(this);
tidal_search_action->setShortcuts(QList<QKeySequence>() << QKeySequence("Ctrl+F") << QKeySequence("Ctrl+L"));
addAction(tidal_search_action);
connect(tidal_search_action, SIGNAL(triggered()), SLOT(FocusTidalSearchField()));
// Reload pretty OSD to avoid issues with fonts
osd_->ReloadPrettyOSDSettings();
@@ -809,6 +811,7 @@ void MainWindow::ReloadAllSettings() {
collection_view_->ReloadSettings();
ui_->playlist->view()->ReloadSettings();
tidal_search_view_->ReloadSettings();
deezer_search_view_->ReloadSettings();
}
@@ -2311,39 +2314,6 @@ void MainWindow::keyPressEvent(QKeyEvent *event) {
}
}
void MainWindow::FocusTidalSearchField() {
ui_->tabs->setCurrentWidget(tidal_search_view_);
tidal_search_view_->FocusSearchField();
}
void MainWindow::DoTidalSearch(const QString& query) {
FocusTidalSearchField();
tidal_search_view_->StartSearch(query);
}
void MainWindow::SearchForArtist() {
PlaylistItemPtr item(app_->playlist_manager()->current()->item_at(playlist_menu_index_.row()));
Song song = item->Metadata();
if (!song.albumartist().isEmpty()) {
DoTidalSearch(song.albumartist().simplified());
}
else if (!song.artist().isEmpty()) {
DoTidalSearch(song.artist().simplified());
}
}
void MainWindow::SearchForAlbum() {
PlaylistItemPtr item(app_->playlist_manager()->current()->item_at(playlist_menu_index_.row()));
Song song = item->Metadata();
if (!song.album().isEmpty()) {
DoTidalSearch(song.album().simplified());
}
}
void MainWindow::LoadCoverFromFile() {
album_cover_choice_controller_->LoadCoverFromFile(&song_);
}
@@ -2402,4 +2372,3 @@ void MainWindow::GetCoverAutomatically() {
if (search) album_cover_choice_controller_->SearchCoverAutomatically(song_);
}

View File

@@ -89,6 +89,7 @@ class TranscodeDialog;
class Ui_MainWindow;
class Windows7ThumbBar;
class TidalSearchView;
class DeezerSearchView;
class MainWindow : public QMainWindow, public PlatformInterface {
Q_OBJECT
@@ -273,11 +274,6 @@ signals:
void ShowConsole();
void FocusTidalSearchField();
void DoTidalSearch(const QString& query);
void SearchForArtist();
void SearchForAlbum();
void LoadCoverFromFile();
void SaveCoverToFile();
void LoadCoverFromURL();
@@ -342,6 +338,7 @@ signals:
#endif
TidalSearchView *tidal_search_view_;
DeezerSearchView *deezer_search_view_;
QAction *collection_show_all_;
QAction *collection_show_duplicates_;

View File

@@ -14,7 +14,7 @@
<string>Strawberry Music Player</string>
</property>
<property name="windowIcon">
<iconset resource="../../data/data.qrc">
<iconset resource="../../data/icons.qrc">
<normaloff>:/icons/64x64/strawberry.png</normaloff>:/icons/64x64/strawberry.png</iconset>
</property>
<widget class="QWidget" name="centralWidget">
@@ -553,7 +553,7 @@
</action>
<action name="action_about_strawberry">
<property name="icon">
<iconset resource="../../data/data.qrc">
<iconset resource="../../data/icons.qrc">
<normaloff>:/icons/64x64/strawberry.png</normaloff>:/icons/64x64/strawberry.png</iconset>
</property>
<property name="text">
@@ -782,6 +782,7 @@
</customwidgets>
<resources>
<include location="../../data/data.qrc"/>
<include location="../../data/icons.qrc"/>
</resources>
<connections/>
</ui>

View File

@@ -61,6 +61,7 @@
#endif
#include "tidal/tidalsearch.h"
#include "deezer/deezersearch.h"
void RegisterMetaTypes() {
@@ -118,4 +119,7 @@ void RegisterMetaTypes() {
qRegisterMetaType<TidalSearch::ResultList>("TidalSearch::ResultList");
qRegisterMetaType<TidalSearch::Result>("TidalSearch::Result");
qRegisterMetaType<DeezerSearch::ResultList>("DeezerSearch::ResultList");
qRegisterMetaType<DeezerSearch::Result>("DeezerSearch::Result");
}

View File

@@ -59,6 +59,9 @@
#ifdef HAVE_VLC
# include "engine/vlcengine.h"
#endif
#ifdef HAVE_DEEZER
# include "engine/deezerengine.h"
#endif
#include "collection/collectionbackend.h"
#include "playlist/playlist.h"
@@ -70,6 +73,8 @@
#include "settings/backendsettingspage.h"
#include "settings/behavioursettingspage.h"
#include "settings/playlistsettingspage.h"
#include "internet/internetmodel.h"
#include "internet/internetservice.h"
using std::shared_ptr;
@@ -103,7 +108,7 @@ Player::~Player() {
void Player::CreateEngine(Engine::EngineType enginetype) {
Engine::EngineType use_enginetype = Engine::None;
Engine::EngineType use_enginetype(Engine::None);
for (int i = 0 ; use_enginetype == Engine::None ; i++) {
switch(enginetype) {
@@ -131,6 +136,15 @@ void Player::CreateEngine(Engine::EngineType enginetype) {
use_enginetype=Engine::Phonon;
engine_.reset(new PhononEngine(app_->task_manager()));
break;
#endif
#ifdef HAVE_DEEZER
case Engine::Deezer:{
use_enginetype=Engine::Deezer;
DeezerEngine *deezerengine = new DeezerEngine(app_->task_manager());
connect(this, SIGNAL(Authenticated()), deezerengine, SLOT(LoadAccessToken()));
engine_.reset(deezerengine);
break;
}
#endif
default:
if (i > 0) { qFatal("No engine available!"); }
@@ -144,7 +158,7 @@ void Player::CreateEngine(Engine::EngineType enginetype) {
s.beginGroup(BackendSettingsPage::kSettingsGroup);
s.setValue("engine", EngineName(use_enginetype));
s.setValue("output", engine_->DefaultOutput());
s.setValue("device", QVariant(""));
s.setValue("device", QVariant());
s.endGroup();
}
@@ -499,7 +513,7 @@ void Player::PlayAt(int index, Engine::TrackChangeFlags change, bool reshuffle)
current_item_ = app_->playlist_manager()->active()->current_item();
const QUrl url = current_item_->Url();
if (url_handlers_.contains(url.scheme())) {
if (url_handlers_.contains(url.scheme()) && !(engine_->type() == Engine::Deezer && url.scheme() == "dzmedia")) {
// It's already loading
if (url == loading_async_) return;
@@ -761,3 +775,7 @@ void Player::UrlHandlerDestroyed(QObject *object) {
}
}
void Player::HandleAuthentication() {
emit Authenticated();
}

View File

@@ -114,6 +114,9 @@ class PlayerInterface : public QObject {
// The toggle parameter is true when user requests to toggle visibility for Pretty OSD
void ForceShowOSD(Song, bool toogle);
void Authenticated();
};
class Player : public PlayerInterface {
@@ -176,6 +179,8 @@ class Player : public PlayerInterface {
void Play();
void ShowOSD();
void TogglePrettyOSD();
void HandleAuthentication();
private slots:
void EngineStateChanged(Engine::State);

View File

@@ -298,7 +298,7 @@ uint Song::mtime() const { return d->mtime_; }
uint Song::ctime() const { return d->ctime_; }
int Song::filesize() const { return d->filesize_; }
Song::FileType Song::filetype() const { return d->filetype_; }
bool Song::is_stream() const { return d->source_ == Source_Stream || d->source_ == Source_Tidal; }
bool Song::is_stream() const { return d->source_ == Source_Stream || d->source_ == Source_Tidal || d->source_ == Source_Deezer; }
bool Song::is_cdda() const { return d->source_ == Source_CDDA; }
bool Song::is_collection_song() const {
return !is_cdda() && !is_stream() && id() != -1;
@@ -384,6 +384,7 @@ QString Song::TextForSource(Source source) {
case Song::Source_Device: return QObject::tr("Device");
case Song::Source_Stream: return QObject::tr("Stream");
case Song::Source_Tidal: return QObject::tr("Tidal");
case Song::Source_Deezer: return QObject::tr("Deezer");
default: return QObject::tr("Unknown");
}
@@ -398,6 +399,7 @@ QIcon Song::IconForSource(Source source) {
case Song::Source_Device: return IconLoader::Load("device");
case Song::Source_Stream: return IconLoader::Load("applications-internet");
case Song::Source_Tidal: return IconLoader::Load("tidal");
case Song::Source_Deezer: return IconLoader::Load("deezer");
default: return IconLoader::Load("edit-delete");
}

View File

@@ -98,6 +98,7 @@ class Song {
Source_Device = 4,
Source_Stream = 5,
Source_Tidal = 6,
Source_Deezer = 7,
};
enum FileType {