1
0
mirror of https://github.com/strawberrymusicplayer/strawberry synced 2024-12-10 15:55:29 +01:00

Remove deezer

This commit is contained in:
Jonas Kvinge 2019-03-09 17:43:20 +01:00
parent c0fb35f6b9
commit 380f2509ac
46 changed files with 19 additions and 2484 deletions

View File

@ -22,7 +22,7 @@ before_install:
git pull;
brew update;
brew unlink python;
brew install glib pkgconfig protobuf protobuf-c qt gettext;
brew install glib pkgconfig libffi protobuf protobuf-c qt gettext;
brew install sqlite --with-fts;
brew install gstreamer gst-plugins-base;
brew install gst-plugins-good --with-flac;
@ -35,8 +35,8 @@ before_install:
ls /usr/local/lib/gstreamer-1.0;
fi
before_script:
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker exec build cmake -Hstrawberry -Bbuild -DENABLE_STREAM_DEEZER=ON -DENABLE_TRANSLATIONS=ON ; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then mkdir build; cd build; cmake .. -DUSE_BUNDLE=ON -DENABLE_STREAM_DEEZER=ON -DENABLE_TRANSLATIONS=ON ; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker exec build cmake -Hstrawberry -Bbuild -DENABLE_TRANSLATIONS=ON ; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then mkdir build; cd build; cmake .. -DUSE_BUNDLE=ON -DENABLE_TRANSLATIONS=ON ; fi
script:
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker exec build make -C build -j8 ; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then

View File

