diff --git a/data/data.qrc b/data/data.qrc
index 346b6bf6c..a944cff24 100644
--- a/data/data.qrc
+++ b/data/data.qrc
@@ -9,7 +9,6 @@
currenttrack_pause.png
currenttrack_play.png
globalsearch.css
- grooveshark-valicert-ca.pem
hypnotoad.gif
icon_large_grey.png
icon_large.png
@@ -320,7 +319,6 @@
providers/dropbox.png
providers/echonest.png
providers/googledrive.png
- providers/grooveshark.png
providers/itunes.png
providers/jamendo.png
providers/jazzradio.png
diff --git a/data/grooveshark-valicert-ca.pem b/data/grooveshark-valicert-ca.pem
deleted file mode 100644
index 1cb1d7126..000000000
--- a/data/grooveshark-valicert-ca.pem
+++ /dev/null
@@ -1,43 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0
-IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz
-BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y
-aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG
-9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMTk1NFoXDTE5MDYy
-NjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y
-azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs
-YXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw
-Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl
-cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOOnHK5avIWZJV16vY
-dA757tn2VUdZZUcOBVXc65g2PFxTXdMwzzjsvUGJ7SVCCSRrCl6zfN1SLUzm1NZ9
-WlmpZdRJEy0kTRxQb7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7RfZHM047QS
-v4dk+NoS/zcnwbNDu+97bi5p9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9v
-UJSZSWI4OB9L+KXIPqeCgfYrx+jFzug6EILLGACOTb2oWH+heQC1u+mNr0HZDzTu
-IYEZoDJJKPTEjlbVUjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwC
-W/POuZ6lcg5Ktz885hZo+L7tdEy8W9ViH0Pd
------END CERTIFICATE-----
-
------BEGIN CERTIFICATE-----
-MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh
-MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE
-YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3
-MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRo
-ZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3Mg
-MiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggEN
-ADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCA
-PVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6w
-wdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi
-EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMY
-avx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+
-YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLE
-sNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h
-/t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5
-IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj
-YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD
-ggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNy
-OO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P
-TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ
-HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER
-dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf
-ReYNnyicsbkqWletNw+vHX/bvZ8=
------END CERTIFICATE-----
diff --git a/data/providers/grooveshark.png b/data/providers/grooveshark.png
deleted file mode 100644
index 98f9fa63c..000000000
Binary files a/data/providers/grooveshark.png and /dev/null differ
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index fc87333f6..d62f9a898 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -147,7 +147,6 @@ set(SOURCES
globalsearch/globalsearchsettingspage.cpp
globalsearch/globalsearchsortmodel.cpp
globalsearch/globalsearchview.cpp
- globalsearch/groovesharksearchprovider.cpp
globalsearch/icecastsearchprovider.cpp
globalsearch/librarysearchprovider.cpp
globalsearch/savedradiosearchprovider.cpp
@@ -167,10 +166,6 @@ set(SOURCES
internet/digitally/digitallyimportedsettingspage.cpp
internet/digitally/digitallyimportedurlhandler.cpp
internet/core/geolocator.cpp
- internet/grooveshark/groovesharkradio.cpp
- internet/grooveshark/groovesharkservice.cpp
- internet/grooveshark/groovesharksettingspage.cpp
- internet/grooveshark/groovesharkurlhandler.cpp
internet/icecast/icecastbackend.cpp
internet/icecast/icecastfilterwidget.cpp
internet/icecast/icecastmodel.cpp
@@ -464,7 +459,6 @@ set(HEADERS
globalsearch/globalsearchmodel.h
globalsearch/globalsearchsettingspage.h
globalsearch/globalsearchview.h
- globalsearch/groovesharksearchprovider.h
globalsearch/searchprovider.h
globalsearch/simplesearchprovider.h
globalsearch/soundcloudsearchprovider.h
@@ -476,9 +470,6 @@ set(HEADERS
internet/digitally/digitallyimportedservicebase.h
internet/digitally/digitallyimportedsettingspage.h
internet/core/geolocator.h
- internet/grooveshark/groovesharkservice.h
- internet/grooveshark/groovesharksettingspage.h
- internet/grooveshark/groovesharkurlhandler.h
internet/icecast/icecastbackend.h
internet/icecast/icecastfilterwidget.h
internet/icecast/icecastmodel.h
@@ -694,7 +685,6 @@ set(UI
globalsearch/suggestionwidget.ui
internet/digitally/digitallyimportedsettingspage.ui
- internet/grooveshark/groovesharksettingspage.ui
internet/icecast/icecastfilterwidget.ui
internet/core/internetshowsettingspage.ui
internet/core/internetviewcontainer.ui
diff --git a/src/engines/gstenginepipeline.cpp b/src/engines/gstenginepipeline.cpp
index 7ca19408f..b81791713 100644
--- a/src/engines/gstenginepipeline.cpp
+++ b/src/engines/gstenginepipeline.cpp
@@ -890,19 +890,6 @@ void GstEnginePipeline::SourceSetupCallback(GstURIDecodeBin* bin,
g_object_set(element, "device",
instance->source_device().toLocal8Bit().constData(), nullptr);
}
- if (g_object_class_find_property(G_OBJECT_GET_CLASS(element),
- "extra-headers") &&
- instance->url().host().contains("grooveshark")) {
- // Grooveshark streaming servers will answer with a 400 error 'Bad request'
- // if we don't specify 'Range' field in HTTP header.
- // Maybe it could be useful in some other cases, but for now, I prefer to
- // keep this grooveshark specific.
- GstStructure* headers;
- headers = gst_structure_new("extra-headers", "Range", G_TYPE_STRING,
- "bytes=0-", nullptr);
- g_object_set(element, "extra-headers", headers, nullptr);
- gst_structure_free(headers);
- }
if (g_object_class_find_property(G_OBJECT_GET_CLASS(element),
"extra-headers") &&
instance->url().host().contains("amazonaws.com")) {
diff --git a/src/globalsearch/groovesharksearchprovider.cpp b/src/globalsearch/groovesharksearchprovider.cpp
deleted file mode 100644
index aa96a1c7b..000000000
--- a/src/globalsearch/groovesharksearchprovider.cpp
+++ /dev/null
@@ -1,132 +0,0 @@
-/* This file is part of Clementine.
- Copyright 2011, David Sansome
-
- Clementine 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.
-
- Clementine 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 Clementine. If not, see .
-*/
-
-#include "groovesharksearchprovider.h"
-
-#include
-
-#include "core/application.h"
-#include "core/logging.h"
-#include "covers/albumcoverloader.h"
-#include "internet/grooveshark/groovesharkservice.h"
-
-GroovesharkSearchProvider::GroovesharkSearchProvider(Application* app,
- QObject* parent)
- : SearchProvider(app, parent), service_(nullptr) {}
-
-void GroovesharkSearchProvider::Init(GroovesharkService* service) {
- service_ = service;
- SearchProvider::Init(
- "Grooveshark", "grooveshark", QIcon(":providers/grooveshark.png"),
- WantsDelayedQueries | ArtIsProbablyRemote | CanShowConfig);
-
- connect(service_, SIGNAL(SimpleSearchResults(int, SongList)),
- SLOT(SearchDone(int, SongList)));
- connect(service_, SIGNAL(AlbumSearchResult(int, QList)),
- SLOT(AlbumSearchResult(int, QList)));
- connect(service_, SIGNAL(AlbumSongsLoaded(quint64, SongList)),
- SLOT(AlbumSongsLoaded(quint64, SongList)));
-
- cover_loader_options_.desired_height_ = kArtHeight;
- cover_loader_options_.pad_output_image_ = true;
- cover_loader_options_.scale_output_image_ = true;
-
- connect(app_->album_cover_loader(), SIGNAL(ImageLoaded(quint64, QImage)),
- SLOT(AlbumArtLoaded(quint64, QImage)));
-}
-
-void GroovesharkSearchProvider::SearchAsync(int id, const QString& query) {
- const int service_id = service_->SimpleSearch(query);
- pending_searches_[service_id] = PendingState(id, TokenizeQuery(query));
- ;
-
- const int album_id = service_->SearchAlbums(query);
- pending_searches_[album_id] = PendingState(id, TokenizeQuery(query));
-}
-
-void GroovesharkSearchProvider::SearchDone(int id, const SongList& songs) {
- // Map back to the original id.
- const PendingState state = pending_searches_.take(id);
- const int global_search_id = state.orig_id_;
-
- ResultList ret;
- for (const Song& song : songs) {
- Result result(this);
- result.metadata_ = song;
-
- ret << result;
- }
-
- emit ResultsAvailable(global_search_id, ret);
- MaybeSearchFinished(global_search_id);
-}
-
-void GroovesharkSearchProvider::AlbumSearchResult(
- int id, const QList& albums_ids) {
- // Map back to the original id.
- const PendingState state = pending_searches_.take(id);
- const int global_search_id = state.orig_id_;
- if (albums_ids.isEmpty()) {
- MaybeSearchFinished(global_search_id);
- return;
- }
- for (const quint64 album_id : albums_ids) {
- pending_searches_[album_id] = PendingState(global_search_id, QStringList());
- }
-}
-
-void GroovesharkSearchProvider::MaybeSearchFinished(int id) {
- if (pending_searches_.keys(PendingState(id, QStringList())).isEmpty()) {
- emit SearchFinished(id);
- }
-}
-
-void GroovesharkSearchProvider::LoadArtAsync(int id, const Result& result) {
- quint64 loader_id = app_->album_cover_loader()->LoadImageAsync(
- cover_loader_options_, result.metadata_);
- cover_loader_tasks_[loader_id] = id;
-}
-
-void GroovesharkSearchProvider::AlbumArtLoaded(quint64 id,
- const QImage& image) {
- if (!cover_loader_tasks_.contains(id)) {
- return;
- }
- int original_id = cover_loader_tasks_.take(id);
- emit ArtLoaded(original_id, image);
-}
-
-bool GroovesharkSearchProvider::IsLoggedIn() {
- return (service_ && service_->IsLoggedIn());
-}
-
-void GroovesharkSearchProvider::ShowConfig() { service_->ShowConfig(); }
-
-void GroovesharkSearchProvider::AlbumSongsLoaded(quint64 id,
- const SongList& songs) {
- const PendingState state = pending_searches_.take(id);
- const int global_search_id = state.orig_id_;
- ResultList ret;
- for (const Song& s : songs) {
- Result result(this);
- result.metadata_ = s;
- ret << result;
- }
-
- emit ResultsAvailable(global_search_id, ret);
- MaybeSearchFinished(global_search_id);
-}
diff --git a/src/globalsearch/groovesharksearchprovider.h b/src/globalsearch/groovesharksearchprovider.h
deleted file mode 100644
index c4aedd119..000000000
--- a/src/globalsearch/groovesharksearchprovider.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/* This file is part of Clementine.
- Copyright 2011, David Sansome
-
- Clementine 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.
-
- Clementine 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 Clementine. If not, see .
-*/
-
-#ifndef GROOVESHARKSEARCHPROVIDER_H
-#define GROOVESHARKSEARCHPROVIDER_H
-
-#include "searchprovider.h"
-#include "covers/albumcoverloaderoptions.h"
-#include "internet/grooveshark/groovesharkservice.h"
-
-class AlbumCoverLoader;
-
-class GroovesharkSearchProvider : public SearchProvider {
- Q_OBJECT
-
- public:
- explicit GroovesharkSearchProvider(Application* app, QObject* parent = nullptr);
- void Init(GroovesharkService* service);
-
- // SearchProvider
- void SearchAsync(int id, const QString& query) override;
- void LoadArtAsync(int id, const Result& result) override;
- bool IsLoggedIn() override;
- void ShowConfig() override;
- InternetService* internet_service() override { return service_; }
-
- private slots:
- void SearchDone(int id, const SongList& songs);
- void AlbumSearchResult(int id, const QList& albums_ids);
- void AlbumArtLoaded(quint64 id, const QImage& image);
- void AlbumSongsLoaded(quint64 id, const SongList& songs);
-
- private:
- void MaybeSearchFinished(int id);
-
- GroovesharkService* service_;
- QMap pending_searches_;
-
- AlbumCoverLoaderOptions cover_loader_options_;
- QMap cover_loader_tasks_;
-};
-
-#endif
diff --git a/src/internet/core/internetmodel.cpp b/src/internet/core/internetmodel.cpp
index 09754cd5e..707811d68 100644
--- a/src/internet/core/internetmodel.cpp
+++ b/src/internet/core/internetmodel.cpp
@@ -29,7 +29,6 @@
#include
#include "internet/digitally/digitallyimportedservicebase.h"
-#include "internet/grooveshark/groovesharkservice.h"
#include "internet/icecast/icecastservice.h"
#include "internet/core/internetmimedata.h"
#include "internet/core/internetservice.h"
@@ -90,7 +89,6 @@ InternetModel::InternetModel(Application* app, QObject* parent)
AddService(new DigitallyImportedService(app, this));
AddService(new IcecastService(app, this));
AddService(new JamendoService(app, this));
- AddService(new GroovesharkService(app, this));
AddService(new JazzRadioService(app, this));
AddService(new MagnatuneService(app, this));
AddService(new PodcastService(app, this));
diff --git a/src/internet/grooveshark/groovesharkradio.cpp b/src/internet/grooveshark/groovesharkradio.cpp
deleted file mode 100644
index df5326421..000000000
--- a/src/internet/grooveshark/groovesharkradio.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-/* This file is part of Clementine.
- Copyright 2011, Arnaud Bienner
- Copyright 2014, Krzysztof Sobiecki
- Copyright 2014, John Maguire
-
- Clementine 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.
-
- Clementine 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 Clementine. If not, see .
-*/
-
-#include "groovesharkradio.h"
-
-#include "groovesharkservice.h"
-#include "core/logging.h"
-#include "internet/core/internetplaylistitem.h"
-
-GroovesharkRadio::GroovesharkRadio(GroovesharkService* service)
- : service_(service), tag_id_(0), use_tag_(false), first_time_(true) {}
-
-GroovesharkRadio::GroovesharkRadio(GroovesharkService* service, int tag_id)
- : service_(service), tag_id_(tag_id), use_tag_(true), first_time_(true) {}
-
-void GroovesharkRadio::Load(const QByteArray& data) {}
-
-QByteArray GroovesharkRadio::Save() const { return QByteArray(); }
-
-PlaylistItemList GroovesharkRadio::Generate() {
- PlaylistItemList items;
- if (first_time_) {
- Song song;
- if (use_tag_) {
- song = service_->StartAutoplayTag(tag_id_, autoplay_state_);
- } else {
- song = service_->StartAutoplay(autoplay_state_);
- }
- // If the song url isn't valid, stop here
- if (!song.is_valid()) {
- return items;
- }
- PlaylistItemPtr playlist_item =
- PlaylistItemPtr(new InternetPlaylistItem(service_, song));
- items << playlist_item;
- first_time_ = false;
- }
- Song song = service_->GetAutoplaySong(autoplay_state_);
- if (!song.is_valid()) {
- return items;
- }
- PlaylistItemPtr playlist_item =
- PlaylistItemPtr(new InternetPlaylistItem(service_, song));
- items << playlist_item;
- return items;
-}
diff --git a/src/internet/grooveshark/groovesharkradio.h b/src/internet/grooveshark/groovesharkradio.h
deleted file mode 100644
index b36d9e8b4..000000000
--- a/src/internet/grooveshark/groovesharkradio.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* This file is part of Clementine.
- Copyright 2011, Arnaud Bienner
- Copyright 2014, Krzysztof Sobiecki
- Copyright 2014, John Maguire
-
- Clementine 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.
-
- Clementine 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 Clementine. If not, see .
-*/
-
-#ifndef INTERNET_GROOVESHARK_GROOVESHARKRADIO_H_
-#define INTERNET_GROOVESHARK_GROOVESHARKRADIO_H_
-
-#include "smartplaylists/generator.h"
-
-class GroovesharkService;
-
-class GroovesharkRadio : public smart_playlists::Generator {
- public:
- // Start Grooveshark radio for a particular type of music
- GroovesharkRadio(GroovesharkService* service, int tag_id);
- // Start Grooveshark radio based on last artists and songs you listen to
- explicit GroovesharkRadio(GroovesharkService* service);
-
- QString type() const { return "Grooveshark"; }
- void Load(const QByteArray& data);
- QByteArray Save() const;
- PlaylistItemList Generate();
- PlaylistItemList GenerateMore(int count) { return Generate(); }
- bool is_dynamic() const { return true; }
-
- private:
- GroovesharkService* service_;
- int tag_id_;
- // Boolean to specify if we should use tag. If not, we will used autoplay
- // without tag
- bool use_tag_;
- // For Generate: indicates if it's the first time we generate songs
- bool first_time_;
- QVariantMap autoplay_state_;
-};
-
-#endif // INTERNET_GROOVESHARK_GROOVESHARKRADIO_H_
diff --git a/src/internet/grooveshark/groovesharkservice.cpp b/src/internet/grooveshark/groovesharkservice.cpp
deleted file mode 100644
index b97d4d3c1..000000000
--- a/src/internet/grooveshark/groovesharkservice.cpp
+++ /dev/null
@@ -1,1829 +0,0 @@
-/* This file is part of Clementine.
- Copyright 2011-2014, Arnaud Bienner
- Copyright 2011-2012, 2014, John Maguire
- Copyright 2011, HYPNOTOAD
- Copyright 2011-2012, David Sansome
- Copyright 2014, Antonio Nicolás Pina
- Copyright 2014, Krzysztof Sobiecki
-
- Clementine 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.
-
- Clementine 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 Clementine. If not, see .
- */
-
-#include "groovesharkservice.h"
-
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-
-#include "qtiocompressor.h"
-
-#include "internet/core/internetmodel.h"
-#include "groovesharkradio.h"
-#include "groovesharkurlhandler.h"
-#include "internet/core/searchboxwidget.h"
-
-#include "core/application.h"
-#include "core/closure.h"
-#include "core/database.h"
-#include "core/logging.h"
-#include "core/mergedproxymodel.h"
-#include "core/network.h"
-#include "core/player.h"
-#include "core/scopedtransaction.h"
-#include "core/song.h"
-#include "core/taskmanager.h"
-#include "core/timeconstants.h"
-#include "core/utilities.h"
-#include "globalsearch/globalsearch.h"
-#include "globalsearch/groovesharksearchprovider.h"
-#include "playlist/playlist.h"
-#include "playlist/playlistcontainer.h"
-#include "playlist/playlistmanager.h"
-#include "ui/iconloader.h"
-
-using smart_playlists::Generator;
-using smart_playlists::GeneratorPtr;
-
-// The Grooveshark terms of service require that application keys are not
-// accessible to third parties. Therefore this application key is obfuscated to
-// prevent third parties from viewing it.
-const char* GroovesharkService::kApiKey = "clementineplayer";
-const char* GroovesharkService::kApiSecret =
- "OzLDTB5XqmhkkhxMUK0/Mp5PQgD5O27DTEJa/jtkwEw=";
-
-const char* GroovesharkService::kServiceName = "Grooveshark";
-const char* GroovesharkService::kSettingsGroup = "Grooveshark";
-const char* GroovesharkService::kUrl = "http://api.grooveshark.com/ws/3.0/";
-const char* GroovesharkService::kUrlCover =
- "http://beta.grooveshark.com/static/amazonart/l";
-const char* GroovesharkService::kHomepage = "http://grooveshark.com/";
-
-const int GroovesharkService::kSongSearchLimit = 100;
-const int GroovesharkService::kSongSimpleSearchLimit = 10;
-const int GroovesharkService::kAlbumSearchLimit = 10;
-
-const int GroovesharkService::kSearchDelayMsec = 400;
-
-typedef QPair Param;
-
-GroovesharkService::GroovesharkService(Application* app, InternetModel* parent)
- : InternetService(kServiceName, app, parent, parent),
- url_handler_(new GroovesharkUrlHandler(this, this)),
- next_pending_search_id_(0),
- next_pending_playlist_retrieve_id_(0),
- root_(nullptr),
- search_(nullptr),
- popular_month_(nullptr),
- popular_today_(nullptr),
- stations_(nullptr),
- grooveshark_radio_(nullptr),
- favorites_(nullptr),
- library_(nullptr),
- playlists_parent_(nullptr),
- subscribed_playlists_parent_(nullptr),
- network_(new NetworkAccessManager(this)),
- context_menu_(nullptr),
- create_playlist_(nullptr),
- delete_playlist_(nullptr),
- rename_playlist_(nullptr),
- remove_from_playlist_(nullptr),
- remove_from_favorites_(nullptr),
- remove_from_library_(nullptr),
- get_url_to_share_song_(nullptr),
- get_url_to_share_playlist_(nullptr),
- search_box_(new SearchBoxWidget(this)),
- search_delay_(new QTimer(this)),
- last_search_reply_(nullptr),
- api_key_(QByteArray::fromBase64(kApiSecret)),
- login_state_(LoginState_OtherError),
- task_popular_id_(0),
- task_playlists_id_(0),
- task_search_id_(0) {
- app_->player()->RegisterUrlHandler(url_handler_);
-
- search_delay_->setInterval(kSearchDelayMsec);
- search_delay_->setSingleShot(true);
- connect(search_delay_, SIGNAL(timeout()), SLOT(DoSearch()));
-
- // Get already existing (authenticated) session id, if any
- QSettings s;
- s.beginGroup(GroovesharkService::kSettingsGroup);
- session_id_ = s.value("sessionid").toString();
- username_ = s.value("username").toString();
-
- GroovesharkSearchProvider* search_provider =
- new GroovesharkSearchProvider(app_, this);
- search_provider->Init(this);
- app_->global_search()->AddProvider(search_provider);
-
- // Init secret: this code is ugly, but that's good as nobody is supposed to
- // wonder what it does
- QByteArray ba =
- QByteArray::fromBase64(QCoreApplication::applicationName().toLatin1());
- int n = api_key_.length(), n2 = ba.length();
- for (int i = 0; i < n; i++) api_key_[i] = api_key_[i] ^ ba[i % n2];
-
- connect(search_box_, SIGNAL(TextChanged(QString)), SLOT(Search(QString)));
-}
-
-GroovesharkService::~GroovesharkService() {}
-
-QStandardItem* GroovesharkService::CreateRootItem() {
- root_ = new QStandardItem(QIcon(":providers/grooveshark.png"), kServiceName);
- root_->setData(true, InternetModel::Role_CanLazyLoad);
- root_->setData(InternetModel::PlayBehaviour_DoubleClickAction,
- InternetModel::Role_PlayBehaviour);
- return root_;
-}
-
-void GroovesharkService::LazyPopulate(QStandardItem* item) {
- switch (item->data(InternetModel::Role_Type).toInt()) {
- case InternetModel::Type_Service: {
- EnsureConnected();
- break;
- }
- default:
- break;
- }
-}
-
-void GroovesharkService::ShowConfig() {
- app_->OpenSettingsDialogAtPage(SettingsDialog::Page_Grooveshark);
-}
-
-QWidget* GroovesharkService::HeaderWidget() const {
- if (IsLoggedIn()) return search_box_;
- return nullptr;
-}
-
-void GroovesharkService::Search(const QString& text, bool now) {
- pending_search_ = text;
-
- // If there is no text (e.g. user cleared search box), we don't need to do a
- // real query that will return nothing: we can clear the playlist now
- if (text.isEmpty()) {
- search_delay_->stop();
- ClearSearchResults();
- return;
- }
-
- if (now) {
- search_delay_->stop();
- DoSearch();
- } else {
- search_delay_->start();
- }
-}
-
-int GroovesharkService::SimpleSearch(const QString& query) {
- QList parameters;
- parameters << Param("query", query) << Param("country", "")
- << Param("limit", QString::number(kSongSimpleSearchLimit))
- << Param("offset", "");
-
- int id = next_pending_search_id_++;
- QNetworkReply* reply = CreateRequest("getSongSearchResults", parameters);
- NewClosure(reply, SIGNAL(finished()), this,
- SLOT(SimpleSearchFinished(QNetworkReply*, int)), reply, id);
- return id;
-}
-
-void GroovesharkService::SimpleSearchFinished(QNetworkReply* reply, int id) {
- reply->deleteLater();
-
- QVariantMap result = ExtractResult(reply);
- SongList songs = ExtractSongs(result);
- emit SimpleSearchResults(id, songs);
-}
-
-int GroovesharkService::SearchAlbums(const QString& query) {
- QList parameters;
- parameters << Param("query", query) << Param("country", "")
- << Param("limit", QString::number(kAlbumSearchLimit));
-
- QNetworkReply* reply = CreateRequest("getAlbumSearchResults", parameters);
-
- const int id = next_pending_search_id_++;
-
- NewClosure(reply, SIGNAL(finished()), this,
- SLOT(SearchAlbumsFinished(QNetworkReply*, int)), reply, id);
-
- return id;
-}
-
-void GroovesharkService::SearchAlbumsFinished(QNetworkReply* reply, int id) {
- reply->deleteLater();
-
- QVariantMap result = ExtractResult(reply);
- QVariantList albums = result["albums"].toList();
-
- QList ret;
- for (const QVariant& v : albums) {
- quint64 album_id = v.toMap()["AlbumID"].toULongLong();
- GetAlbumSongs(album_id);
- ret << album_id;
- }
-
- emit AlbumSearchResult(id, ret);
-}
-
-void GroovesharkService::GetAlbumSongs(quint64 album_id) {
- QList parameters;
- parameters << Param("albumID", album_id) << Param("country", "");
- QNetworkReply* reply = CreateRequest("getAlbumSongs", parameters);
- NewClosure(reply, SIGNAL(finished()), this,
- SLOT(GetAlbumSongsFinished(QNetworkReply*, quint64)), reply,
- album_id);
-}
-
-void GroovesharkService::GetAlbumSongsFinished(QNetworkReply* reply,
- quint64 album_id) {
- reply->deleteLater();
- QVariantMap result = ExtractResult(reply);
- SongList songs = ExtractSongs(result);
-
- emit AlbumSongsLoaded(album_id, songs);
-}
-
-void GroovesharkService::DoSearch() {
- if (!task_search_id_) {
- task_search_id_ =
- app_->task_manager()->StartTask(tr("Searching on Grooveshark"));
- }
-
- ClearSearchResults();
-
- QList parameters;
- parameters << Param("query", pending_search_) << Param("country", "")
- << Param("limit", QString::number(kSongSearchLimit))
- << Param("offset", "");
- last_search_reply_ = CreateRequest("getSongSearchResults", parameters);
- NewClosure(last_search_reply_, SIGNAL(finished()), this,
- SLOT(SearchSongsFinished(QNetworkReply*)), last_search_reply_);
-}
-
-void GroovesharkService::SearchSongsFinished(QNetworkReply* reply) {
- reply->deleteLater();
-
- if (reply != last_search_reply_) return;
-
- QVariantMap result = ExtractResult(reply);
- SongList songs = ExtractSongs(result);
- app_->task_manager()->SetTaskFinished(task_search_id_);
- task_search_id_ = 0;
-
- // Fill results list
- if (!search_) return;
- for (const Song& song : songs) {
- QStandardItem* child = CreateSongItem(song);
- search_->appendRow(child);
- }
-
- QModelIndex index = model()->merged_model()->mapFromSource(search_->index());
- ScrollToIndex(index);
-}
-
-void GroovesharkService::InitCountry() {
- if (!country_.isEmpty()) return;
- // Get country info
- QNetworkReply* reply_country = CreateRequest("getCountry", QList());
- if (WaitForReply(reply_country)) {
- country_ = ExtractResult(reply_country);
- }
- reply_country->deleteLater();
-}
-
-QUrl GroovesharkService::GetStreamingUrlFromSongId(const QString& song_id,
- const QString& artist_id,
- QString* server_id,
- QString* stream_key,
- qint64* length_nanosec) {
- QList parameters;
-
- InitCountry();
- parameters << Param("songID", song_id) << Param("country", country_);
- QNetworkReply* reply = CreateRequest("getSubscriberStreamKey", parameters);
-
- // Wait for the reply
- bool reply_has_timeouted = !WaitForReply(reply);
- reply->deleteLater();
- if (reply_has_timeouted) return QUrl();
-
- QVariantMap result = ExtractResult(reply);
- server_id->clear();
- server_id->append(result["StreamServerID"].toString());
- stream_key->clear();
- stream_key->append(result["StreamKey"].toString());
- *length_nanosec = result["uSecs"].toLongLong() * 1000;
- // Keep in mind that user has request to listen to this song
- last_songs_ids_.append(song_id.toInt());
- last_artists_ids_.append(artist_id.toInt());
- // If we have enough ids, remove the old ones
- if (last_songs_ids_.size() > 100) last_songs_ids_.removeFirst();
- if (last_artists_ids_.size() > 100) last_artists_ids_.removeFirst();
-
- return QUrl(result["url"].toString());
-}
-
-void GroovesharkService::Login(const QString& username,
- const QString& password) {
- // To login, we first need to create a session. Next, we will authenticate
- // this session using the user's username and password (for now, we just keep
- // them in mind)
- username_ = username;
- password_ = QCryptographicHash::hash(password.toLocal8Bit(),
- QCryptographicHash::Md5).toHex();
-
- QList parameters;
- QNetworkReply* reply = CreateRequest("startSession", parameters, true);
-
- NewClosure(reply, SIGNAL(finished()), this,
- SLOT(SessionCreated(QNetworkReply*)), reply);
-}
-
-void GroovesharkService::SessionCreated(QNetworkReply* reply) {
- reply->deleteLater();
-
- if (reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() !=
- 200) {
- emit StreamError("Failed to create Grooveshark session: " +
- reply->errorString());
- emit LoginFinished(false);
- return;
- }
-
- QVariantMap result = ExtractResult(reply);
- if (!result["success"].toBool()) {
- qLog(Error) << "Grooveshark returned an error during session creation";
- }
- session_id_ = result["sessionID"].toString();
- qLog(Debug) << "Session ID returned: " << session_id_;
-
- AuthenticateSession();
-}
-
-void GroovesharkService::AuthenticateSession() {
- QList parameters;
- parameters << Param("login", username_) << Param("password", password_);
-
- QNetworkReply* reply = CreateRequest("authenticate", parameters, true);
- NewClosure(reply, SIGNAL(finished()), this,
- SLOT(Authenticated(QNetworkReply*)), reply);
-}
-
-void GroovesharkService::Authenticated(QNetworkReply* reply) {
- reply->deleteLater();
-
- QVariantMap result = ExtractResult(reply);
- // Check if the user has been authenticated correctly
- QString error;
- if (!result["success"].toBool() || result["UserID"].toInt() == 0) {
- error = tr("Invalid username and/or password");
- login_state_ = LoginState_AuthFailed;
- } else if (!result["IsAnywhere"].toBool() || !result["IsPremium"].toBool()) {
- error = tr("User %1 doesn't have a Grooveshark Anywhere account")
- .arg(username_);
- login_state_ = LoginState_NoPremium;
- }
- if (!error.isEmpty()) {
- QMessageBox::warning(nullptr, tr("Grooveshark login error"), error,
- QMessageBox::Close);
- ResetSessionId();
- emit LoginFinished(false);
- return;
- }
- login_state_ = LoginState_LoggedIn;
- user_id_ = result["UserID"].toString();
- emit LoginFinished(true);
- EnsureItemsCreated();
-}
-
-void GroovesharkService::ClearSearchResults() {
- if (search_) search_->removeRows(0, search_->rowCount());
-}
-
-void GroovesharkService::Logout() {
- ResetSessionId();
- RemoveItems();
-}
-
-void GroovesharkService::RemoveItems() {
- root_->removeRows(0, root_->rowCount());
- // 'search', 'favorites', 'popular', ... items were root's children, and have
- // been deleted: we should update these now invalid pointers
- search_ = nullptr;
- popular_month_ = nullptr;
- popular_today_ = nullptr;
- library_ = nullptr;
- favorites_ = nullptr;
- subscribed_playlists_parent_ = nullptr;
- stations_ = nullptr;
- grooveshark_radio_ = nullptr;
- playlists_parent_ = nullptr;
- playlists_.clear();
- subscribed_playlists_parent_ = nullptr;
- subscribed_playlists_.clear();
- // Cancel any pending requests and mark tasks as finished, in case they
- // weren't
- // finished yet.
- pending_retrieve_playlists_.clear();
- app_->task_manager()->SetTaskFinished(task_playlists_id_);
- app_->task_manager()->SetTaskFinished(task_popular_id_);
- app_->task_manager()->SetTaskFinished(task_search_id_);
-}
-
-void GroovesharkService::ResetSessionId() {
- QSettings s;
- s.beginGroup(GroovesharkService::kSettingsGroup);
-
- session_id_.clear();
- s.setValue("sessionid", session_id_);
-}
-
-void GroovesharkService::ShowContextMenu(const QPoint& global_pos) {
- EnsureMenuCreated();
-
- // Check if we should display actions
- bool display_delete_playlist_action = false,
- display_remove_from_playlist_action = false,
- display_remove_from_favorites_action = false,
- display_remove_from_library_action = false,
- display_share_song_url = false, display_share_playlist_url = false;
-
- QModelIndex index(model()->current_index());
-
- if (index.data(InternetModel::Role_Type).toInt() ==
- InternetModel::Type_UserPlaylist &&
- index.data(Role_PlaylistType).toInt() == UserPlaylist) {
- display_delete_playlist_action = true;
- }
- // We check parent's type (instead of index type) because we want to enable
- // 'remove' actions for items which are inside a playlist
- int parent_type = index.parent().data(InternetModel::Role_Type).toInt();
- if (parent_type == InternetModel::Type_UserPlaylist) {
- int parent_playlist_type = index.parent().data(Role_PlaylistType).toInt();
- if (parent_playlist_type == UserFavorites)
- display_remove_from_favorites_action = true;
- else if (parent_playlist_type == UserLibrary)
- display_remove_from_library_action = true;
- else if (parent_playlist_type == UserPlaylist)
- display_remove_from_playlist_action = true;
- }
- delete_playlist_->setVisible(display_delete_playlist_action);
- // If we can delete this playlist, we can also rename it
- rename_playlist_->setVisible(display_delete_playlist_action);
- remove_from_playlist_->setVisible(display_remove_from_playlist_action);
- remove_from_favorites_->setVisible(display_remove_from_favorites_action);
- remove_from_library_->setVisible(display_remove_from_library_action);
-
- // Check if we can display actions to get URL for sharing songs/playlists:
- // - share song
- if (index.data(InternetModel::Role_Type).toInt() ==
- InternetModel::Type_Track) {
- display_share_song_url = true;
- current_song_id_ =
- ExtractSongId(index.data(InternetModel::Role_Url).toUrl());
- }
- get_url_to_share_song_->setVisible(display_share_song_url);
-
- // - share playlist
- if (index.data(InternetModel::Role_Type).toInt() ==
- InternetModel::Type_UserPlaylist &&
- index.data(Role_UserPlaylistId).isValid()) {
- display_share_playlist_url = true;
- current_playlist_id_ = index.data(Role_UserPlaylistId).toInt();
- } else if (parent_type == InternetModel::Type_UserPlaylist &&
- index.parent().data(Role_UserPlaylistId).isValid()) {
- display_share_playlist_url = true;
- current_playlist_id_ = index.parent().data(Role_UserPlaylistId).toInt();
- }
- get_url_to_share_playlist_->setVisible(display_share_playlist_url);
-
- context_menu_->popup(global_pos);
-}
-
-void GroovesharkService::EnsureMenuCreated() {
- if (!context_menu_) {
- context_menu_ = new QMenu;
- context_menu_->addActions(GetPlaylistActions());
- create_playlist_ = context_menu_->addAction(
- IconLoader::Load("list-add"), tr("Create a new Grooveshark playlist"),
- this, SLOT(CreateNewPlaylist()));
- delete_playlist_ = context_menu_->addAction(
- IconLoader::Load("edit-delete"), tr("Delete Grooveshark playlist"),
- this, SLOT(DeleteCurrentPlaylist()));
- rename_playlist_ = context_menu_->addAction(
- IconLoader::Load("edit-rename"), tr("Rename Grooveshark playlist"),
- this, SLOT(RenameCurrentPlaylist()));
- context_menu_->addSeparator();
- remove_from_playlist_ = context_menu_->addAction(
- IconLoader::Load("list-remove"), tr("Remove from playlist"), this,
- SLOT(RemoveCurrentFromPlaylist()));
- remove_from_favorites_ = context_menu_->addAction(
- IconLoader::Load("list-remove"), tr("Remove from favorites"), this,
- SLOT(RemoveCurrentFromFavorites()));
- remove_from_library_ = context_menu_->addAction(
- IconLoader::Load("list-remove"), tr("Remove from My Music"), this,
- SLOT(RemoveCurrentFromLibrary()));
- get_url_to_share_song_ =
- context_menu_->addAction(tr("Get a URL to share this Grooveshark song"),
- this, SLOT(GetCurrentSongUrlToShare()));
- get_url_to_share_playlist_ = context_menu_->addAction(
- tr("Get a URL to share this Grooveshark playlist"), this,
- SLOT(GetCurrentPlaylistUrlToShare()));
- context_menu_->addSeparator();
- context_menu_->addAction(IconLoader::Load("download"),
- tr("Open %1 in browser").arg("grooveshark.com"),
- this, SLOT(Homepage()));
- context_menu_->addAction(IconLoader::Load("view-refresh"), tr("Refresh"),
- this, SLOT(RefreshItems()));
- context_menu_->addSeparator();
- context_menu_->addAction(IconLoader::Load("configure"),
- tr("Configure Grooveshark..."), this,
- SLOT(ShowConfig()));
- }
-}
-
-void GroovesharkService::Homepage() {
- QDesktopServices::openUrl(QUrl(kHomepage));
-}
-
-void GroovesharkService::RefreshItems() {
- RemoveItems();
- EnsureItemsCreated();
-}
-
-void GroovesharkService::EnsureItemsCreated() {
- if (IsLoggedIn() && !search_) {
- search_ =
- new QStandardItem(IconLoader::Load("edit-find"), tr("Search results"));
- search_->setToolTip(
- tr("Start typing something on the search box above to "
- "fill this search results list"));
- search_->setData(InternetModel::PlayBehaviour_MultipleItems,
- InternetModel::Role_PlayBehaviour);
- root_->appendRow(search_);
-
- QStandardItem* popular =
- new QStandardItem(QIcon(":/star-on.png"), tr("Popular songs"));
- root_->appendRow(popular);
-
- popular_month_ = new QStandardItem(QIcon(":/star-on.png"),
- tr("Popular songs of the Month"));
- popular_month_->setData(InternetModel::Type_UserPlaylist,
- InternetModel::Role_Type);
- popular_month_->setData(true, InternetModel::Role_CanLazyLoad);
- popular_month_->setData(InternetModel::PlayBehaviour_MultipleItems,
- InternetModel::Role_PlayBehaviour);
- popular->appendRow(popular_month_);
-
- popular_today_ =
- new QStandardItem(QIcon(":/star-on.png"), tr("Popular songs today"));
- popular_today_->setData(InternetModel::Type_UserPlaylist,
- InternetModel::Role_Type);
- popular_today_->setData(true, InternetModel::Role_CanLazyLoad);
- popular_today_->setData(InternetModel::PlayBehaviour_MultipleItems,
- InternetModel::Role_PlayBehaviour);
- popular->appendRow(popular_today_);
-
- QStandardItem* radios_divider =
- new QStandardItem(QIcon(":last.fm/icon_radio.png"), tr("Radios"));
- root_->appendRow(radios_divider);
-
- stations_ =
- new QStandardItem(QIcon(":last.fm/icon_radio.png"), tr("Stations"));
- stations_->setData(InternetModel::Type_UserPlaylist,
- InternetModel::Role_Type);
- stations_->setData(true, InternetModel::Role_CanLazyLoad);
- radios_divider->appendRow(stations_);
-
- grooveshark_radio_ = new QStandardItem(QIcon(":last.fm/icon_radio.png"),
- tr("Grooveshark radio"));
- grooveshark_radio_->setToolTip(
- tr("Listen to Grooveshark songs based on what you've listened to "
- "previously"));
- grooveshark_radio_->setData(InternetModel::Type_SmartPlaylist,
- InternetModel::Role_Type);
- radios_divider->appendRow(grooveshark_radio_);
-
- library_ =
- new QStandardItem(IconLoader::Load("folder-sound"), tr("My Music"));
- library_->setData(InternetModel::Type_UserPlaylist,
- InternetModel::Role_Type);
- library_->setData(UserLibrary, Role_PlaylistType);
- library_->setData(true, InternetModel::Role_CanLazyLoad);
- library_->setData(true, InternetModel::Role_CanBeModified);
- library_->setData(InternetModel::PlayBehaviour_MultipleItems,
- InternetModel::Role_PlayBehaviour);
- root_->appendRow(library_);
-
- favorites_ =
- new QStandardItem(QIcon(":/last.fm/love.png"), tr("Favorites"));
- favorites_->setData(InternetModel::Type_UserPlaylist,
- InternetModel::Role_Type);
- favorites_->setData(UserFavorites, Role_PlaylistType);
- favorites_->setData(true, InternetModel::Role_CanLazyLoad);
- favorites_->setData(true, InternetModel::Role_CanBeModified);
- favorites_->setData(InternetModel::PlayBehaviour_MultipleItems,
- InternetModel::Role_PlayBehaviour);
- root_->appendRow(favorites_);
-
- playlists_parent_ = new QStandardItem(tr("Playlists"));
- root_->appendRow(playlists_parent_);
-
- subscribed_playlists_parent_ =
- new QStandardItem(tr("Subscribed playlists"));
- root_->appendRow(subscribed_playlists_parent_);
-
- RetrieveUserFavorites();
- RetrieveUserLibrarySongs();
- RetrieveUserPlaylists();
- RetrieveSubscribedPlaylists();
- RetrieveAutoplayTags();
- RetrievePopularSongs();
- }
-}
-
-void GroovesharkService::EnsureConnected() {
- if (session_id_.isEmpty()) {
- ShowConfig();
- } else {
- EnsureItemsCreated();
- }
-}
-
-QStandardItem* GroovesharkService::CreatePlaylistItem(
- const QString& playlist_name, int playlist_id) {
- QStandardItem* item = new QStandardItem(playlist_name);
- item->setData(InternetModel::Type_UserPlaylist, InternetModel::Role_Type);
- item->setData(UserPlaylist, Role_PlaylistType);
- item->setData(true, InternetModel::Role_CanLazyLoad);
- item->setData(true, InternetModel::Role_CanBeModified);
- item->setData(InternetModel::PlayBehaviour_MultipleItems,
- InternetModel::Role_PlayBehaviour);
- item->setData(playlist_id, Role_UserPlaylistId);
- return item;
-}
-
-void GroovesharkService::RetrieveUserPlaylists() {
- task_playlists_id_ =
- app_->task_manager()->StartTask(tr("Retrieving Grooveshark playlists"));
- QNetworkReply* reply = CreateRequest("getUserPlaylists", QList());
-
- NewClosure(reply, SIGNAL(finished()), this,
- SLOT(UserPlaylistsRetrieved(QNetworkReply*)), reply);
-}
-
-void GroovesharkService::UserPlaylistsRetrieved(QNetworkReply* reply) {
- reply->deleteLater();
-
- QVariantMap result = ExtractResult(reply);
- QList playlists = ExtractPlaylistInfo(result);
-
- for (const PlaylistInfo& playlist_info : playlists) {
- int playlist_id = playlist_info.id_;
- const QString& playlist_name = playlist_info.name_;
- QStandardItem* playlist_item =
- CreatePlaylistItem(playlist_name, playlist_id);
- playlists_parent_->appendRow(playlist_item);
-
- // Keep in mind this playlist
- playlists_.insert(playlist_id,
- PlaylistInfo(playlist_id, playlist_name, playlist_item));
-
- // Request playlist's songs
- RefreshPlaylist(playlist_id);
- }
-
- if (playlists.isEmpty()) {
- app_->task_manager()->SetTaskFinished(task_playlists_id_);
- }
-}
-
-void GroovesharkService::PlaylistSongsRetrieved(QNetworkReply* reply,
- int playlist_id,
- int request_id) {
- reply->deleteLater();
-
- if (!pending_retrieve_playlists_.remove(request_id)) {
- // This request has been canceled. Stop here
- return;
- }
- PlaylistInfo* playlist_info = subscribed_playlists_.contains(playlist_id)
- ? &subscribed_playlists_[playlist_id]
- : &playlists_[playlist_id];
- playlist_info->item_->removeRows(0, playlist_info->item_->rowCount());
-
- QVariantMap result = ExtractResult(reply);
- SongList songs = ExtractSongs(result);
- SortSongsAlphabeticallyIfNeeded(&songs);
-
- for (const Song& song : songs) {
- QStandardItem* child = CreateSongItem(song);
- child->setData(playlist_info->id_, Role_UserPlaylistId);
- child->setData(true, InternetModel::Role_CanBeModified);
-
- playlist_info->item_->appendRow(child);
- }
-
- // Keep in mind this playlist
- playlist_info->songs_ids_ = ExtractSongsIds(result);
-
- if (pending_retrieve_playlists_.isEmpty()) {
- app_->task_manager()->SetTaskFinished(task_playlists_id_);
- }
-}
-
-void GroovesharkService::RetrieveUserFavorites() {
- int task_id = app_->task_manager()->StartTask(
- tr("Retrieving Grooveshark favorites songs"));
- QNetworkReply* reply = CreateRequest("getUserFavoriteSongs", QList());
-
- NewClosure(reply, SIGNAL(finished()), this,
- SLOT(UserFavoritesRetrieved(QNetworkReply*, int)), reply, task_id);
-}
-
-void GroovesharkService::UserFavoritesRetrieved(QNetworkReply* reply,
- int task_id) {
- reply->deleteLater();
- app_->task_manager()->SetTaskFinished(task_id);
-
- if (!favorites_) {
- // The use probably logged out before the response arrived.
- return;
- }
-
- favorites_->removeRows(0, favorites_->rowCount());
-
- QVariantMap result = ExtractResult(reply);
- SongList songs = ExtractSongs(result);
- SortSongsAlphabeticallyIfNeeded(&songs);
-
- for (const Song& song : songs) {
- QStandardItem* child = CreateSongItem(song);
- child->setData(true, InternetModel::Role_CanBeModified);
-
- favorites_->appendRow(child);
- }
-}
-
-void GroovesharkService::RetrieveUserLibrarySongs() {
- int task_id = app_->task_manager()->StartTask(
- tr("Retrieving Grooveshark My Music songs"));
- QNetworkReply* reply = CreateRequest("getUserLibrarySongs", QList());
-
- NewClosure(reply, SIGNAL(finished()), this,
- SLOT(UserLibrarySongsRetrieved(QNetworkReply*, int)), reply,
- task_id);
-}
-
-void GroovesharkService::UserLibrarySongsRetrieved(QNetworkReply* reply,
- int task_id) {
- reply->deleteLater();
- app_->task_manager()->SetTaskFinished(task_id);
-
- if (!library_) {
- // The use probably logged out before the response arrived.
- return;
- }
-
- library_->removeRows(0, library_->rowCount());
-
- QVariantMap result = ExtractResult(reply);
- SongList songs = ExtractSongs(result);
- SortSongsAlphabeticallyIfNeeded(&songs);
-
- for (const Song& song : songs) {
- QStandardItem* child = CreateSongItem(song);
- child->setData(true, InternetModel::Role_CanBeModified);
-
- library_->appendRow(child);
- }
-}
-
-void GroovesharkService::RetrievePopularSongs() {
- task_popular_id_ =
- app_->task_manager()->StartTask(tr("Getting Grooveshark popular songs"));
- RetrievePopularSongsMonth();
- RetrievePopularSongsToday();
-}
-
-void GroovesharkService::RetrievePopularSongsMonth() {
- QList parameters;
- parameters << Param("limit", QString::number(kSongSearchLimit));
- QNetworkReply* reply = CreateRequest("getPopularSongsMonth", parameters);
- NewClosure(reply, SIGNAL(finished()), this,
- SLOT(PopularSongsMonthRetrieved(QNetworkReply*)), reply);
-}
-
-void GroovesharkService::PopularSongsMonthRetrieved(QNetworkReply* reply) {
- reply->deleteLater();
- QVariantMap result = ExtractResult(reply);
- SongList songs = ExtractSongs(result);
-
- app_->task_manager()->IncreaseTaskProgress(task_popular_id_, 50, 100);
- if (app_->task_manager()->GetTaskProgress(task_popular_id_) >= 100) {
- app_->task_manager()->SetTaskFinished(task_popular_id_);
- }
-
- if (!popular_month_) return;
-
- for (const Song& song : songs) {
- QStandardItem* child = CreateSongItem(song);
- popular_month_->appendRow(child);
- }
-}
-
-void GroovesharkService::RetrievePopularSongsToday() {
- QList parameters;
- parameters << Param("limit", QString::number(kSongSearchLimit));
- QNetworkReply* reply = CreateRequest("getPopularSongsToday", parameters);
- NewClosure(reply, SIGNAL(finished()), this,
- SLOT(PopularSongsTodayRetrieved(QNetworkReply*)), reply);
-}
-
-void GroovesharkService::PopularSongsTodayRetrieved(QNetworkReply* reply) {
- reply->deleteLater();
- QVariantMap result = ExtractResult(reply);
- SongList songs = ExtractSongs(result);
-
- app_->task_manager()->IncreaseTaskProgress(task_popular_id_, 50, 100);
- if (app_->task_manager()->GetTaskProgress(task_popular_id_) >= 100) {
- app_->task_manager()->SetTaskFinished(task_popular_id_);
- }
-
- if (!popular_today_) return;
-
- for (const Song& song : songs) {
- QStandardItem* child = CreateSongItem(song);
- popular_today_->appendRow(child);
- }
-}
-
-void GroovesharkService::RetrieveSubscribedPlaylists() {
- QNetworkReply* reply =
- CreateRequest("getUserPlaylistsSubscribed", QList());
- NewClosure(reply, SIGNAL(finished()), this,
- SLOT(SubscribedPlaylistsRetrieved(QNetworkReply*)), reply);
-}
-
-void GroovesharkService::SubscribedPlaylistsRetrieved(QNetworkReply* reply) {
- reply->deleteLater();
-
- QVariantMap result = ExtractResult(reply);
- QList playlists = ExtractPlaylistInfo(result);
-
- for (const PlaylistInfo& playlist_info : playlists) {
- int playlist_id = playlist_info.id_;
- const QString& playlist_name = playlist_info.name_;
-
- QStandardItem* playlist_item =
- CreatePlaylistItem(playlist_name, playlist_id);
- // Refine some playlist properties that should be different for subscribed
- // playlists
- playlist_item->setData(SubscribedPlaylist, Role_PlaylistType);
- playlist_item->setData(false, InternetModel::Role_CanBeModified);
-
- subscribed_playlists_.insert(
- playlist_id, PlaylistInfo(playlist_id, playlist_name, playlist_item));
- subscribed_playlists_parent_->appendRow(playlist_item);
-
- // Request playlist's songs
- RefreshPlaylist(playlist_id);
- }
-}
-
-void GroovesharkService::RetrieveAutoplayTags() {
- QNetworkReply* reply = CreateRequest("getAutoplayTags", QList());
- NewClosure(reply, SIGNAL(finished()), this,
- SLOT(AutoplayTagsRetrieved(QNetworkReply*)), reply);
-}
-
-void GroovesharkService::AutoplayTagsRetrieved(QNetworkReply* reply) {
- reply->deleteLater();
- QVariantMap result = ExtractResult(reply);
- QVariantMap::const_iterator it;
- if (!stations_) return;
- for (it = result.constBegin(); it != result.constEnd(); ++it) {
- int id = it.key().toInt();
- QString name = it.value().toString().toLower();
- // Names received aren't very nice: make them more user friendly to display
- name.replace("_", " ");
- name[0] = name[0].toUpper();
-
- QStandardItem* item =
- new QStandardItem(QIcon(":last.fm/icon_radio.png"), name);
- item->setData(InternetModel::Type_SmartPlaylist, InternetModel::Role_Type);
- item->setData(InternetModel::PlayBehaviour_SingleItem,
- InternetModel::Role_PlayBehaviour);
- item->setData(id, Role_UserPlaylistId);
-
- stations_->appendRow(item);
- }
-}
-
-Song GroovesharkService::StartAutoplayTag(int tag_id,
- QVariantMap& autoplay_state) {
- QList parameters;
- parameters << Param("tagID", tag_id);
- QNetworkReply* reply = CreateRequest("startAutoplayTag", parameters);
-
- bool reply_has_timeouted = !WaitForReply(reply);
- reply->deleteLater();
- if (reply_has_timeouted) return Song();
-
- QVariantMap result = ExtractResult(reply);
- autoplay_state = result["autoplayState"].toMap();
- return ExtractSong(result["nextSong"].toMap());
-}
-
-Song GroovesharkService::StartAutoplay(QVariantMap& autoplay_state) {
- QList parameters;
- QVariantList artists_ids_qvariant;
- for (int artist_id : last_artists_ids_) {
- artists_ids_qvariant << QVariant(artist_id);
- }
- QVariantList songs_ids_qvariant;
- for (int song_id : last_songs_ids_) {
- songs_ids_qvariant << QVariant(song_id);
- }
- parameters << Param("artistIDs", artists_ids_qvariant)
- << Param("songIDs", songs_ids_qvariant);
- QNetworkReply* reply = CreateRequest("startAutoplay", parameters);
-
- bool reply_has_timeouted = !WaitForReply(reply);
- reply->deleteLater();
- if (reply_has_timeouted) return Song();
-
- QVariantMap result = ExtractResult(reply);
- autoplay_state = result["autoplayState"].toMap();
- return ExtractSong(result["nextSong"].toMap());
-}
-
-Song GroovesharkService::GetAutoplaySong(QVariantMap& autoplay_state) {
- QList parameters;
- parameters << Param("autoplayState", autoplay_state);
- QNetworkReply* reply = CreateRequest("getAutoplaySong", parameters);
-
- bool reply_has_timeouted = !WaitForReply(reply);
- reply->deleteLater();
- if (reply_has_timeouted) return Song();
-
- QVariantMap result = ExtractResult(reply);
- autoplay_state = result["autoplayState"].toMap();
- return ExtractSong(result["nextSong"].toMap());
-}
-
-void GroovesharkService::MarkStreamKeyOver30Secs(const QString& stream_key,
- const QString& server_id) {
- QList parameters;
- parameters << Param("streamKey", stream_key)
- << Param("streamServerID", server_id);
-
- QNetworkReply* reply = CreateRequest("markStreamKeyOver30Secs", parameters);
- NewClosure(reply, SIGNAL(finished()), this,
- SLOT(StreamMarked(QNetworkReply*)), reply);
-}
-
-void GroovesharkService::StreamMarked(QNetworkReply* reply) {
- reply->deleteLater();
- QVariantMap result = ExtractResult(reply);
- if (!result["success"].toBool()) {
- qLog(Warning) << "Grooveshark markStreamKeyOver30Secs failed";
- }
-}
-
-void GroovesharkService::MarkSongComplete(const QString& song_id,
- const QString& stream_key,
- const QString& server_id) {
- QList parameters;
- parameters << Param("songID", song_id) << Param("streamKey", stream_key)
- << Param("streamServerID", server_id);
-
- QNetworkReply* reply = CreateRequest("markSongComplete", parameters);
- NewClosure(reply, SIGNAL(finished()), this,
- SLOT(SongMarkedAsComplete(QNetworkReply*)), reply);
-}
-
-void GroovesharkService::SongMarkedAsComplete(QNetworkReply* reply) {
- reply->deleteLater();
- QVariantMap result = ExtractResult(reply);
- if (!result["success"].toBool()) {
- qLog(Warning) << "Grooveshark markSongComplete failed";
- }
-}
-
-void GroovesharkService::ItemDoubleClicked(QStandardItem* item) {
- if (item == root_) {
- EnsureConnected();
- }
-}
-
-GeneratorPtr GroovesharkService::CreateGenerator(QStandardItem* item) {
- GeneratorPtr ret;
- if (!item || item->data(InternetModel::Role_Type).toInt() !=
- InternetModel::Type_SmartPlaylist) {
- return ret;
- }
-
- if (item == grooveshark_radio_) {
- if (last_artists_ids_.isEmpty()) {
- QMessageBox::warning(nullptr, tr("Error"),
- tr("To start Grooveshark radio, you should first "
- "listen to a few other Grooveshark songs"));
- return ret;
- }
- ret = GeneratorPtr(new GroovesharkRadio(this));
- } else {
- int tag_id = item->data(Role_UserPlaylistId).toInt();
- ret = GeneratorPtr(new GroovesharkRadio(this, tag_id));
- }
- return ret;
-}
-
-void GroovesharkService::DropMimeData(const QMimeData* data,
- const QModelIndex& index) {
- if (!data) {
- return;
- }
-
- // Get Grooveshark songs' ids, if any.
- QList data_songs_ids = ExtractSongsIds(data->urls());
- if (data_songs_ids.isEmpty()) {
- // There is none: probably means user didn't dropped Grooveshark songs
- return;
- }
-
- int type = index.data(InternetModel::Role_Type).toInt();
- int parent_type = index.parent().data(InternetModel::Role_Type).toInt();
-
- if (type == InternetModel::Type_UserPlaylist ||
- parent_type == InternetModel::Type_UserPlaylist) {
- int playlist_type = index.data(Role_PlaylistType).toInt();
- int parent_playlist_type = index.parent().data(Role_PlaylistType).toInt();
- // If dropped on Favorites list
- if (playlist_type == UserFavorites ||
- parent_playlist_type == UserFavorites) {
- for (int song_id : data_songs_ids) {
- AddUserFavoriteSong(song_id);
- }
- } else if (playlist_type == UserLibrary ||
- parent_playlist_type == UserLibrary) {
- // FIXME: Adding songs to user libray doesn't work atm, but the problem
- // seems to be on Grooveshark server side, as it returns success=true
- // when calling addUserLibrarySongs with a valid song id.
- // So this code is deactivated for now to not mislead user
- // AddUserLibrarySongs(data_songs_ids);
- } else { // Dropped on a normal playlist
- // Get the playlist
- int playlist_id = index.data(Role_UserPlaylistId).toInt();
- if (!playlists_.contains(playlist_id)) {
- return;
- }
- // Get the current playlist's songs
- PlaylistInfo playlist = playlists_[playlist_id];
- QList songs_ids = playlist.songs_ids_;
- songs_ids << data_songs_ids;
-
- SetPlaylistSongs(playlist_id, songs_ids);
- }
- }
-}
-
-QList GroovesharkService::playlistitem_actions(const Song& song) {
- // Clear previous actions
- while (!playlistitem_actions_.isEmpty()) {
- QAction* action = playlistitem_actions_.takeFirst();
- delete action->menu();
- delete action;
- }
-
- // Create a 'add to favorites' action
- QAction* add_to_favorites = new QAction(
- QIcon(":/last.fm/love.png"), tr("Add to Grooveshark favorites"), this);
- connect(add_to_favorites, SIGNAL(triggered()),
- SLOT(AddCurrentSongToUserFavorites()));
- playlistitem_actions_.append(add_to_favorites);
-
- // FIXME: as explained above, adding songs to library doesn't work currently
- // QAction* add_to_library = new QAction(IconLoader::Load("folder-sound"),
- // tr("Add to Grooveshark My Music"),
- // this);
- // connect(add_to_library, SIGNAL(triggered()),
- // SLOT(AddCurrentSongToUserLibrary()));
- // playlistitem_actions_.append(add_to_library);
-
- // Create a menu with 'add to playlist' actions for each Grooveshark playlist
- QAction* add_to_playlists = new QAction(
- IconLoader::Load("list-add"), tr("Add to Grooveshark playlists"), this);
- QMenu* playlists_menu = new QMenu();
- for (const PlaylistInfo& playlist_info : playlists_.values()) {
- QAction* add_to_playlist = new QAction(playlist_info.name_, this);
- add_to_playlist->setData(playlist_info.id_);
- playlists_menu->addAction(add_to_playlist);
- }
- connect(playlists_menu, SIGNAL(triggered(QAction*)),
- SLOT(AddCurrentSongToPlaylist(QAction*)));
- add_to_playlists->setMenu(playlists_menu);
- playlistitem_actions_.append(add_to_playlists);
-
- QAction* share_song =
- new QAction(tr("Get a URL to share this Grooveshark song"), this);
- connect(share_song, SIGNAL(triggered()), SLOT(GetCurrentSongUrlToShare()));
- playlistitem_actions_.append(share_song);
-
- // Keep in mind the current song id
- current_song_id_ = ExtractSongId(song.url());
-
- return playlistitem_actions_;
-}
-
-void GroovesharkService::GetCurrentSongUrlToShare() {
- GetSongUrlToShare(current_song_id_);
-}
-
-void GroovesharkService::GetSongUrlToShare(int song_id) {
- QList parameters;
- parameters << Param("songID", song_id);
- QNetworkReply* reply = CreateRequest("getSongURLFromSongID", parameters);
-
- NewClosure(reply, SIGNAL(finished()), this,
- SLOT(SongUrlToShareReceived(QNetworkReply*)), reply);
-}
-
-void GroovesharkService::SongUrlToShareReceived(QNetworkReply* reply) {
- reply->deleteLater();
-
- QVariantMap result = ExtractResult(reply);
- if (!result["url"].isValid()) return;
- QString url = result["url"].toString();
- ShowUrlBox(tr("Grooveshark song's URL"), url);
-}
-
-void GroovesharkService::GetCurrentPlaylistUrlToShare() {
- GetPlaylistUrlToShare(current_playlist_id_);
-}
-
-void GroovesharkService::GetPlaylistUrlToShare(int playlist_id) {
- QList parameters;
- parameters << Param("playlistID", playlist_id);
- QNetworkReply* reply =
- CreateRequest("getPlaylistURLFromPlaylistID", parameters);
-
- NewClosure(reply, SIGNAL(finished()), this,
- SLOT(PlaylistUrlToShareReceived(QNetworkReply*)), reply);
-}
-
-void GroovesharkService::PlaylistUrlToShareReceived(QNetworkReply* reply) {
- reply->deleteLater();
- QVariantMap result = ExtractResult(reply);
- if (!result["url"].isValid()) return;
- QString url = result["url"].toString();
- ShowUrlBox(tr("Grooveshark playlist's URL"), url);
-}
-
-void GroovesharkService::AddCurrentSongToPlaylist(QAction* action) {
- int playlist_id = action->data().toInt();
- if (!playlists_.contains(playlist_id)) {
- return;
- }
- // Get the current playlist's songs
- PlaylistInfo playlist = playlists_[playlist_id];
- QList songs_ids = playlist.songs_ids_;
- songs_ids << current_song_id_;
-
- SetPlaylistSongs(playlist_id, songs_ids);
-}
-
-void GroovesharkService::SetPlaylistSongs(int playlist_id,
- const QList& songs_ids) {
- // If we are still retrieving playlists songs, don't update playlist: don't
- // take the risk to erase all (not yet retrieved) playlist's songs.
- if (!pending_retrieve_playlists_.isEmpty()) return;
- int task_id =
- app_->task_manager()->StartTask(tr("Update Grooveshark playlist"));
-
- QList parameters;
-
- // Convert song ids to QVariant
- QVariantList songs_ids_qvariant;
- for (int song_id : songs_ids) {
- songs_ids_qvariant << QVariant(song_id);
- }
-
- parameters << Param("playlistID", playlist_id)
- << Param("songIDs", songs_ids_qvariant);
-
- QNetworkReply* reply = CreateRequest("setPlaylistSongs", parameters);
-
- NewClosure(reply, SIGNAL(finished()), this,
- SLOT(PlaylistSongsSet(QNetworkReply*, int, int)), reply,
- playlist_id, task_id);
-}
-
-void GroovesharkService::PlaylistSongsSet(QNetworkReply* reply, int playlist_id,
- int task_id) {
- reply->deleteLater();
- app_->task_manager()->SetTaskFinished(task_id);
-
- QVariantMap result = ExtractResult(reply);
- if (!result["success"].toBool()) {
- qLog(Warning) << "Grooveshark setPlaylistSongs failed";
- return;
- }
-
- RefreshPlaylist(playlist_id);
-}
-
-void GroovesharkService::RefreshPlaylist(int playlist_id) {
- QList parameters;
- parameters << Param("playlistID", playlist_id);
- QNetworkReply* reply = CreateRequest("getPlaylistSongs", parameters);
- int id = next_pending_playlist_retrieve_id_++;
- NewClosure(reply, SIGNAL(finished()), this,
- SLOT(PlaylistSongsRetrieved(QNetworkReply*, int, int)), reply,
- playlist_id, id);
-
- pending_retrieve_playlists_.insert(id);
-}
-
-void GroovesharkService::CreateNewPlaylist() {
- QString name =
- QInputDialog::getText(nullptr, tr("Create a new Grooveshark playlist"),
- tr("Name"), QLineEdit::Normal);
- if (name.isEmpty()) {
- return;
- }
-
- QList parameters;
- parameters << Param("name", name) << Param("songIDs", QVariantList());
- QNetworkReply* reply = CreateRequest("createPlaylist", parameters);
- NewClosure(reply, SIGNAL(finished()), this,
- SLOT(NewPlaylistCreated(QNetworkReply*, const QString&)), reply,
- name);
-}
-
-void GroovesharkService::NewPlaylistCreated(QNetworkReply* reply,
- const QString& name) {
- reply->deleteLater();
- QVariantMap result = ExtractResult(reply);
- if (!result["success"].toBool() || !result["playlistID"].isValid()) {
- qLog(Warning) << "Grooveshark createPlaylist failed";
- return;
- }
-
- int playlist_id = result["playlistID"].toInt();
- QStandardItem* new_playlist_item = CreatePlaylistItem(name, playlist_id);
- PlaylistInfo playlist_info(playlist_id, name, new_playlist_item);
- playlist_info.item_ = new_playlist_item;
- playlists_parent_->appendRow(new_playlist_item);
- playlists_.insert(playlist_id, playlist_info);
-}
-
-void GroovesharkService::DeleteCurrentPlaylist() {
- if (model()->current_index().data(InternetModel::Role_Type).toInt() !=
- InternetModel::Type_UserPlaylist) {
- return;
- }
-
- int playlist_id = model()->current_index().data(Role_UserPlaylistId).toInt();
- DeletePlaylist(playlist_id);
-}
-
-void GroovesharkService::DeletePlaylist(int playlist_id) {
- if (!playlists_.contains(playlist_id)) {
- return;
- }
-
- std::unique_ptr confirmation_dialog(
- new QMessageBox(QMessageBox::Question, tr("Delete Grooveshark playlist"),
- tr("Are you sure you want to delete this playlist?"),
- QMessageBox::Yes | QMessageBox::Cancel));
- if (confirmation_dialog->exec() != QMessageBox::Yes) {
- return;
- }
-
- QList parameters;
- parameters << Param("playlistID", playlist_id);
- QNetworkReply* reply = CreateRequest("deletePlaylist", parameters);
- NewClosure(reply, SIGNAL(finished()), this,
- SLOT(PlaylistDeleted(QNetworkReply*, int)), reply, playlist_id);
-}
-
-void GroovesharkService::PlaylistDeleted(QNetworkReply* reply,
- int playlist_id) {
- reply->deleteLater();
- QVariantMap result = ExtractResult(reply);
- if (!result["success"].toBool()) {
- qLog(Warning) << "Grooveshark deletePlaylist failed";
- return;
- }
- if (!playlists_.contains(playlist_id)) {
- return;
- }
- PlaylistInfo playlist_info = playlists_.take(playlist_id);
- playlists_parent_->removeRow(playlist_info.item_->row());
-}
-
-void GroovesharkService::RenameCurrentPlaylist() {
- const QModelIndex& index(model()->current_index());
-
- if (index.data(InternetModel::Role_Type).toInt() !=
- InternetModel::Type_UserPlaylist ||
- index.data(Role_PlaylistType).toInt() != UserPlaylist) {
- return;
- }
-
- const int playlist_id = index.data(Role_UserPlaylistId).toInt();
- RenamePlaylist(playlist_id);
-}
-
-void GroovesharkService::RenamePlaylist(int playlist_id) {
- if (!playlists_.contains(playlist_id)) {
- return;
- }
- const QString& old_name = playlists_[playlist_id].name_;
- QString new_name =
- QInputDialog::getText(nullptr, tr("Rename \"%1\" playlist").arg(old_name),
- tr("Name"), QLineEdit::Normal, old_name);
- if (new_name.isEmpty()) {
- return;
- }
-
- QList parameters;
- parameters << Param("playlistID", playlist_id) << Param("name", new_name);
- QNetworkReply* reply = CreateRequest("renamePlaylist", parameters);
- NewClosure(reply, SIGNAL(finished()), this,
- SLOT(PlaylistRenamed(QNetworkReply*, int, const QString&)), reply,
- playlist_id, new_name);
-}
-
-void GroovesharkService::PlaylistRenamed(QNetworkReply* reply, int playlist_id,
- const QString& new_name) {
- reply->deleteLater();
- QVariantMap result = ExtractResult(reply);
- if (!result["success"].toBool()) {
- qLog(Warning) << "Grooveshark renamePlaylist failed";
- return;
- }
- if (!playlists_.contains(playlist_id)) {
- return;
- }
- PlaylistInfo& playlist_info = playlists_[playlist_id];
- playlist_info.name_ = new_name;
- playlist_info.item_->setText(new_name);
-}
-
-void GroovesharkService::AddUserFavoriteSong(int song_id) {
- int task_id = app_->task_manager()->StartTask(tr("Adding song to favorites"));
- QList parameters;
- parameters << Param("songID", song_id);
- QNetworkReply* reply = CreateRequest("addUserFavoriteSong", parameters);
- NewClosure(reply, SIGNAL(finished()), this,
- SLOT(UserFavoriteSongAdded(QNetworkReply*, int)), reply, task_id);
-}
-
-void GroovesharkService::UserFavoriteSongAdded(QNetworkReply* reply,
- int task_id) {
- reply->deleteLater();
- app_->task_manager()->SetTaskFinished(task_id);
-
- QVariantMap result = ExtractResult(reply);
- if (!result["success"].toBool()) {
- qLog(Warning) << "Grooveshark addUserFavoriteSong failed";
- return;
- }
- // Refresh user's favorites list
- RetrieveUserFavorites();
-}
-
-void GroovesharkService::AddUserLibrarySongs(const QList& songs_ids) {
- int task_id = app_->task_manager()->StartTask(tr("Adding song to My Music"));
- QList parameters;
-
- // Convert songs ids to QVariant
- QVariantList songs_ids_qvariant;
- for (int song_id : songs_ids) {
- songs_ids_qvariant << QVariant(song_id);
- }
- QVariantList albums_ids_qvariant;
- QVariantList artists_ids_qvariant;
-
- parameters << Param("songIDs", songs_ids_qvariant);
- // We do not support albums and artist parameters for now, but they are
- // required
- parameters << Param("albumIDs", albums_ids_qvariant);
- parameters << Param("artistIDs", artists_ids_qvariant);
- QNetworkReply* reply = CreateRequest("addUserLibrarySongs", parameters);
- NewClosure(reply, SIGNAL(finished()), this,
- SLOT(UserLibrarySongAdded(QNetworkReply*, int)), reply, task_id);
-}
-
-void GroovesharkService::UserLibrarySongAdded(QNetworkReply* reply,
- int task_id) {
- reply->deleteLater();
- app_->task_manager()->SetTaskFinished(task_id);
-
- QVariantMap result = ExtractResult(reply);
- if (!result["success"].toBool()) {
- qLog(Warning) << "Grooveshark addUserLibrarySongs failed";
- return;
- }
- // Refresh user's library list
- RetrieveUserLibrarySongs();
-}
-
-void GroovesharkService::RemoveCurrentFromPlaylist() {
- const QModelIndexList& indexes(model()->selected_indexes());
- QMap> playlists_songs_ids;
- for (const QModelIndex& index : indexes) {
- if (index.parent().data(InternetModel::Role_Type).toInt() !=
- InternetModel::Type_UserPlaylist) {
- continue;
- }
-
- int playlist_id = index.data(Role_UserPlaylistId).toInt();
- int song_id = ExtractSongId(index.data(InternetModel::Role_Url).toUrl());
- if (song_id) {
- playlists_songs_ids[playlist_id] << song_id;
- }
- }
-
- for (QMap>::const_iterator it =
- playlists_songs_ids.constBegin();
- it != playlists_songs_ids.constEnd(); ++it) {
- RemoveFromPlaylist(it.key(), it.value());
- }
-}
-
-void GroovesharkService::RemoveFromPlaylist(
- int playlist_id, const QList& songs_ids_to_remove) {
- if (!playlists_.contains(playlist_id)) {
- return;
- }
-
- QList songs_ids = playlists_[playlist_id].songs_ids_;
- for (const int song_id : songs_ids_to_remove) {
- songs_ids.removeOne(song_id);
- }
-
- SetPlaylistSongs(playlist_id, songs_ids);
-}
-
-void GroovesharkService::RemoveCurrentFromFavorites() {
- const QModelIndexList& indexes(model()->selected_indexes());
- QList songs_ids;
- for (const QModelIndex& index : indexes) {
- if (index.parent().data(Role_PlaylistType).toInt() != UserFavorites) {
- continue;
- }
-
- int song_id = ExtractSongId(index.data(InternetModel::Role_Url).toUrl());
- if (song_id) {
- songs_ids << song_id;
- }
- }
-
- RemoveFromFavorites(songs_ids);
-}
-
-void GroovesharkService::RemoveFromFavorites(
- const QList& songs_ids_to_remove) {
- if (songs_ids_to_remove.isEmpty()) return;
-
- int task_id =
- app_->task_manager()->StartTask(tr("Removing songs from favorites"));
- QList parameters;
-
- // Convert song ids to QVariant
- QVariantList songs_ids_qvariant;
- for (const int song_id : songs_ids_to_remove) {
- songs_ids_qvariant << QVariant(song_id);
- }
-
- parameters << Param("songIDs", songs_ids_qvariant);
- QNetworkReply* reply = CreateRequest("removeUserFavoriteSongs", parameters);
- NewClosure(reply, SIGNAL(finished()), this,
- SLOT(SongsRemovedFromFavorites(QNetworkReply*, int)), reply,
- task_id);
-}
-
-void GroovesharkService::SongsRemovedFromFavorites(QNetworkReply* reply,
- int task_id) {
- app_->task_manager()->SetTaskFinished(task_id);
- reply->deleteLater();
-
- QVariantMap result = ExtractResult(reply);
- if (!result["success"].toBool()) {
- qLog(Warning) << "Grooveshark removeUserFavoriteSongs failed";
- return;
- }
- RetrieveUserFavorites();
-}
-
-void GroovesharkService::RemoveCurrentFromLibrary() {
- const QModelIndexList& indexes(model()->selected_indexes());
- QList songs_ids;
-
- for (const QModelIndex& index : indexes) {
- if (index.parent().data(Role_PlaylistType).toInt() != UserLibrary) {
- continue;
- }
-
- int song_id = ExtractSongId(index.data(InternetModel::Role_Url).toUrl());
- if (song_id) {
- songs_ids << song_id;
- }
- }
-
- RemoveFromLibrary(songs_ids);
-}
-
-void GroovesharkService::RemoveFromLibrary(
- const QList& songs_ids_to_remove) {
- if (songs_ids_to_remove.isEmpty()) return;
-
- int task_id =
- app_->task_manager()->StartTask(tr("Removing songs from My Music"));
- QList parameters;
-
- // Convert song ids to QVariant
- QVariantList songs_ids_qvariant;
- for (const int song_id : songs_ids_to_remove) {
- songs_ids_qvariant << QVariant(song_id);
- }
- QVariantList albums_ids_qvariant;
- QVariantList artists_ids_qvariant;
-
- parameters << Param("songIDs", songs_ids_qvariant);
- // We do not support albums and artist parameters for now, but they are
- // required
- parameters << Param("albumIDs", albums_ids_qvariant);
- parameters << Param("artistIDs", artists_ids_qvariant);
-
- QNetworkReply* reply = CreateRequest("removeUserLibrarySongs", parameters);
- NewClosure(reply, SIGNAL(finished()), this,
- SLOT(SongsRemovedFromLibrary(QNetworkReply*, int)), reply,
- task_id);
-}
-
-void GroovesharkService::SongsRemovedFromLibrary(QNetworkReply* reply,
- int task_id) {
- app_->task_manager()->SetTaskFinished(task_id);
- reply->deleteLater();
-
- QVariantMap result = ExtractResult(reply);
- if (!result["success"].toBool()) {
- qLog(Warning) << "Grooveshark removeUserLibrarySongs failed";
- return;
- }
- RetrieveUserLibrarySongs();
-}
-
-QNetworkReply* GroovesharkService::CreateRequest(const QString& method_name,
- const QList& params,
- bool use_https) {
- QVariantMap request_params;
- request_params.insert("method", method_name);
-
- QVariantMap header;
- header.insert("wsKey", kApiKey);
- if (session_id_.isEmpty()) {
- if (method_name != "startSession") {
- // It's normal to not have a session_id when calling startSession.
- // Otherwise it's not, so print a warning message
- qLog(Warning) << "Session ID is empty: will not be added to query";
- }
- } else {
- header.insert("sessionID", session_id_);
- }
- request_params.insert("header", header);
-
- QVariantMap parameters;
- for (const Param& param : params) {
- parameters.insert(param.first, param.second);
- }
- request_params.insert("parameters", parameters);
-
- QJson::Serializer serializer;
- QByteArray post_params = serializer.serialize(request_params);
-
- QUrl url(kUrl);
- if (use_https) {
- url.setScheme("https");
- }
- url.setQueryItems(
- QList>() << QPair(
- "sig", Utilities::HmacMd5(api_key_, post_params).toHex()));
- QNetworkRequest req(url);
- QNetworkReply* reply = network_->post(req, post_params);
-
- if (use_https) {
- connect(reply, SIGNAL(sslErrors(QList)),
- SLOT(RequestSslErrors(QList)));
- }
-
- return reply;
-}
-
-void GroovesharkService::RequestSslErrors(const QList& errors) {
- QNetworkReply* reply = qobject_cast(sender());
-
- for (const QSslError& error : errors) {
- emit StreamError("SSL error occurred in Grooveshark request for " +
- reply->url().toString() + ": " + error.errorString());
- }
-}
-
-bool GroovesharkService::WaitForReply(QNetworkReply* reply) {
- QEventLoop event_loop;
- QTimer timeout_timer;
- connect(&timeout_timer, SIGNAL(timeout()), &event_loop, SLOT(quit()));
- connect(reply, SIGNAL(finished()), &event_loop, SLOT(quit()));
- timeout_timer.start(10000);
- event_loop.exec();
- if (!timeout_timer.isActive()) {
- qLog(Error) << "Grooveshark request timeout";
- return false;
- }
- timeout_timer.stop();
- return true;
-}
-
-QVariantMap GroovesharkService::ExtractResult(QNetworkReply* reply) {
- QJson::Parser parser;
- bool ok;
- QVariantMap result = parser.parse(reply, &ok).toMap();
- if (!ok) {
- qLog(Error) << "Error while parsing Grooveshark result";
- }
- QVariantList errors = result["errors"].toList();
- QVariantList::iterator it;
- for (it = errors.begin(); it != errors.end(); ++it) {
- QVariantMap error = (*it).toMap();
- qLog(Error) << "Grooveshark error: (" << error["code"].toInt() << ") "
- << error["message"].toString();
- switch (error["code"].toInt()) {
- case 100: // User auth required
- case 102: // User premium required
- case 300: // Session required
- // These errors can happen if session_id is obsolete (e.g. we haven't
- // use
- // it for more than two weeks): force the user to login again
- Logout();
- break;
- }
- }
- return result["result"].toMap();
-}
-
-namespace {
-bool CompareSongs(const QVariant& song1, const QVariant& song2) {
- QMap song1_map = song1.toMap();
- QMap song2_map = song2.toMap();
- int song1_sort = song1_map["Sort"].toInt();
- int song2_sort = song2_map["Sort"].toInt();
- if (song1_sort == song2_sort) {
- // Favorite songs have a "TSFavorited" and (currently) no "Sort" field
- return song1_map["TSFavorited"].toString() <
- song2_map["TSFavorited"].toString();
- }
- return song1_sort < song2_sort;
-}
-} // namespace
-
-SongList GroovesharkService::ExtractSongs(const QVariantMap& result) {
- QVariantList result_songs = result["songs"].toList();
- qStableSort(result_songs.begin(), result_songs.end(), CompareSongs);
- SongList songs;
- for (int i = 0; i < result_songs.size(); ++i) {
- QVariantMap result_song = result_songs[i].toMap();
- songs << ExtractSong(result_song);
- }
- return songs;
-}
-
-Song GroovesharkService::ExtractSong(const QVariantMap& result_song) {
- Song song;
- if (!result_song.isEmpty()) {
- int song_id = result_song["SongID"].toInt();
- QString song_name;
- if (result_song.contains("SongName")) {
- song_name = result_song["SongName"].toString();
- } else {
- song_name = result_song["Name"].toString();
- }
- int artist_id = result_song["ArtistID"].toInt();
- QString artist_name = result_song["ArtistName"].toString();
- int album_id = result_song["AlbumID"].toInt();
- QString album_name = result_song["AlbumName"].toString();
- qint64 duration = result_song["EstimateDuration"].toInt() * kNsecPerSec;
- song.Init(song_name, artist_name, album_name, duration);
- QVariant cover = result_song["CoverArtFilename"];
- if (cover.isValid()) {
- song.set_art_automatic(QString(kUrlCover) + cover.toString());
- }
- QVariant track_number = result_song["TrackNum"];
- if (track_number.isValid()) {
- song.set_track(track_number.toInt());
- }
- QVariant year = result_song["Year"];
- if (year.isValid()) {
- song.set_year(year.toInt());
- }
- // Special kind of URL: because we need to request a stream key for each
- // play, we generate a fake URL for now, and we will create a real streaming
- // URL when user will actually play the song (through url handler)
- // URL is grooveshark://artist_id/album_id/song_id
- song.set_url(
- QUrl(QString("grooveshark://%1/%2/%3").arg(artist_id).arg(album_id).arg(
- song_id)));
- }
- return song;
-}
-
-QList GroovesharkService::ExtractSongsIds(const QVariantMap& result) {
- QVariantList result_songs = result["songs"].toList();
- QList songs_ids;
- for (int i = 0; i < result_songs.size(); ++i) {
- QVariantMap result_song = result_songs[i].toMap();
- int song_id = result_song["SongID"].toInt();
- songs_ids << song_id;
- }
- return songs_ids;
-}
-
-QList GroovesharkService::ExtractSongsIds(const QList& urls) {
- QList songs_ids;
- for (const QUrl& url : urls) {
- int song_id = ExtractSongId(url);
- if (song_id) {
- songs_ids << song_id;
- }
- }
- return songs_ids;
-}
-
-int GroovesharkService::ExtractSongId(const QUrl& url) {
- if (url.scheme() == "grooveshark") {
- QStringList ids = url.toString().remove("grooveshark://").split("/");
- if (ids.size() == 3)
- // Returns the third id: song id
- return ids[2].toInt();
- }
- return 0;
-}
-
-QList GroovesharkService::ExtractPlaylistInfo(
- const QVariantMap& result) {
- QVariantList playlists_qvariant = result["playlists"].toList();
-
- QList playlists;
-
- // Get playlists info
- for (const QVariant& playlist_qvariant : playlists_qvariant) {
- QVariantMap playlist = playlist_qvariant.toMap();
- int playlist_id = playlist["PlaylistID"].toInt();
- QString playlist_name = playlist["PlaylistName"].toString();
-
- playlists << PlaylistInfo(playlist_id, playlist_name);
- }
-
- // Sort playlists by name
- qSort(playlists.begin(), playlists.end());
-
- return playlists;
-}
-
-void GroovesharkService::SortSongsAlphabeticallyIfNeeded(SongList* songs) const {
- QSettings s;
- s.beginGroup(GroovesharkService::kSettingsGroup);
- const bool sort_songs_alphabetically = s.value("sort_alphabetically").toBool();
- if (sort_songs_alphabetically) {
- Song::SortSongsListAlphabetically(songs);
- }
-}
diff --git a/src/internet/grooveshark/groovesharkservice.h b/src/internet/grooveshark/groovesharkservice.h
deleted file mode 100644
index 17c16c42f..000000000
--- a/src/internet/grooveshark/groovesharkservice.h
+++ /dev/null
@@ -1,338 +0,0 @@
-/* This file is part of Clementine.
- Copyright 2011-2014, Arnaud Bienner
- Copyright 2011-2012, 2014, John Maguire
- Copyright 2012, David Sansome
- Copyright 2014, Krzysztof Sobiecki
-
- Clementine 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.
-
- Clementine 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 Clementine. If not, see .
- */
-
-#ifndef INTERNET_GROOVESHARK_GROOVESHARKSERVICE_H_
-#define INTERNET_GROOVESHARK_GROOVESHARKSERVICE_H_
-
-#include "internet/core/internetmodel.h"
-#include "internet/core/internetservice.h"
-
-#include
-
-class GroovesharkUrlHandler;
-class NetworkAccessManager;
-class Playlist;
-class SearchBoxWidget;
-
-class QMenu;
-class QNetworkReply;
-class QNetworkRequest;
-class QSortFilterProxyModel;
-
-class GroovesharkService : public InternetService {
- Q_OBJECT
-
- public:
- GroovesharkService(Application* app, InternetModel* parent);
- ~GroovesharkService();
-
- enum Role {
- Role_UserPlaylistId = InternetModel::RoleCount,
- Role_PlaylistType
- };
-
- enum PlaylistType {
- UserPlaylist = Qt::UserRole,
- // Favorites and Library list are like playlists, but we want to do special
- // treatments in some cases
- UserFavorites,
- UserLibrary,
- SubscribedPlaylist
- };
-
- // Values are persisted - don't change.
- enum LoginState {
- LoginState_LoggedIn = 1,
- LoginState_AuthFailed = 2,
- LoginState_NoPremium = 3,
- LoginState_OtherError = 4
- };
-
- // Internet Service methods
- QStandardItem* CreateRootItem();
- void LazyPopulate(QStandardItem* parent);
-
- void ItemDoubleClicked(QStandardItem* item);
- smart_playlists::GeneratorPtr CreateGenerator(QStandardItem* item);
- void DropMimeData(const QMimeData* data, const QModelIndex& index);
- QList playlistitem_actions(const Song& song);
- void ShowContextMenu(const QPoint& global_pos);
- QWidget* HeaderWidget() const;
-
- // User should be logged in to be able to generate streaming urls
- QUrl GetStreamingUrlFromSongId(const QString& song_id,
- const QString& artist_id, QString* server_id,
- QString* stream_key, qint64* length_nanosec);
- void Login(const QString& username, const QString& password);
- void Logout();
- bool IsLoggedIn() const { return !session_id_.isEmpty(); }
- void RetrieveUserPlaylists();
- void RetrieveUserFavorites();
- void RetrieveUserLibrarySongs();
- void RetrievePopularSongs();
- void RetrievePopularSongsMonth();
- void RetrievePopularSongsToday();
- void RetrieveSubscribedPlaylists();
- void RetrieveAutoplayTags();
- void SetPlaylistSongs(int playlist_id, const QList& songs_ids);
- void RemoveFromPlaylist(int playlist_id,
- const QList& songs_ids_to_remove);
- // Refresh playlist_id playlist , or create it if it doesn't exist
- void RefreshPlaylist(int playlist_id);
- void DeletePlaylist(int playlist_id);
- void RenamePlaylist(int playlist_id);
- void AddUserFavoriteSong(int song_id);
- void RemoveFromFavorites(const QList& songs_ids_to_remove);
- void AddUserLibrarySongs(const QList& songs_ids);
- void RemoveFromLibrary(const QList& songs_ids_to_remove);
- void GetSongUrlToShare(int song_id);
- void GetPlaylistUrlToShare(int playlist_id);
- // Start autoplay for the given tag_id, fill the autoplay_state, returns a
- // first song to play
- Song StartAutoplayTag(int tag_id, QVariantMap& autoplay_state);
- Song StartAutoplay(QVariantMap& autoplay_state);
- // Get another autoplay song. autoplay_state is the autoplay_state received
- // from StartAutoplayTag
- Song GetAutoplaySong(QVariantMap& autoplay_state);
- void MarkStreamKeyOver30Secs(const QString& stream_key,
- const QString& server_id);
- void MarkSongComplete(const QString& song_id, const QString& stream_key,
- const QString& server_id);
-
- // Persisted in the settings and updated on each Login().
- LoginState login_state() const { return login_state_; }
- const QString& session_id() { return session_id_; }
-
- int SimpleSearch(const QString& query);
- int SearchAlbums(const QString& query);
- void GetAlbumSongs(quint64 album_id);
-
- static const char* kServiceName;
- static const char* kSettingsGroup;
-
- signals:
- void LoginFinished(bool success);
- void SimpleSearchResults(int id, SongList songs);
- // AlbumSearchResult emits the search id and the Grooveshark ids of the
- // albums found. Albums' songs will be loaded asynchronously and
- // AlbumSongsLoaded will be emitted, containing the actual Albums' songs.
- void AlbumSearchResult(int id, QList albums_ids);
- void AlbumSongsLoaded(quint64 id, SongList songs);
-
- public slots:
- void Search(const QString& text, bool now = false);
- void ShowConfig();
- // Refresh all Grooveshark's items, and re-fill them
- void RefreshItems();
-
- protected:
- struct PlaylistInfo {
- PlaylistInfo() {}
- PlaylistInfo(int id, QString name, QStandardItem* item = nullptr)
- : id_(id), name_(name), item_(item) {}
-
- bool operator<(const PlaylistInfo other) const {
- return name_.localeAwareCompare(other.name_) < 0;
- }
-
- int id_;
- QString name_;
- QStandardItem* item_;
- QList songs_ids_;
- };
-
- private slots:
- void SessionCreated(QNetworkReply* reply);
- void DoSearch();
- void SearchSongsFinished(QNetworkReply* reply);
- void SimpleSearchFinished(QNetworkReply* reply, int id);
- void SearchAlbumsFinished(QNetworkReply* reply, int id);
- void GetAlbumSongsFinished(QNetworkReply* reply, quint64 album_id);
- void Authenticated(QNetworkReply* reply);
- void UserPlaylistsRetrieved(QNetworkReply* reply);
- void UserFavoritesRetrieved(QNetworkReply* reply, int task_id);
- void UserLibrarySongsRetrieved(QNetworkReply* reply, int task_id);
- void PopularSongsMonthRetrieved(QNetworkReply* reply);
- void PopularSongsTodayRetrieved(QNetworkReply* reply);
- void SubscribedPlaylistsRetrieved(QNetworkReply* reply);
- void AutoplayTagsRetrieved(QNetworkReply* reply);
- void PlaylistSongsRetrieved(QNetworkReply* reply, int playlist_id, int request_id);
- void PlaylistSongsSet(QNetworkReply* reply, int playlist_id, int task_id);
- void CreateNewPlaylist();
- void NewPlaylistCreated(QNetworkReply* reply, const QString& name);
- void DeleteCurrentPlaylist();
- void RenameCurrentPlaylist();
- void PlaylistDeleted(QNetworkReply* reply, int playlist_id);
- void PlaylistRenamed(QNetworkReply* reply, int playlist_id,
- const QString& new_name);
- void AddCurrentSongToUserFavorites() {
- AddUserFavoriteSong(current_song_id_);
- }
- void AddCurrentSongToUserLibrary() {
- AddUserLibrarySongs(QList() << current_song_id_);
- }
- void AddCurrentSongToPlaylist(QAction* action);
- void UserFavoriteSongAdded(QNetworkReply* reply, int task_id);
- void UserLibrarySongAdded(QNetworkReply* reply, int task_id);
- void GetCurrentSongUrlToShare();
- void SongUrlToShareReceived(QNetworkReply* reply);
- void GetCurrentPlaylistUrlToShare();
- void PlaylistUrlToShareReceived(QNetworkReply* reply);
- void RemoveCurrentFromPlaylist();
- void RemoveCurrentFromFavorites();
- void RemoveCurrentFromLibrary();
- void SongsRemovedFromFavorites(QNetworkReply* reply, int task_id);
- void SongsRemovedFromLibrary(QNetworkReply* reply, int task_id);
- void StreamMarked(QNetworkReply* reply);
- void SongMarkedAsComplete(QNetworkReply* reply);
-
- void RequestSslErrors(const QList& errors);
-
- void Homepage();
-
- private:
- void EnsureMenuCreated();
- void EnsureItemsCreated();
- void RemoveItems();
- void EnsureConnected();
- void ClearSearchResults();
-
- // Create a playlist item, with data set as excepted. Doesn't fill the item
- // with songs rows.
- QStandardItem* CreatePlaylistItem(const QString& playlist_name,
- int playlist_id);
-
- void AuthenticateSession();
- void InitCountry();
-
- // Create a request for the given method, with the given params.
- // If need_authentication is true, add session_id to params.
- // Returns the reply object created
- QNetworkReply* CreateRequest(const QString& method_name,
- const QList>& params,
- bool use_https = false);
- // Convenient function which block until 'reply' replies, or timeout after 10
- // seconds. Returns false if reply has timeouted
- bool WaitForReply(QNetworkReply* reply);
- // Convenient function for extracting result from reply
- QVariantMap ExtractResult(QNetworkReply* reply);
- // Convenient function for extracting songs from grooveshark result. result
- // should be the "result" field of most Grooveshark replies
- SongList ExtractSongs(const QVariantMap& result);
- // Convenient function for extracting song from grooveshark result.
- // result_song should be the song field ('song', 'nextSong', ...) of the
- // Grooveshark reply
- Song ExtractSong(const QVariantMap& result_song);
- // Convenient functions for extracting Grooveshark songs ids
- QList ExtractSongsIds(const QVariantMap& result);
- QList ExtractSongsIds(const QList& urls);
- int ExtractSongId(
- const QUrl& url); // Returns 0 if url is not a Grooveshark url
- // Convenient function for extracting basic playlist info (only 'id' and
- // 'name': QStandardItem still need to be created), and sort them by name
- QList ExtractPlaylistInfo(const QVariantMap& result);
-
- void ResetSessionId();
-
- // Sort songs alphabetically only if the "sort_alphabetically" option has been
- // checked in the preferences settings.
- void SortSongsAlphabeticallyIfNeeded(SongList* songs) const;
-
- GroovesharkUrlHandler* url_handler_;
-
- QString pending_search_;
-
- int next_pending_search_id_;
- int next_pending_playlist_retrieve_id_;
-
- QSet pending_retrieve_playlists_;
-
- QMap playlists_;
- QMap subscribed_playlists_;
-
- QStandardItem* root_;
- QStandardItem* search_;
- QStandardItem* popular_month_;
- QStandardItem* popular_today_;
- QStandardItem* stations_;
- QStandardItem* grooveshark_radio_;
- QStandardItem* favorites_;
- // Grooveshark Library (corresponds to Grooveshark 'MyMusic' actually, but
- // called 'Library' in the API).
- // Nothing to do with Clementine's local library
- QStandardItem* library_;
- QStandardItem* playlists_parent_;
- QStandardItem* subscribed_playlists_parent_;
-
- NetworkAccessManager* network_;
-
- QMenu* context_menu_;
- // IDs kept when showing menu, to know what the user has clicked on, to be
- // able to perform actions on corresponding items
- int current_song_id_;
- int current_playlist_id_;
-
- QAction* create_playlist_;
- QAction* delete_playlist_;
- QAction* rename_playlist_;
- QAction* remove_from_playlist_;
- QAction* remove_from_favorites_;
- QAction* remove_from_library_;
- QAction* get_url_to_share_song_;
- QAction* get_url_to_share_playlist_;
- QList playlistitem_actions_;
-
- SearchBoxWidget* search_box_;
-
- QTimer* search_delay_;
- QNetworkReply* last_search_reply_;
-
- QString username_;
- QString password_; // In fact, password's md5 hash
- QString user_id_;
- QString session_id_;
- QMap country_;
- // The last artists and songs ids th users has listened to. Used for autoplay
- QList last_artists_ids_;
- QList last_songs_ids_;
- QByteArray api_key_;
-
- LoginState login_state_;
-
- // Tasks' ids: we need to keep them in mind to be able to update task status
- // on each step
- int task_popular_id_;
- int task_playlists_id_;
- int task_search_id_;
-
- static const char* kUrl;
- static const char* kUrlCover;
- static const char* kHomepage;
-
- static const int kSongSearchLimit;
- static const int kSongSimpleSearchLimit;
- static const int kAlbumSearchLimit;
- static const int kSearchDelayMsec;
-
- static const char* kApiKey;
- static const char* kApiSecret;
-};
-
-#endif // INTERNET_GROOVESHARK_GROOVESHARKSERVICE_H_
diff --git a/src/internet/grooveshark/groovesharksettingspage.cpp b/src/internet/grooveshark/groovesharksettingspage.cpp
deleted file mode 100644
index 7c923e52a..000000000
--- a/src/internet/grooveshark/groovesharksettingspage.cpp
+++ /dev/null
@@ -1,131 +0,0 @@
-/* This file is part of Clementine.
- Copyright 2011, 2014, Arnaud Bienner
- Copyright 2011, David Sansome
- Copyright 2014, Krzysztof Sobiecki
- Copyright 2014, John Maguire
-
- Clementine 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.
-
- Clementine 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 Clementine. If not, see .
-*/
-
-#include "groovesharksettingspage.h"
-#include "ui_groovesharksettingspage.h"
-
-#include
-#include
-#include
-#include
-#include
-
-#include "groovesharkservice.h"
-#include "internet/core/internetmodel.h"
-#include "core/logging.h"
-#include "core/network.h"
-#include "ui/iconloader.h"
-
-GroovesharkSettingsPage::GroovesharkSettingsPage(SettingsDialog* dialog)
- : SettingsPage(dialog),
- ui_(new Ui_GroovesharkSettingsPage),
- service_(InternetModel::Service()),
- validated_(false) {
- ui_->setupUi(this);
-
- setWindowIcon(QIcon(":/providers/grooveshark.png"));
-
- connect(ui_->login, SIGNAL(clicked()), SLOT(Login()));
- connect(ui_->login_state, SIGNAL(LogoutClicked()), SLOT(Logout()));
- connect(ui_->login_state, SIGNAL(LoginClicked()), SLOT(Login()));
-
- connect(service_, SIGNAL(LoginFinished(bool)), SLOT(LoginFinished(bool)));
-
- ui_->login_state->AddCredentialField(ui_->username);
- ui_->login_state->AddCredentialField(ui_->password);
- ui_->login_state->AddCredentialGroup(ui_->account_group);
-}
-
-GroovesharkSettingsPage::~GroovesharkSettingsPage() { delete ui_; }
-
-void GroovesharkSettingsPage::Login() {
- if (service_->IsLoggedIn()) {
- return;
- }
-
- ui_->login_state->SetLoggedIn(LoginStateWidget::LoginInProgress);
- service_->Login(ui_->username->text(), ui_->password->text());
-}
-
-void GroovesharkSettingsPage::Load() {
- QSettings s;
- s.beginGroup(GroovesharkService::kSettingsGroup);
-
- original_username_ = s.value("username").toString();
-
- ui_->username->setText(original_username_);
- validated_ = false;
-
- UpdateLoginState();
-
- ui_->sort_alphabetically->setChecked(s.value("sort_alphabetically").toBool());
-}
-
-void GroovesharkSettingsPage::Save() {
- QSettings s;
- s.beginGroup(GroovesharkService::kSettingsGroup);
-
- s.setValue("username", ui_->username->text());
- s.setValue("sessionid", service_->session_id());
- const bool old_sort_value = s.value("sort_alphabetically").toBool();
- const bool new_sort_value = ui_->sort_alphabetically->isChecked();
- if (old_sort_value != new_sort_value) {
- s.setValue("sort_alphabetically", new_sort_value);
- service_->RefreshItems();
- }
-}
-
-void GroovesharkSettingsPage::LoginFinished(bool success) {
- validated_ = success;
-
- Save();
- UpdateLoginState();
-}
-
-void GroovesharkSettingsPage::UpdateLoginState() {
- const bool logged_in = service_->IsLoggedIn();
-
- ui_->login_state->SetLoggedIn(
- logged_in ? LoginStateWidget::LoggedIn : LoginStateWidget::LoggedOut,
- ui_->username->text());
- ui_->login_state->SetAccountTypeVisible(!logged_in);
-
- switch (service_->login_state()) {
- case GroovesharkService::LoginState_NoPremium:
- ui_->login_state->SetAccountTypeText(
- tr("You do not have a Grooveshark Anywhere account."));
- break;
-
- case GroovesharkService::LoginState_AuthFailed:
- ui_->login_state->SetAccountTypeText(
- tr("Your username or password was incorrect."));
- break;
-
- default:
- ui_->login_state->SetAccountTypeText(
- tr("A Grooveshark Anywhere account is required."));
- break;
- }
-}
-
-void GroovesharkSettingsPage::Logout() {
- service_->Logout();
- UpdateLoginState();
-}
diff --git a/src/internet/grooveshark/groovesharksettingspage.h b/src/internet/grooveshark/groovesharksettingspage.h
deleted file mode 100644
index f465acd4e..000000000
--- a/src/internet/grooveshark/groovesharksettingspage.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/* This file is part of Clementine.
- Copyright 2011, Arnaud Bienner
- Copyright 2014, Krzysztof Sobiecki
- Copyright 2014, John Maguire
-
- Clementine 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.
-
- Clementine 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 Clementine. If not, see .
-*/
-
-#ifndef INTERNET_GROOVESHARK_GROOVESHARKSETTINGSPAGE_H_
-#define INTERNET_GROOVESHARK_GROOVESHARKSETTINGSPAGE_H_
-
-#include "ui/settingspage.h"
-
-class NetworkAccessManager;
-class Ui_GroovesharkSettingsPage;
-class GroovesharkService;
-
-class GroovesharkSettingsPage : public SettingsPage {
- Q_OBJECT
-
- public:
- explicit GroovesharkSettingsPage(SettingsDialog* dialog);
- ~GroovesharkSettingsPage();
-
- void Load();
- void Save();
-
- private slots:
- void Login();
- void LoginFinished(bool success);
- void Logout();
-
- private:
- void UpdateLoginState();
-
- private:
- Ui_GroovesharkSettingsPage* ui_;
- GroovesharkService* service_;
-
- bool validated_;
- QString original_username_;
- QString original_password_;
-};
-
-#endif // INTERNET_GROOVESHARK_GROOVESHARKSETTINGSPAGE_H_
diff --git a/src/internet/grooveshark/groovesharksettingspage.ui b/src/internet/grooveshark/groovesharksettingspage.ui
deleted file mode 100644
index f79278f6e..000000000
--- a/src/internet/grooveshark/groovesharksettingspage.ui
+++ /dev/null
@@ -1,128 +0,0 @@
-
-
- GroovesharkSettingsPage
-
-
-
- 0
- 0
- 480
- 184
-
-
-
- Grooveshark
-
-
- By default, Grooveshark sorts songs on date added
-
-
- -
-
-
- -
-
-
- Account details
-
-
-
-
-
-
- true
-
-
-
- 0
-
-
-
-
-
- Username
-
-
-
- -
-
-
- -
-
-
- Password
-
-
-
- -
-
-
- QLineEdit::Password
-
-
-
- -
-
-
- Login
-
-
-
-
-
-
-
-
-
- -
-
-
- Preferences
-
-
-
-
-
-
-
-
-
- true
-
-
- Sort playlists songs alphabetically
-
-
- false
-
-
-
-
-
-
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 30
-
-
-
-
-
-
-
-
- LoginStateWidget
- QWidget
- widgets/loginstatewidget.h
- 1
-
-
-
-
-
-
-
diff --git a/src/internet/grooveshark/groovesharkurlhandler.cpp b/src/internet/grooveshark/groovesharkurlhandler.cpp
deleted file mode 100644
index 9554892c8..000000000
--- a/src/internet/grooveshark/groovesharkurlhandler.cpp
+++ /dev/null
@@ -1,82 +0,0 @@
-/* This file is part of Clementine.
- Copyright 2011, Arnaud Bienner
- Copyright 2014, Krzysztof Sobiecki
- Copyright 2014, John Maguire
-
- Clementine 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.
-
- Clementine 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 Clementine. If not, see .
-*/
-
-#include "groovesharkurlhandler.h"
-
-#include
-
-#include "groovesharkservice.h"
-#include "core/logging.h"
-
-GroovesharkUrlHandler::GroovesharkUrlHandler(GroovesharkService* service,
- QObject* parent)
- : UrlHandler(parent),
- service_(service),
- timer_mark_stream_key_(new QTimer(this)) {
- // We have to warn Grooveshark when user has listened for more than 30
- // seconds of a song, and when it ends. I guess this is used by Grooveshark
- // for statistics and user history.
- // To do this, we have TrackAboutToEnd method, and timer_mark_stream_key_
- // timer.
- // It is not perfect, as we may call Grooveshark MarkStreamKeyOver30Secs even
- // if user hasn't actually listen to 30 seconds (e.g. stream set to pause
- // state) but this is not a big deal and it should be accurate enough anyway.
- timer_mark_stream_key_->setInterval(30000);
- timer_mark_stream_key_->setSingleShot(true);
- connect(timer_mark_stream_key_, SIGNAL(timeout()),
- SLOT(MarkStreamKeyOver30Secs()));
-}
-
-UrlHandler::LoadResult GroovesharkUrlHandler::StartLoading(const QUrl& url) {
- qint64 length_nanosec = 0;
- QUrl streaming_url;
- QStringList ids = url.toString().remove("grooveshark://").split("/");
- if (ids.size() < 3) {
- qLog(Error) << "Invalid grooveshark URL: " << url.toString();
- qLog(Error) << "Should be grooveshark://artist_id/album_id/song_id";
- } else {
- last_artist_id_ = ids[0];
- last_album_id_ = ids[1];
- last_song_id_ = ids[2];
-
- streaming_url = service_->GetStreamingUrlFromSongId(
- last_song_id_, last_artist_id_, &last_server_id_, &last_stream_key_,
- &length_nanosec);
- qLog(Debug) << "Grooveshark Streaming URL: " << streaming_url;
-
- timer_mark_stream_key_->start();
- }
-
- return LoadResult(url, LoadResult::TrackAvailable, streaming_url,
- length_nanosec);
-}
-
-void GroovesharkUrlHandler::TrackAboutToEnd() {
- if (timer_mark_stream_key_->isActive()) {
- timer_mark_stream_key_->stop();
- return;
- }
- service_->MarkSongComplete(last_song_id_, last_stream_key_, last_server_id_);
-}
-
-void GroovesharkUrlHandler::TrackSkipped() { timer_mark_stream_key_->stop(); }
-
-void GroovesharkUrlHandler::MarkStreamKeyOver30Secs() {
- service_->MarkStreamKeyOver30Secs(last_stream_key_, last_server_id_);
-}
diff --git a/src/internet/grooveshark/groovesharkurlhandler.h b/src/internet/grooveshark/groovesharkurlhandler.h
deleted file mode 100644
index 883045ea4..000000000
--- a/src/internet/grooveshark/groovesharkurlhandler.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* This file is part of Clementine.
- Copyright 2011, Arnaud Bienner
- Copyright 2012, 2014, John Maguire
- Copyright 2014, Krzysztof Sobiecki
-
- Clementine 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.
-
- Clementine 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 Clementine. If not, see .
-*/
-
-#ifndef INTERNET_GROOVESHARK_GROOVESHARKURLHANDLER_H_
-#define INTERNET_GROOVESHARK_GROOVESHARKURLHANDLER_H_
-
-#include "core/urlhandler.h"
-
-class GroovesharkService;
-class QTimer;
-
-class GroovesharkUrlHandler : public UrlHandler {
- Q_OBJECT
- public:
- GroovesharkUrlHandler(GroovesharkService* service, QObject* parent);
-
- QString scheme() const { return "grooveshark"; }
- QIcon icon() const { return QIcon(":providers/grooveshark.png"); }
- LoadResult StartLoading(const QUrl& url);
- void TrackAboutToEnd();
- void TrackSkipped();
-
- private slots:
- void MarkStreamKeyOver30Secs();
-
- private:
- GroovesharkService* service_;
- QTimer* timer_mark_stream_key_;
- QString last_artist_id_;
- QString last_album_id_;
- QString last_song_id_;
- QString last_server_id_;
- QString last_stream_key_;
-};
-
-#endif // INTERNET_GROOVESHARK_GROOVESHARKURLHANDLER_H_
diff --git a/src/main.cpp b/src/main.cpp
index 24ad9dddd..2e6291299 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -398,15 +398,7 @@ int main(int argc, char* argv[]) {
Q_INIT_RESOURCE(data);
Q_INIT_RESOURCE(translations);
- // Grooveshark uses GoDaddy to sign its SSL certificates, which are in turn
- // signed by a ValiCert CA. This CA certificate isn't installed by default
- // in Windows, it's only added by windows update, or manually browsing to a
- // website with a certificate signed by ValiCert. Here we explicitly add
- // that CA to the default list used by QSslSocket, so it always works in
- // Clementine.
- QSslSocket::addDefaultCaCertificates(
- QSslCertificate::fromPath(":/grooveshark-valicert-ca.pem", QSsl::Pem));
- // Do the same for SoundCloud, whose certificate is missing on OS X.
+ // Add root CA cert for SoundCloud, whose certificate is missing on OS X.
QSslSocket::addDefaultCaCertificates(
QSslCertificate::fromPath(":/soundcloud-ca.pem", QSsl::Pem));
diff --git a/src/ui/settingsdialog.cpp b/src/ui/settingsdialog.cpp
index 5cfb1bda8..2cb7e1b7b 100644
--- a/src/ui/settingsdialog.cpp
+++ b/src/ui/settingsdialog.cpp
@@ -36,7 +36,6 @@
#include "engines/gstengine.h"
#include "globalsearch/globalsearchsettingspage.h"
#include "internet/digitally/digitallyimportedsettingspage.h"
-#include "internet/grooveshark/groovesharksettingspage.h"
#include "internet/core/internetshowsettingspage.h"
#include "internet/magnatune/magnatunesettingspage.h"
#include "internet/soundcloud/soundcloudsettingspage.h"
@@ -168,8 +167,6 @@ SettingsDialog::SettingsDialog(Application* app, BackgroundStreams* streams,
AddPage(Page_Lastfm, new LastFMSettingsPage(this), providers);
#endif
- AddPage(Page_Grooveshark, new GroovesharkSettingsPage(this), providers);
-
#ifdef HAVE_GOOGLE_DRIVE
AddPage(Page_GoogleDrive, new GoogleDriveSettingsPage(this), providers);
#endif
diff --git a/src/ui/settingsdialog.h b/src/ui/settingsdialog.h
index 607ecc0e8..14bb9765b 100644
--- a/src/ui/settingsdialog.h
+++ b/src/ui/settingsdialog.h
@@ -68,7 +68,6 @@ class SettingsDialog : public QDialog {
Page_Notifications,
Page_Library,
Page_Lastfm,
- Page_Grooveshark,
Page_SoundCloud,
Page_Spotify,
Page_Magnatune,