Add Deezer support
This commit is contained in:
@@ -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(); }
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -200,6 +200,7 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
// Resources
|
||||
Q_INIT_RESOURCE(data);
|
||||
Q_INIT_RESOURCE(icons);
|
||||
|
||||
Application app;
|
||||
|
||||
|
||||
@@ -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_);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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_;
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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");
|
||||
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
|
||||
@@ -98,6 +98,7 @@ class Song {
|
||||
Source_Device = 4,
|
||||
Source_Stream = 5,
|
||||
Source_Tidal = 6,
|
||||
Source_Deezer = 7,
|
||||
};
|
||||
|
||||
enum FileType {
|
||||
|
||||
Reference in New Issue
Block a user