@ -112,8 +112,6 @@ pkg_check_modules(LIBMTP libmtp>=1.0)
pkg_check_modules(LIBIMOBILEDEVICE libimobiledevice-1.0)
pkg_check_modules(LIBUSBMUXD libusbmuxd)
pkg_check_modules(LIBPLIST libplist)
pkg_check_modules(LIBDEEZER libdeezer)
pkg_check_modules(LIBDZMEDIA libdzmedia)
find_package(Gettext)
if(WIN32)
@ -291,18 +289,6 @@ optional_component(PHONON OFF "Engine: Phonon backend (UNSTABLE)"
DEPENDS "phonon4qt5" PHONON_FOUND
)
if (WIN32)
optional_component(DEEZER ON "Engine: Deezer backend"
DEPENDS "libdeezer" LIBDEEZER_FOUND
)
else ()
optional_component(DEEZER ON "Engine: Deezer backend"
DEPENDS "Linux" LINUX
DEPENDS "libdeezer" LIBDEEZER_FOUND
DEPENDS "libpulse" LIBPULSE_FOUND
)
endif()
optional_component(CHROMAPRINT ON "Chromaprint (Tag fetching from Musicbrainz)"
DEPENDS "chromaprint" CHROMAPRINT_FOUND
)
@ -359,21 +345,6 @@ optional_component(TRANSLATIONS OFF "Translations (No languages included yet)"
optional_component(STREAM_TIDAL ON "Streaming: Tidal support")
if (LIBDZMEDIA_FOUND OR LIBDEEZER_FOUND)
optional_component(STREAM_DEEZER ON "Streaming: Deezer support")
else()
optional_component(STREAM_DEEZER OFF "Streaming: Deezer support")
endif()
optional_component(DZMEDIA ON "DZMedia"
DEPENDS "libdzmedia" LIBDZMEDIA_FOUND
DEPENDS "Deezer support" HAVE_STREAM_DEEZER
)
if (HAVE_STREAM_DEEZER AND NOT HAVE_DZMEDIA AND NOT HAVE_DEEZER)
message(STATUS "Deezer is enabled, but not DZMedia or Deezer engine, only preview streams will be available.")
endif()
if(APPLE)
option(USE_BUNDLE "Bundle macOS dependencies" OFF)
elseif(WIN32)
@ -418,8 +389,8 @@ add_custom_target(uninstall
# Show a summary of what we have enabled
summary_show()
if(NOT HAVE_GSTREAMER AND NOT HAVE_XINE AND NOT HAVE_VLC AND NOT HAVE_PHONON AND NOT HAVE_DEEZER)
message(FATAL_ERROR "You need to have either GStreamer, Xine, VLC, Phonon or Deezer to compile!")
if(NOT HAVE_GSTREAMER AND NOT HAVE_XINE AND NOT HAVE_VLC AND NOT HAVE_PHONON)
message(FATAL_ERROR "You need to have either GStreamer, Xine, VLC or Phonon to compile!")
elseif(NOT HAVE_GSTREAMER)
message(WARNING "GStreamer is the only engine that is fully implemented. Using other engines is possible but not recommended.")
endif()

View File

@ -25,7 +25,7 @@ Strawberry is a audio player and music collection organizer. It is a fork of Cle
* Audio analyzer
* Audio equalizer
* Transfer music to iPod, iPhone, MTP or mass-storage USB player
* Streaming support for Tidal and Deezer [*]
* Streaming support for Tidal
* Scrobbler with support for Last.fm, Libre.fm and ListenBrainz
It has so far been tested to work on Linux, OpenBSD, macOS and Windows.
@ -48,7 +48,7 @@ To build Strawberry from source you need the following installed on your system
* [ALSA library (linux)](https://www.alsa-project.org/)
* [DBus (linux)](https://www.freedesktop.org/wiki/Software/dbus/)
* [PulseAudio (linux optional)](https://www.freedesktop.org/wiki/Software/PulseAudio/?)
* [GStreamer](https://gstreamer.freedesktop.org/), [Xine](https://www.xine-project.org), [VLC](https://www.videolan.org), [Deezer](https://build-repo.deezer.com/native_sdk/deezer-native-sdk-v1.2.10.zip) or [Phonon](https://techbase.kde.org/Phonon)
* [GStreamer](https://gstreamer.freedesktop.org/), [Xine](https://www.xine-project.org), [VLC](https://www.videolan.org) or [Phonon](https://techbase.kde.org/Phonon)
Optional dependencies:
@ -57,11 +57,9 @@ Optional dependencies:
* iPod Classic devices: [libgpod](http://www.gtkpod.org/libgpod/)
* iPhone, iPod Touch, iPad and Apple TV devices: [libimobiledevice, libplist and libusbmuxd](https://www.libimobiledevice.org/)
Either GStreamer, Xine, VLC, Deezer or Phonon engine is required, but only GStreamer is fully implemented so far.
Either GStreamer, Xine, VLC or Phonon engine is required, but only GStreamer is fully implemented so far.
You should also install the gstreamer plugins base and good, and optionally bad and ugly.
Deezer support require deezer's own engine, and usually only works on Windows. It is not available on Linux unless you specifically compile with the deezer library, which currently only works on Ubuntu Xenial. The Deezer SDK can be found here: https://build-repo.deezer.com/native_sdk/deezer-native-sdk-v1.2.10.zip
### :wrench: Compiling from source
### Get the code:

View File

@ -29,7 +29,6 @@
<file>pictures/osd_background.png</file>
<file>pictures/osd_shadow_corner.png</file>
<file>pictures/osd_shadow_edge.png</file>
<file>pictures/deezer.png</file>
<file>pictures/nyancat.png</file>
<file>pictures/rainbowdash.png</file>
<file>fonts/HumongousofEternitySt.ttf</file>

View File

@ -84,7 +84,6 @@
<file>icons/128x128/zoom-in.png</file>
<file>icons/128x128/zoom-out.png</file>
<file>icons/128x128/tidal.png</file>
<file>icons/128x128/deezer.png</file>
<file>icons/128x128/scrobble.png</file>
<file>icons/128x128/scrobble-disabled.png</file>
<file>icons/64x64/albums.png</file>
@ -171,7 +170,6 @@
<file>icons/64x64/zoom-in.png</file>
<file>icons/64x64/zoom-out.png</file>
<file>icons/64x64/tidal.png</file>
<file>icons/64x64/deezer.png</file>
<file>icons/64x64/scrobble.png</file>
<file>icons/64x64/scrobble-disabled.png</file>
<file>icons/48x48/albums.png</file>
@ -351,7 +349,6 @@
<file>icons/32x32/zoom-in.png</file>
<file>icons/32x32/zoom-out.png</file>
<file>icons/32x32/tidal.png</file>
<file>icons/32x32/deezer.png</file>
<file>icons/32x32/scrobble.png</file>
<file>icons/32x32/scrobble-disabled.png</file>
<file>icons/22x22/albums.png</file>
@ -442,7 +439,6 @@
<file>icons/22x22/zoom-in.png</file>
<file>icons/22x22/zoom-out.png</file>
<file>icons/22x22/tidal.png</file>
<file>icons/22x22/deezer.png</file>
<file>icons/22x22/scrobble.png</file>
<file>icons/22x22/scrobble-disabled.png</file>
</qresource>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

View File

@ -25,8 +25,6 @@ Files: src/core/main.h
src/engine/enginetype.h
src/engine/alsadevicefinder.cpp
src/engine/alsadevicefinder.h
src/engine/deezerengine.cpp
src/engine/deezerengine.h
src/engine/devicefinder.cpp
src/engine/devicefinder.h
src/engine/enginedevice.cpp
@ -39,8 +37,6 @@ Files: src/core/main.h
src/settings/backendsettingspage.h
src/settings/scrobblersettingspage.cpp
src/settings/scrobblersettingspage.h
src/settings/deezersettingspage.cpp
src/settings/deezersettingspage.h
src/settings/tidalsettingspage.cpp
src/settings/tidalsettingspage.h
src/covermanager/lastfmcoverprovider.cpp
@ -58,7 +54,6 @@ Files: src/core/main.h
src/lyrics/*
src/scrobbler/*
src/tidal/*
src/deezer/*
src/transcoder/transcoderoptionswavpack.cpp
src/transcoder/transcoderoptionswavpack.h
Copyright: 2012-2014, 2017-2018, Jonas Kvinge <jonas@jkvinge.net>

3
dist/debian/rules vendored
View File

@ -12,8 +12,7 @@ configure-stamp:
dh_testdir
cmake .. \
-DCMAKE_INSTALL_PREFIX=$(CURDIR)/debian/strawberry/usr \
-DENABLE_TRANSLATIONS=ON \
-DENABLE_STREAM_DEEZER=ON
-DENABLE_TRANSLATIONS=ON
touch configure-stamp
build: build-stamp

View File

@ -52,7 +52,6 @@ build() {
cmake ../${pkgname}-@STRAWBERRY_VERSION_PACKAGE@ \
-DCMAKE_INSTALL_PREFIX=/usr \
-DUSE_SYSTEM_TAGLIB=ON \
-DENABLE_STREAM_DEEZER=ON \
-DENABLE_PHONON=ON \
-DENABLE_TRANSLATIONS=ON
make -j$(nproc)

View File

@ -34,7 +34,7 @@
<li>Audio analyzer</li>
<li>Audio equalizer</li>
<li>Transfer music to iPod, iPhone, MTP or mass-storage USB player</li>
<li>Streaming support for Tidal and Deezer</li>
<li>Streaming support for Tidal</li>
<li>Scrobbler with support for Last.fm, Libre.fm and ListenBrainz</li>
</ul>
</description>

View File

@ -162,7 +162,6 @@ Section "Strawberry" Strawberry
File "libxml2-2.dll"
File "libsoup-2.4-1.dll"
File "liblzma-5.dll"
File "libdeezer.x64.dll"
; Register Strawberry with Default Programs
Var /GLOBAL AppIcon
@ -403,7 +402,6 @@ Section "Uninstall"
Delete "$INSTDIR\libxml2-2.dll"
Delete "$INSTDIR\libsoup-2.4-1.dll"
Delete "$INSTDIR\liblzma-5.dll"
Delete "$INSTDIR\libdeezer.x64.dll"
Delete "$INSTDIR\platforms\qwindows.dll"
Delete "$INSTDIR\sqldrivers\qsqlite.dll"

View File

@ -162,7 +162,6 @@ Section "Strawberry" Strawberry
File "libxml2-2.dll"
File "libsoup-2.4-1.dll"
File "liblzma-5.dll"
File "libdeezer.x86.dll"
; Register Strawberry with Default Programs
Var /GLOBAL AppIcon
@ -403,7 +402,6 @@ Section "Uninstall"
Delete "$INSTDIR\libxml2-2.dll"
Delete "$INSTDIR\libsoup-2.4-1.dll"
Delete "$INSTDIR\liblzma-5.dll"
Delete "$INSTDIR\libdeezer.x86.dll"
Delete "$INSTDIR\platforms\qwindows.dll"
Delete "$INSTDIR\sqldrivers\qsqlite.dll"

View File

@ -161,7 +161,6 @@ Section "Strawberry" Strawberry
File "libxml2-2.dll"
File "libsoup-2.4-1.dll"
File "liblzma-5.dll"
File "libdeezer.x64.dll"
; Register Strawberry with Default Programs
Var /GLOBAL AppIcon
@ -370,7 +369,6 @@ Section "Uninstall"
Delete "$INSTDIR\libxml2-2.dll"
Delete "$INSTDIR\libsoup-2.4-1.dll"
Delete "$INSTDIR\liblzma-5.dll"
Delete "$INSTDIR\libdeezer.x64.dll"
Delete "$INSTDIR\platforms\qwindows.dll"
Delete "$INSTDIR\sqldrivers\qsqlite.dll"

View File

@ -161,7 +161,6 @@ Section "Strawberry" Strawberry
File "libxml2-2.dll"
File "libsoup-2.4-1.dll"
File "liblzma-5.dll"
File "libdeezer.x86.dll"
; Register Strawberry with Default Programs
Var /GLOBAL AppIcon
@ -370,7 +369,6 @@ Section "Uninstall"
Delete "$INSTDIR\libxml2-2.dll"
Delete "$INSTDIR\libsoup-2.4-1.dll"
Delete "$INSTDIR\liblzma-5.dll"
Delete "$INSTDIR\libdeezer.x86.dll"
Delete "$INSTDIR\platforms\qwindows.dll"
Delete "$INSTDIR\sqldrivers\qsqlite.dll"

View File

@ -64,14 +64,6 @@ if(HAVE_PHONON)
include_directories(${PHONON_INCLUDE_DIRS})
endif()
if(HAVE_LIBDEEZER)
include_directories(${DEEZER_INCLUDE_DIRS})
endif()
if(HAVE_LIBDZMEDIA)
include_directories(${DZMEDIA_INCLUDE_DIRS})
endif()
link_directories(${TAGLIB_LIBRARY_DIRS})
include_directories(${TAGLIB_INCLUDE_DIRS})
@ -579,12 +571,6 @@ optional_source(HAVE_PHONON
HEADERS engine/phononengine.h
)
# Deezer
optional_source(HAVE_DEEZER
SOURCES engine/deezerengine.cpp
HEADERS engine/deezerengine.h
)
# DBUS and MPRIS - Unix specific
if(UNIX AND HAVE_DBUS)
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/dbus)
@ -888,19 +874,6 @@ optional_source(HAVE_STREAM_TIDAL
settings/tidalsettingspage.ui
)
optional_source(HAVE_STREAM_DEEZER
SOURCES
deezer/deezerservice.cpp
deezer/deezerurlhandler.cpp
settings/deezersettingspage.cpp
HEADERS
deezer/deezerservice.h
deezer/deezerurlhandler.h
settings/deezersettingspage.h
UI
settings/deezersettingspage.ui
)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/version.h.in ${CMAKE_CURRENT_BINARY_DIR}/version.h)
@ -994,14 +967,6 @@ if(HAVE_PHONON)
target_link_libraries(strawberry_lib ${PHONON_LIBRARIES})
endif()
if(HAVE_DEEZER)
target_link_libraries(strawberry_lib ${LIBDEEZER_LIBRARIES})
endif()
if(HAVE_DZMEDIA)
target_link_libraries(strawberry_lib ${LIBDZMEDIA_LIBRARIES})
endif()
if(HAVE_LIBGPOD)
target_link_libraries(strawberry_lib ${LIBGPOD_LIBRARIES})
endif(HAVE_LIBGPOD)

View File

@ -39,7 +39,6 @@
#cmakedefine HAVE_SPARKLE
#cmakedefine HAVE_CHROMAPRINT
#cmakedefine HAVE_TAGLIB_DSFFILE
#cmakedefine HAVE_DZMEDIA
#cmakedefine HAVE_GLOBALSHORTCUTS
#cmakedefine IMOBILEDEVICE_USES_UDIDS
#cmakedefine USE_INSTALL_PREFIX
@ -48,10 +47,8 @@
#cmakedefine HAVE_VLC
#cmakedefine HAVE_XINE
#cmakedefine HAVE_PHONON
#cmakedefine HAVE_DEEZER
#cmakedefine HAVE_STREAM_TIDAL
#cmakedefine HAVE_STREAM_DEEZER
#cmakedefine HAVE_KEYSYMDEF_H
#cmakedefine HAVE_XF86KEYSYM_H

View File

@ -66,9 +66,6 @@
#ifdef HAVE_STREAM_TIDAL
# include "tidal/tidalservice.h"
#endif
#ifdef HAVE_STREAM_DEEZER
# include "deezer/deezerservice.h"
#endif
#include "scrobbler/audioscrobbler.h"
@ -127,17 +124,11 @@ class ApplicationImpl {
InternetServices *internet_services = new InternetServices(app);
#ifdef HAVE_STREAM_TIDAL
internet_services->AddService(new TidalService(app, internet_services));
#endif
#ifdef HAVE_STREAM_DEEZER
internet_services->AddService(new DeezerService(app, internet_services));
#endif
return internet_services;
}),
#ifdef HAVE_STREAM_TIDAL
tidal_search_([=]() { return new InternetSearch(app, Song::Source_Tidal, app); }),
#endif
#ifdef HAVE_STREAM_DEEZER
deezer_search_([=]() { return new InternetSearch(app, Song::Source_Deezer, app); }),
#endif
scrobbler_([=]() { return new AudioScrobbler(app, app); })
{}
@ -161,9 +152,6 @@ class ApplicationImpl {
Lazy<InternetServices> internet_services_;
#ifdef HAVE_STREAM_TIDAL
Lazy<InternetSearch> tidal_search_;
#endif
#ifdef HAVE_STREAM_DEEZER
Lazy<InternetSearch> deezer_search_;
#endif
Lazy<AudioScrobbler> scrobbler_;
@ -236,7 +224,4 @@ InternetServices *Application::internet_services() const { return p_->internet_s
#ifdef HAVE_STREAM_TIDAL
InternetSearch *Application::tidal_search() const { return p_->tidal_search_.get(); }
#endif
#ifdef HAVE_STREAM_DEEZER
InternetSearch *Application::deezer_search() const { return p_->deezer_search_.get(); }
#endif
AudioScrobbler *Application::scrobbler() const { return p_->scrobbler_.get(); }

View File

@ -96,9 +96,6 @@ class Application : public QObject {
#ifdef HAVE_STREAM_TIDAL
InternetSearch *tidal_search() const;
#endif
#ifdef HAVE_STREAM_DEEZER
InternetSearch *deezer_search() const;
#endif
AudioScrobbler *scrobbler() const;

View File

@ -136,9 +136,6 @@
#ifdef HAVE_STREAM_TIDAL
# include "settings/tidalsettingspage.h"
#endif
#ifdef HAVE_STREAM_DEEZER
# include "settings/deezersettingspage.h"
#endif
#include "internet/internetservices.h"
#include "internet/internetservice.h"
@ -206,9 +203,6 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
}),
#ifdef HAVE_STREAM_TIDAL
tidal_search_view_(new InternetSearchView(app_, app_->tidal_search(), TidalSettingsPage::kSettingsGroup, SettingsDialog::Page_Tidal, this)),
#endif
#ifdef HAVE_STREAM_DEEZER
deezer_search_view_(new InternetSearchView(app_, app_->deezer_search(), DeezerSettingsPage::kSettingsGroup, SettingsDialog::Page_Deezer, this)),
#endif
playlist_menu_(new QMenu(this)),
playlist_add_to_another_(nullptr),
@ -266,9 +260,6 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
#ifdef HAVE_STREAM_TIDAL
ui_->tabs->addTab(tidal_search_view_, IconLoader::Load("tidal"), tr("Tidal"));
#endif
#ifdef HAVE_STREAM_DEEZER
ui_->tabs->addTab(deezer_search_view_, IconLoader::Load("deezer"), tr("Deezer"));
#endif
// Add the playing widget to the fancy tab widget
ui_->tabs->addBottomWidget(ui_->widget_playing);
@ -547,9 +538,6 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
#ifdef HAVE_STREAM_TIDAL
connect(tidal_search_view_, SIGNAL(AddToPlaylist(QMimeData*)), SLOT(AddToPlaylist(QMimeData*)));
#endif
#ifdef HAVE_STREAM_DEEZER
connect(deezer_search_view_, SIGNAL(AddToPlaylist(QMimeData*)), SLOT(AddToPlaylist(QMimeData*)));
#endif
// Playlist menu
playlist_play_pause_ = playlist_menu_->addAction(tr("Play"), this, SLOT(PlaylistPlay()));
@ -859,16 +847,6 @@ void MainWindow::ReloadSettings() {
ui_->tabs->delTab("Tidal");
#endif
#ifdef HAVE_STREAM_DEEZER
settings.beginGroup(DeezerSettingsPage::kSettingsGroup);
bool enable_deezer = settings.value("enabled", false).toBool();
settings.endGroup();
if (enable_deezer)
ui_->tabs->addTab(deezer_search_view_, IconLoader::Load("deezer"), tr("Deezer"));
else
ui_->tabs->delTab("Deezer");
#endif
}
void MainWindow::ReloadAllSettings() {
@ -885,9 +863,6 @@ void MainWindow::ReloadAllSettings() {
#ifdef HAVE_STREAM_TIDAL
tidal_search_view_->ReloadSettings();
#endif
#ifdef HAVE_STREAM_DEEZER
deezer_search_view_->ReloadSettings();
#endif
}

View File

@ -332,7 +332,6 @@ signals:
#endif
InternetSearchView *tidal_search_view_;
InternetSearchView *deezer_search_view_;
QAction *collection_show_all_;
QAction *collection_show_duplicates_;

View File

@ -59,9 +59,6 @@
#ifdef HAVE_VLC
# include "engine/vlcengine.h"
#endif
#ifdef HAVE_DEEZER
# include "engine/deezerengine.h"
#endif
#include "collection/collectionbackend.h"
#include "playlist/playlist.h"
@ -140,15 +137,6 @@ Engine::EngineType 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!"); }
@ -321,7 +309,7 @@ void Player::NextInternal(Engine::TrackChangeFlags change) {
if (app_->playlist_manager()->active()->current_item()) {
const QUrl url = app_->playlist_manager()->active()->current_item()->Url();
if (url_handlers_.contains(url.scheme()) && !(engine_->type() == Engine::Deezer && url.scheme() == "dzmedia")) {
if (url_handlers_.contains(url.scheme())) {
// The next track is already being loaded
if (url == loading_async_) return;
@ -531,7 +519,7 @@ void Player::PlayAt(int index, Engine::TrackChangeFlags change, bool reshuffle)
if (current_item_ && change == Engine::Manual && engine_->position_nanosec() != engine_->length_nanosec()) {
emit TrackSkipped(current_item_);
const QUrl &url = current_item_->Url();
if (url_handlers_.contains(url.scheme()) && !(engine_->type() == Engine::Deezer && url.scheme() == "dzmedia")) {
if (url_handlers_.contains(url.scheme())) {
url_handlers_[url.scheme()]->TrackSkipped();
}
}
@ -550,7 +538,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()) && !(engine_->type() == Engine::Deezer && url.scheme() == "dzmedia")) {
if (url_handlers_.contains(url.scheme())) {
// It's already loading
if (url == loading_async_) return;
@ -697,7 +685,7 @@ void Player::TrackAboutToEnd() {
// We don't want to preload (and scrobble) the next item in the playlist if it's just going to be stopped again immediately after.
if (app_->playlist_manager()->active()->current_item()) {
const QUrl url = app_->playlist_manager()->active()->current_item()->Url();
if (url_handlers_.contains(url.scheme()) && !(engine_->type() == Engine::Deezer && url.scheme() == "dzmedia")) {
if (url_handlers_.contains(url.scheme())) {
url_handlers_[url.scheme()]->TrackAboutToEnd();
return;
}
@ -730,7 +718,7 @@ void Player::TrackAboutToEnd() {
QUrl url = next_item->Url();
// Get the actual track URL rather than the stream URL.
if (url_handlers_.contains(url.scheme()) && !(engine_->type() == Engine::Deezer && url.scheme() == "dzmedia")) {
if (url_handlers_.contains(url.scheme())) {
UrlHandler::LoadResult result = url_handlers_[url.scheme()]->LoadNext(url);
switch (result.type_) {
case UrlHandler::LoadResult::Error:

View File

@ -304,7 +304,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 || d->source_ == Source_Deezer; }
bool Song::is_stream() const { return d->source_ == Source_Stream || d->source_ == Source_Tidal; }
bool Song::is_cdda() const { return d->source_ == Source_CDDA; }
bool Song::is_collection_song() const {
return !is_cdda() && !is_stream() && id() != -1;
@ -393,7 +393,6 @@ 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");
}
@ -408,7 +407,6 @@ 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

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

View File

@ -1,827 +0,0 @@
/*
* 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"
#ifdef HAVE_DZMEDIA
# include <dzmedia.h>
#endif
#include <QObject>
#include <QByteArray>
#include <QList>
#include <QVector>
#include <QPair>
#include <QString>
#include <QUrl>
#include <QUrlQuery>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QTimer>
#include <QJsonParseError>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QJsonValue>
#include <QMenu>
#include <QDesktopServices>
#include <QSettings>
#include "core/application.h"
#include "core/player.h"
#include "core/closure.h"
#include "core/logging.h"
#include "core/mergedproxymodel.h"
#include "core/network.h"
#include "core/song.h"
#include "core/iconloader.h"
#include "core/taskmanager.h"
#include "core/timeconstants.h"
#include "core/utilities.h"
#include "internet/internetservices.h"
#include "internet/internetsearch.h"
#include "internet/localredirectserver.h"
#include "deezerservice.h"
#include "deezerurlhandler.h"
#include "settings/deezersettingspage.h"
const Song::Source DeezerService::kSource = Song::Source_Deezer;
const char *DeezerService::kApiUrl = "https://api.deezer.com";
const char *DeezerService::kOAuthUrl = "https://connect.deezer.com/oauth/auth.php";
const char *DeezerService::kOAuthAccessTokenUrl = "https://connect.deezer.com/oauth/access_token.php";
const char *DeezerService::kOAuthRedirectUrl = "https://oauth.strawbs.net";
const int DeezerService::kAppID = 303684;
const char *DeezerService::kSecretKey = "06911976010b9ddd7256769adf2b2e56";
typedef QPair<QString, QString> Param;
DeezerService::DeezerService(Application *app, QObject *parent)
: InternetService(Song::Source_Deezer, "Deezer", "dzmedia", app, parent),
network_(new NetworkAccessManager(this)),
url_handler_(new DeezerUrlHandler(app, this)),
#ifdef HAVE_DZMEDIA
dzmedia_(new DZMedia(this)),
#endif
timer_searchdelay_(new QTimer(this)),
searchdelay_(1500),
albumssearchlimit_(1),
songssearchlimit_(1),
fetchalbums_(false),
preview_(false),
pending_search_id_(0),
next_pending_search_id_(1),
search_id_(0),
albums_requested_(0),
albums_received_(0)
{
timer_searchdelay_->setSingleShot(true);
connect(timer_searchdelay_, SIGNAL(timeout()), SLOT(StartSearch()));
connect(this, SIGNAL(Authenticated()), app->player(), SLOT(HandleAuthentication()));
app->player()->RegisterUrlHandler(url_handler_);
ReloadSettings();
LoadAccessToken();
#ifdef HAVE_DZMEDIA
connect(dzmedia_, SIGNAL(StreamURLReceived(QUrl, QUrl, DZMedia::FileType)), this, SLOT(GetStreamURLFinished(QUrl, QUrl, DZMedia::FileType)));
#endif
}
DeezerService::~DeezerService() {}
void DeezerService::ShowConfig() {
app_->OpenSettingsDialogAtPage(SettingsDialog::Page_Deezer);
}
void DeezerService::ReloadSettings() {
QSettings s;
s.beginGroup(DeezerSettingsPage::kSettingsGroup);
searchdelay_ = s.value("searchdelay", 1500).toInt();
albumssearchlimit_ = s.value("albumssearchlimit", 100).toInt();
songssearchlimit_ = s.value("songssearchlimit", 100).toInt();
fetchalbums_ = s.value("fetchalbums", false).toBool();
coversize_ = s.value("coversize", "cover_big").toString();
#if defined(HAVE_DEEZER) || defined(HAVE_DZMEDIA)
bool preview(false);
#else
bool preview(true);
#endif
preview_ = s.value("preview", preview).toBool();
s.endGroup();
}
void DeezerService::LoadAccessToken() {
QSettings s;
s.beginGroup(DeezerSettingsPage::kSettingsGroup);
if (s.contains("access_token") && s.contains("expiry_time")) {
access_token_ = s.value("access_token").toString();
expiry_time_ = s.value("expiry_time").toDateTime();
}
s.endGroup();
}
void DeezerService::Logout() {
access_token_.clear();
QSettings s;
s.beginGroup(DeezerSettingsPage::kSettingsGroup);
s.remove("access_token");
s.remove("expiry_time");
s.endGroup();
}
void DeezerService::StartAuthorisation() {
LocalRedirectServer *server = new LocalRedirectServer(this);
server->Listen();
QUrl url = QUrl(kOAuthUrl);
QUrlQuery url_query;
//url_query.addQueryItem("response_type", "token");
url_query.addQueryItem("response_type", "code");
url_query.addQueryItem("app_id", QString::number(kAppID));
QUrl redirect_url;
QUrlQuery redirect_url_query;
const QString port = QString::number(server->url().port());
redirect_url = QUrl(kOAuthRedirectUrl);
redirect_url_query.addQueryItem("port", port);
redirect_url.setQuery(redirect_url_query);
url_query.addQueryItem("redirect_uri", redirect_url.toString());
url.setQuery(url_query);
NewClosure(server, SIGNAL(Finished()), this, &DeezerService::RedirectArrived, server, redirect_url);
QDesktopServices::openUrl(url);
}
void DeezerService::RedirectArrived(LocalRedirectServer *server, QUrl url) {
server->deleteLater();
QUrl request_url = server->request_url();
RequestAccessToken(QUrlQuery(request_url).queryItemValue("code").toUtf8());
}
void DeezerService::RequestAccessToken(const QByteArray &code) {
typedef QPair<QString, QString> Arg;
typedef QList<Arg> ArgList;
typedef QPair<QByteArray, QByteArray> EncodedArg;
typedef QList<EncodedArg> EncodedArgList;
ArgList args = ArgList() << Arg("app_id", QString::number(kAppID))
<< Arg("secret", kSecretKey)
<< Arg("code", code);
QUrlQuery url_query;
for (const Arg &arg : args) {
EncodedArg encoded_arg(QUrl::toPercentEncoding(arg.first), QUrl::toPercentEncoding(arg.second));
url_query.addQueryItem(encoded_arg.first, encoded_arg.second);
}
QUrl url(kOAuthAccessTokenUrl);
QNetworkRequest request = QNetworkRequest(url);
QNetworkReply *reply = network_->post(request, url_query.toString(QUrl::FullyEncoded).toUtf8());
NewClosure(reply, SIGNAL(finished()), this, SLOT(FetchAccessTokenFinished(QNetworkReply*)), reply);
}
void DeezerService::FetchAccessTokenFinished(QNetworkReply *reply) {
reply->deleteLater();
if (reply->error() != QNetworkReply::NoError) {
Error(QString("%1 (%2)").arg(reply->errorString()).arg(reply->error()));
return;
}
forever {
QByteArray line = reply->readLine();
QString str(line);
QStringList args = str.split("&");
for (QString arg : args) {
QStringList params = arg.split("=");
if (params.count() < 2) continue;
QString param1 = params.first();
QString param2 = params[1];
if (param1 == "access_token") access_token_ = param2;
else if (param1 == "expires") SetExpiryTime(param2.toInt());
}
if (reply->atEnd()) break;
}
QSettings s;
s.beginGroup(DeezerSettingsPage::kSettingsGroup);
s.setValue("access_token", access_token_);
s.setValue("expiry_time", expiry_time_);
s.endGroup();
emit Authenticated();
emit LoginSuccess();
}
void DeezerService::SetExpiryTime(int expires_in_seconds) {
// Set the expiry time with two minutes' grace.
expiry_time_ = QDateTime::currentDateTime().addSecs(expires_in_seconds - 120);
qLog(Debug) << "Current oauth access token expires at:" << expiry_time_;
}
QNetworkReply *DeezerService::CreateRequest(const QString &ressource_name, const QList<Param> &params) {
typedef QPair<QString, QString> Arg;
typedef QList<Arg> ArgList;
typedef QPair<QByteArray, QByteArray> EncodedArg;
typedef QList<EncodedArg> EncodedArgList;
ArgList args = ArgList() << Arg("access_token", access_token_)
<< Arg("output", "json")
<< params;
QUrlQuery url_query;
for (const Arg& arg : args) {
EncodedArg encoded_arg(QUrl::toPercentEncoding(arg.first), QUrl::toPercentEncoding(arg.second));
url_query.addQueryItem(encoded_arg.first, encoded_arg.second);
}
QUrl url(kApiUrl + QString("/") + ressource_name);
url.setQuery(url_query);
QNetworkRequest req(url);
QNetworkReply *reply = network_->get(req);
//qLog(Debug) << "Deezer: Sending request" << url;
return reply;
}
QByteArray DeezerService::GetReplyData(QNetworkReply *reply) {
QByteArray data;
if (reply->error() == QNetworkReply::NoError && reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() == 200) {
data = reply->readAll();
}
else {
if (reply->error() < 200) {
// This is a network error, there is nothing more to do.
QString failure_reason = QString("%1 (%2)").arg(reply->errorString()).arg(reply->error());
Error(failure_reason);
}
else {
// See if there is Json data containing "error" - then use that instead.
data = reply->readAll();
QJsonParseError error;
QJsonDocument json_doc = QJsonDocument::fromJson(data, &error);
QString failure_reason;
if (error.error == QJsonParseError::NoError && !json_doc.isNull() && !json_doc.isEmpty() && json_doc.isObject()) {
QJsonObject json_obj = json_doc.object();
if (json_obj.contains("error")) {
QJsonValue json_value_error = json_obj["error"];
if (json_value_error.isObject()) {
QJsonObject json_error = json_value_error.toObject();
int code = json_error["code"].toInt();
if (code == 300) Logout();
QString message = json_error["message"].toString();
QString type = json_error["type"].toString();
failure_reason = QString("%1 (%2)").arg(message).arg(code);
}
else { failure_reason = QString("%1 (%2)").arg(reply->errorString()).arg(reply->error()); }
}
else {
failure_reason = QString("%1 (%2)").arg(reply->errorString()).arg(reply->error());
}
}
else {
failure_reason = QString("%1 (%2)").arg(reply->errorString()).arg(reply->error());
}
if (reply->error() == QNetworkReply::ContentAccessDenied || reply->error() == QNetworkReply::ContentOperationNotPermittedError || reply->error() == QNetworkReply::AuthenticationRequiredError) {
// Session is probably expired
Logout();
Error(failure_reason);
}
else if (reply->error() == QNetworkReply::ContentNotFoundError) { // Ignore this error
Error(failure_reason);
}
else { // Fail
Error(failure_reason);
}
}
return QByteArray();
}
return data;
}
QJsonObject DeezerService::ExtractJsonObj(QByteArray &data) {
QJsonParseError error;
QJsonDocument json_doc = QJsonDocument::fromJson(data, &error);
if (error.error != QJsonParseError::NoError) {
Error("Reply from server missing Json data.", data);
return QJsonObject();
}
if (json_doc.isNull() || json_doc.isEmpty()) {
Error("Received empty Json document.", json_doc);
return QJsonObject();
}
if (!json_doc.isObject()) {
Error("Json document is not an object.", json_doc);
return QJsonObject();
}
QJsonObject json_obj = json_doc.object();
if (json_obj.isEmpty()) {
Error("Received empty Json object.", json_doc);
return QJsonObject();
}
return json_obj;
}
QJsonValue DeezerService::ExtractData(QByteArray &data) {
QJsonObject json_obj = ExtractJsonObj(data);
if (json_obj.isEmpty()) return QJsonObject();
if (json_obj.contains("error")) {
QJsonValue json_value_error = json_obj["error"];
if (!json_value_error.isObject()) {
Error("Error missing object", json_obj);
return QJsonValue();
}
QJsonObject json_error = json_value_error.toObject();
int code = json_error["code"].toInt();
if (code == 300) Logout();
QString message = json_error["message"].toString();
QString type = json_error["type"].toString();
Error(QString("%1 (%2)").arg(message).arg(code));
return QJsonValue();
}
if (!json_obj.contains("data") && !json_obj.contains("DATA")) {
Error("Json reply is missing data.", json_obj);
return QJsonValue();
}
QJsonValue json_data;
if (json_obj.contains("data")) json_data = json_obj["data"];
else json_data = json_obj["DATA"];
return json_data;
}
int DeezerService::Search(const QString &text, InternetSearch::SearchType searchby) {
pending_search_id_ = next_pending_search_id_;
pending_search_text_ = text;
pending_search_type_ = searchby;
next_pending_search_id_++;
if (text.isEmpty()) {
timer_searchdelay_->stop();
return pending_search_id_;
}
timer_searchdelay_->setInterval(searchdelay_);
timer_searchdelay_->start();
return pending_search_id_;
}
void DeezerService::StartSearch() {
if (access_token_.isEmpty()) {
emit SearchError(pending_search_id_, "Not authenticated.");
next_pending_search_id_ = 1;
ShowConfig();
return;
}
ClearSearch();
search_id_ = pending_search_id_;
search_text_ = pending_search_text_;
SendSearch();
}
void DeezerService::CancelSearch() {
ClearSearch();
}
void DeezerService::ClearSearch() {
search_id_ = 0;
search_text_.clear();
search_error_.clear();
albums_requested_ = 0;
albums_received_ = 0;
requests_album_.clear();
requests_song_.clear();
songs_.clear();
}
void DeezerService::SendSearch() {
emit UpdateStatus(tr("Searching..."));
QList<Param> parameters;
parameters << Param("q", search_text_);
QString searchparam;
switch (pending_search_type_) {
case InternetSearch::SearchType_Songs:
searchparam = "search/track";
parameters << Param("limit", QString::number(songssearchlimit_));
break;
case InternetSearch::SearchType_Albums:
case InternetSearch::SearchType_Artists:
default:
searchparam = "search/album";
parameters << Param("limit", QString::number(albumssearchlimit_));
break;
}
QNetworkReply *reply = CreateRequest(searchparam, parameters);
NewClosure(reply, SIGNAL(finished()), this, SLOT(SearchFinished(QNetworkReply*, int)), reply, search_id_);
}
void DeezerService::SearchFinished(QNetworkReply *reply, int id) {
reply->deleteLater();
if (id != search_id_) return;
QByteArray data = GetReplyData(reply);
if (data.isEmpty()) {
CheckFinish();
return;
}
QJsonValue json_value = ExtractData(data);
if (!json_value.isArray()) {
CheckFinish();
return;
}
QJsonArray json_data = json_value.toArray();
if (json_data.isEmpty()) {
Error(tr("No match."));
CheckFinish();
return;
}
for (const QJsonValue &value : json_data) {
if (!value.isObject()) {
Error("Invalid Json reply, data is not an object.", value);
continue;
}
QJsonObject json_obj = value.toObject();
if (!json_obj.contains("id") || !json_obj.contains("type")) {
Error("Invalid Json reply, item is missing ID or type.", json_obj);
continue;
}
QString type = json_obj["type"].toString();
if (!json_obj.contains("artist")) {
Error("Invalid Json reply, item missing artist.", json_obj);
continue;
}
QJsonValue json_value_artist = json_obj["artist"];
if (!json_value_artist.isObject()