2011-09-02 00:28:11 +02:00
|
|
|
/* This file is part of Clementine.
|
2011-10-02 12:05:56 +02:00
|
|
|
Copyright 2011, David Sansome <me@davidsansome.com>
|
2011-09-02 00:28:11 +02:00
|
|
|
|
|
|
|
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 <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2011-09-30 15:35:09 +02:00
|
|
|
#include "groovesharkservice.h"
|
2011-09-02 00:28:11 +02:00
|
|
|
|
2011-11-05 02:34:49 +01:00
|
|
|
#include <boost/scoped_ptr.hpp>
|
|
|
|
|
2011-11-10 00:56:27 +01:00
|
|
|
#include <QApplication>
|
|
|
|
#include <QClipboard>
|
2011-11-23 23:56:02 +01:00
|
|
|
#include <QDesktopServices>
|
2011-11-05 02:34:49 +01:00
|
|
|
#include <QInputDialog>
|
2011-09-02 00:28:11 +02:00
|
|
|
#include <QMenu>
|
2011-09-13 22:32:10 +02:00
|
|
|
#include <QMessageBox>
|
2011-10-30 23:59:43 +01:00
|
|
|
#include <QMimeData>
|
2011-09-02 00:28:11 +02:00
|
|
|
#include <QNetworkReply>
|
|
|
|
#include <QNetworkRequest>
|
2011-11-10 00:56:27 +01:00
|
|
|
#include <QPushButton>
|
2011-09-20 00:26:24 +02:00
|
|
|
#include <QTimer>
|
2011-09-02 00:28:11 +02:00
|
|
|
|
|
|
|
#include <qjson/parser.h>
|
|
|
|
#include <qjson/serializer.h>
|
|
|
|
|
|
|
|
#include "qtiocompressor.h"
|
|
|
|
|
|
|
|
#include "internetmodel.h"
|
2011-11-29 13:57:35 +01:00
|
|
|
#include "groovesharkradio.h"
|
2011-09-20 00:26:24 +02:00
|
|
|
#include "groovesharkurlhandler.h"
|
2012-06-27 01:21:57 +02:00
|
|
|
#include "searchboxwidget.h"
|
2011-09-02 00:28:11 +02:00
|
|
|
|
2012-02-12 14:41:50 +01:00
|
|
|
#include "core/application.h"
|
2011-10-04 18:26:40 +02:00
|
|
|
#include "core/closure.h"
|
2011-09-02 00:28:11 +02:00
|
|
|
#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"
|
2012-02-28 23:22:09 +01:00
|
|
|
#include "core/timeconstants.h"
|
2011-09-02 00:28:11 +02:00
|
|
|
#include "core/utilities.h"
|
2011-09-30 15:35:09 +02:00
|
|
|
#include "globalsearch/globalsearch.h"
|
|
|
|
#include "globalsearch/groovesharksearchprovider.h"
|
2011-09-02 00:28:11 +02:00
|
|
|
#include "playlist/playlist.h"
|
|
|
|
#include "playlist/playlistcontainer.h"
|
|
|
|
#include "playlist/playlistmanager.h"
|
|
|
|
#include "ui/iconloader.h"
|
|
|
|
|
2011-11-29 13:57:35 +01:00
|
|
|
using smart_playlists::Generator;
|
|
|
|
using smart_playlists::GeneratorPtr;
|
|
|
|
|
2011-10-05 21:59:15 +02:00
|
|
|
// The Grooveshark terms of service require that application keys are not
|
2011-09-20 10:09:32 +02:00
|
|
|
// accessible to third parties. Therefore this application key is obfuscated to
|
2011-09-02 00:28:11 +02:00
|
|
|
// prevent third parties from viewing it.
|
2011-10-05 21:59:15 +02:00
|
|
|
const char* GroovesharkService::kApiKey = "clementineplayer";
|
2011-11-09 20:44:09 +01:00
|
|
|
const char* GroovesharkService::kApiSecret = "OzLDTB5XqmhkkhxMUK0/Mp5PQgD5O27DTEJa/jtkwEw=";
|
2011-09-02 00:28:11 +02:00
|
|
|
|
2011-10-05 21:59:15 +02:00
|
|
|
const char* GroovesharkService::kServiceName = "Grooveshark";
|
|
|
|
const char* GroovesharkService::kSettingsGroup = "Grooveshark";
|
|
|
|
const char* GroovesharkService::kUrl = "http://api.grooveshark.com/ws/3.0/";
|
2012-03-13 22:53:55 +01:00
|
|
|
const char* GroovesharkService::kUrlCover = "http://beta.grooveshark.com/static/amazonart/l";
|
2011-11-23 23:56:02 +01:00
|
|
|
const char* GroovesharkService::kHomepage = "http://grooveshark.com/";
|
2011-09-02 00:28:11 +02:00
|
|
|
|
2011-11-29 14:13:41 +01:00
|
|
|
const int GroovesharkService::kSongSearchLimit = 100;
|
2011-11-01 13:00:27 +01:00
|
|
|
const int GroovesharkService::kSongSimpleSearchLimit = 10;
|
2013-08-28 22:20:58 +02:00
|
|
|
const int GroovesharkService::kAlbumSearchLimit = 10;
|
|
|
|
|
|
|
|
const int GroovesharkService::kSearchDelayMsec = 400;
|
2011-09-02 00:28:11 +02:00
|
|
|
|
2011-09-20 00:26:24 +02:00
|
|
|
typedef QPair<QString, QVariant> Param;
|
2011-09-02 00:28:11 +02:00
|
|
|
|
2012-02-12 14:41:50 +01:00
|
|
|
GroovesharkService::GroovesharkService(Application* app, InternetModel *parent)
|
|
|
|
: InternetService(kServiceName, app, parent, parent),
|
2011-10-05 21:59:15 +02:00
|
|
|
url_handler_(new GroovesharkUrlHandler(this, this)),
|
2011-09-30 15:35:09 +02:00
|
|
|
next_pending_search_id_(0),
|
2011-09-02 00:28:11 +02:00
|
|
|
root_(NULL),
|
|
|
|
search_(NULL),
|
2011-11-19 18:56:29 +01:00
|
|
|
popular_month_(NULL),
|
|
|
|
popular_today_(NULL),
|
2011-11-29 13:57:35 +01:00
|
|
|
stations_(NULL),
|
2011-11-29 23:52:19 +01:00
|
|
|
grooveshark_radio_(NULL),
|
2011-11-02 00:02:49 +01:00
|
|
|
favorites_(NULL),
|
2012-07-21 18:09:16 +02:00
|
|
|
library_(NULL),
|
2012-06-27 01:21:57 +02:00
|
|
|
playlists_parent_(NULL),
|
|
|
|
subscribed_playlists_parent_(NULL),
|
2011-09-02 00:28:11 +02:00
|
|
|
network_(new NetworkAccessManager(this)),
|
|
|
|
context_menu_(NULL),
|
2011-11-28 21:59:25 +01:00
|
|
|
create_playlist_(NULL),
|
|
|
|
delete_playlist_(NULL),
|
|
|
|
rename_playlist_(NULL),
|
2011-11-02 23:41:58 +01:00
|
|
|
remove_from_playlist_(NULL),
|
|
|
|
remove_from_favorites_(NULL),
|
2012-07-21 18:09:16 +02:00
|
|
|
remove_from_library_(NULL),
|
2012-03-26 23:57:26 +02:00
|
|
|
get_url_to_share_song_(NULL),
|
2012-03-27 00:43:47 +02:00
|
|
|
get_url_to_share_playlist_(NULL),
|
2012-06-27 01:21:57 +02:00
|
|
|
search_box_(new SearchBoxWidget(this)),
|
2011-09-20 19:12:06 +02:00
|
|
|
search_delay_(new QTimer(this)),
|
|
|
|
last_search_reply_(NULL),
|
2011-09-13 22:32:10 +02:00
|
|
|
api_key_(QByteArray::fromBase64(kApiSecret)),
|
2011-11-23 01:07:40 +01:00
|
|
|
login_state_(LoginState_OtherError),
|
|
|
|
task_popular_id_(0),
|
|
|
|
task_playlists_id_(0),
|
|
|
|
task_search_id_(0) {
|
2011-09-02 00:28:11 +02:00
|
|
|
|
2012-02-12 14:41:50 +01:00
|
|
|
app_->player()->RegisterUrlHandler(url_handler_);
|
2011-09-13 22:32:10 +02:00
|
|
|
|
2011-09-20 19:12:06 +02:00
|
|
|
search_delay_->setInterval(kSearchDelayMsec);
|
|
|
|
search_delay_->setSingleShot(true);
|
|
|
|
connect(search_delay_, SIGNAL(timeout()), SLOT(DoSearch()));
|
|
|
|
|
2011-09-13 22:32:10 +02:00
|
|
|
// Get already existing (authenticated) session id, if any
|
|
|
|
QSettings s;
|
2011-10-05 21:59:15 +02:00
|
|
|
s.beginGroup(GroovesharkService::kSettingsGroup);
|
2011-09-13 22:32:10 +02:00
|
|
|
session_id_ = s.value("sessionid").toString();
|
|
|
|
username_ = s.value("username").toString();
|
|
|
|
|
2012-02-13 21:44:04 +01:00
|
|
|
GroovesharkSearchProvider* search_provider = new GroovesharkSearchProvider(app_, this);
|
2011-09-30 15:35:09 +02:00
|
|
|
search_provider->Init(this);
|
2012-02-12 14:41:50 +01:00
|
|
|
app_->global_search()->AddProvider(search_provider);
|
2011-11-09 20:44:09 +01:00
|
|
|
|
|
|
|
// 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];
|
2012-06-27 01:21:57 +02:00
|
|
|
|
|
|
|
connect(search_box_, SIGNAL(TextChanged(QString)), SLOT(Search(QString)));
|
2011-09-02 00:28:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-10-05 21:59:15 +02:00
|
|
|
GroovesharkService::~GroovesharkService() {
|
2011-09-02 00:28:11 +02:00
|
|
|
}
|
|
|
|
|
2011-10-05 21:59:15 +02:00
|
|
|
QStandardItem* GroovesharkService::CreateRootItem() {
|
2011-09-02 00:28:11 +02:00
|
|
|
root_ = new QStandardItem(QIcon(":providers/grooveshark.png"), kServiceName);
|
|
|
|
root_->setData(true, InternetModel::Role_CanLazyLoad);
|
2011-10-02 14:47:03 +02:00
|
|
|
root_->setData(InternetModel::PlayBehaviour_DoubleClickAction,
|
|
|
|
InternetModel::Role_PlayBehaviour);
|
2011-09-02 00:28:11 +02:00
|
|
|
return root_;
|
|
|
|
}
|
|
|
|
|
2011-10-05 21:59:15 +02:00
|
|
|
void GroovesharkService::LazyPopulate(QStandardItem* item) {
|
2011-09-02 00:28:11 +02:00
|
|
|
switch (item->data(InternetModel::Role_Type).toInt()) {
|
|
|
|
case InternetModel::Type_Service: {
|
|
|
|
EnsureConnected();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-10-05 21:59:15 +02:00
|
|
|
void GroovesharkService::ShowConfig() {
|
2012-12-05 10:36:22 +01:00
|
|
|
app_->OpenSettingsDialogAtPage(SettingsDialog::Page_Grooveshark);
|
2011-09-20 19:29:16 +02:00
|
|
|
}
|
|
|
|
|
2012-06-27 01:21:57 +02:00
|
|
|
QWidget* GroovesharkService::HeaderWidget() const {
|
2012-07-21 20:15:36 +02:00
|
|
|
if (IsLoggedIn())
|
|
|
|
return search_box_;
|
|
|
|
return NULL;
|
2012-06-27 01:21:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void GroovesharkService::Search(const QString& text, bool now) {
|
2011-09-20 19:12:06 +02:00
|
|
|
pending_search_ = text;
|
2011-09-02 00:28:11 +02:00
|
|
|
|
2011-11-24 01:26:29 +01:00
|
|
|
// 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();
|
2012-06-27 01:21:57 +02:00
|
|
|
ClearSearchResults();
|
2011-11-24 01:26:29 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-09-20 19:12:06 +02:00
|
|
|
if (now) {
|
|
|
|
search_delay_->stop();
|
|
|
|
DoSearch();
|
|
|
|
} else {
|
|
|
|
search_delay_->start();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-10-05 21:59:15 +02:00
|
|
|
int GroovesharkService::SimpleSearch(const QString& query) {
|
2011-09-30 15:35:09 +02:00
|
|
|
QList<Param> parameters;
|
|
|
|
parameters << Param("query", query)
|
|
|
|
<< Param("country", "")
|
2011-11-01 13:00:27 +01:00
|
|
|
<< Param("limit", QString::number(kSongSimpleSearchLimit))
|
2011-09-30 15:35:09 +02:00
|
|
|
<< Param("offset", "");
|
|
|
|
|
|
|
|
int id = next_pending_search_id_++;
|
2012-10-12 13:43:55 +02:00
|
|
|
QNetworkReply* reply = CreateRequest("getSongSearchResults", parameters);
|
|
|
|
NewClosure(reply, SIGNAL(finished()), this,
|
|
|
|
SLOT(SimpleSearchFinished(QNetworkReply*, int)), reply, id);
|
2011-09-30 15:35:09 +02:00
|
|
|
return id;
|
|
|
|
}
|
|
|
|
|
2012-10-12 13:43:55 +02:00
|
|
|
void GroovesharkService::SimpleSearchFinished(QNetworkReply* reply, int id) {
|
2011-09-30 15:35:09 +02:00
|
|
|
reply->deleteLater();
|
|
|
|
|
|
|
|
QVariantMap result = ExtractResult(reply);
|
|
|
|
SongList songs = ExtractSongs(result);
|
|
|
|
emit SimpleSearchResults(id, songs);
|
|
|
|
}
|
|
|
|
|
2011-10-05 21:59:15 +02:00
|
|
|
int GroovesharkService::SearchAlbums(const QString& query) {
|
2011-10-04 18:26:40 +02:00
|
|
|
QList<Param> parameters;
|
|
|
|
parameters << Param("query", query)
|
|
|
|
<< Param("country", "")
|
2013-08-28 22:20:58 +02:00
|
|
|
<< Param("limit", QString::number(kAlbumSearchLimit));
|
2011-10-04 18:26:40 +02:00
|
|
|
|
2011-11-16 00:34:36 +01:00
|
|
|
QNetworkReply* reply = CreateRequest("getAlbumSearchResults", parameters);
|
2011-10-04 18:26:40 +02:00
|
|
|
|
2011-10-05 11:36:08 +02:00
|
|
|
const int id = next_pending_search_id_++;
|
2011-10-04 18:26:40 +02:00
|
|
|
|
2011-10-06 13:11:18 +02:00
|
|
|
NewClosure(reply, SIGNAL(finished()),
|
|
|
|
this, SLOT(SearchAlbumsFinished(QNetworkReply*,int)),
|
|
|
|
reply, id);
|
2011-10-04 18:26:40 +02:00
|
|
|
|
|
|
|
return id;
|
|
|
|
}
|
|
|
|
|
2011-10-05 21:59:15 +02:00
|
|
|
void GroovesharkService::SearchAlbumsFinished(QNetworkReply* reply, int id) {
|
2011-10-05 11:36:08 +02:00
|
|
|
reply->deleteLater();
|
|
|
|
|
|
|
|
QVariantMap result = ExtractResult(reply);
|
|
|
|
QVariantList albums = result["albums"].toList();
|
2011-10-05 14:08:33 +02:00
|
|
|
|
2012-03-05 00:54:24 +01:00
|
|
|
QList<quint64> ret;
|
2011-10-05 11:36:08 +02:00
|
|
|
foreach (const QVariant& v, albums) {
|
2012-03-05 00:54:24 +01:00
|
|
|
quint64 album_id = v.toMap()["AlbumID"].toULongLong();
|
|
|
|
GetAlbumSongs(album_id);
|
|
|
|
ret << album_id;
|
2011-10-05 11:36:08 +02:00
|
|
|
}
|
2011-10-05 14:08:33 +02:00
|
|
|
|
|
|
|
emit AlbumSearchResult(id, ret);
|
|
|
|
}
|
|
|
|
|
2012-03-05 00:54:24 +01:00
|
|
|
void GroovesharkService::GetAlbumSongs(quint64 album_id) {
|
2011-10-05 14:08:33 +02:00
|
|
|
QList<Param> parameters;
|
|
|
|
parameters << Param("albumID", album_id)
|
|
|
|
<< Param("country", "");
|
2011-11-16 00:34:36 +01:00
|
|
|
QNetworkReply* reply = CreateRequest("getAlbumSongs", parameters);
|
2012-03-05 00:54:24 +01:00
|
|
|
NewClosure(reply, SIGNAL(finished()),
|
|
|
|
this, SLOT(GetAlbumSongsFinished(QNetworkReply*,quint64)),
|
|
|
|
reply, album_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
void GroovesharkService::GetAlbumSongsFinished(QNetworkReply* reply, quint64 album_id) {
|
|
|
|
reply->deleteLater();
|
2011-10-05 14:08:33 +02:00
|
|
|
QVariantMap result = ExtractResult(reply);
|
2012-03-05 00:54:24 +01:00
|
|
|
SongList songs = ExtractSongs(result);
|
|
|
|
|
|
|
|
emit AlbumSongsLoaded(album_id, songs);
|
2011-10-04 18:26:40 +02:00
|
|
|
}
|
|
|
|
|
2011-10-05 21:59:15 +02:00
|
|
|
void GroovesharkService::DoSearch() {
|
2011-11-23 01:07:40 +01:00
|
|
|
if (!task_search_id_) {
|
2012-02-12 14:41:50 +01:00
|
|
|
task_search_id_ = app_->task_manager()->StartTask(tr("Searching on Grooveshark"));
|
2011-11-23 01:07:40 +01:00
|
|
|
}
|
|
|
|
|
2012-06-27 01:21:57 +02:00
|
|
|
ClearSearchResults();
|
2011-09-20 19:12:06 +02:00
|
|
|
|
2012-06-27 01:21:57 +02:00
|
|
|
QList<Param> parameters;
|
2011-09-20 19:12:06 +02:00
|
|
|
parameters << Param("query", pending_search_)
|
2011-09-02 00:28:11 +02:00
|
|
|
<< Param("country", "")
|
2012-06-27 01:21:57 +02:00
|
|
|
<< Param("limit", QString::number(kSongSearchLimit))
|
2011-09-02 00:28:11 +02:00
|
|
|
<< Param("offset", "");
|
2012-10-14 23:27:45 +02:00
|
|
|
last_search_reply_ = CreateRequest("getSongSearchResults", parameters);
|
|
|
|
NewClosure(last_search_reply_, SIGNAL(finished()), this,
|
|
|
|
SLOT(SearchSongsFinished(QNetworkReply*)), last_search_reply_);
|
2011-09-02 00:28:11 +02:00
|
|
|
}
|
|
|
|
|
2012-10-12 13:43:55 +02:00
|
|
|
void GroovesharkService::SearchSongsFinished(QNetworkReply* reply) {
|
2011-09-02 00:28:11 +02:00
|
|
|
reply->deleteLater();
|
|
|
|
|
2012-10-14 23:27:45 +02:00
|
|
|
if (reply != last_search_reply_)
|
|
|
|
return;
|
|
|
|
|
2011-09-13 22:32:10 +02:00
|
|
|
QVariantMap result = ExtractResult(reply);
|
2011-09-24 12:06:31 +02:00
|
|
|
SongList songs = ExtractSongs(result);
|
2012-02-12 14:41:50 +01:00
|
|
|
app_->task_manager()->SetTaskFinished(task_search_id_);
|
2011-11-23 01:07:40 +01:00
|
|
|
task_search_id_ = 0;
|
2012-06-27 01:21:57 +02:00
|
|
|
|
|
|
|
// Fill results list
|
|
|
|
foreach (const Song& song, songs) {
|
2012-06-27 21:19:30 +02:00
|
|
|
QStandardItem* child = CreateSongItem(song);
|
2012-06-27 01:21:57 +02:00
|
|
|
search_->appendRow(child);
|
|
|
|
}
|
|
|
|
|
|
|
|
QModelIndex index = model()->merged_model()->mapFromSource(search_->index());
|
|
|
|
ScrollToIndex(index);
|
2011-09-02 00:28:11 +02:00
|
|
|
}
|
|
|
|
|
2011-10-05 21:59:15 +02:00
|
|
|
void GroovesharkService::InitCountry() {
|
2011-09-20 00:26:24 +02:00
|
|
|
if (!country_.isEmpty())
|
|
|
|
return;
|
|
|
|
// Get country info
|
2011-11-16 00:34:36 +01:00
|
|
|
QNetworkReply *reply_country = CreateRequest("getCountry", QList<Param>());
|
2012-03-08 21:26:27 +01:00
|
|
|
if (WaitForReply(reply_country)) {
|
|
|
|
country_ = ExtractResult(reply_country);
|
|
|
|
}
|
|
|
|
reply_country->deleteLater();
|
2011-09-20 00:26:24 +02:00
|
|
|
}
|
|
|
|
|
2011-11-29 23:52:19 +01:00
|
|
|
QUrl GroovesharkService::GetStreamingUrlFromSongId(const QString& song_id, const QString& artist_id,
|
2011-10-02 12:05:56 +02:00
|
|
|
QString* server_id, QString* stream_key, qint64* length_nanosec) {
|
2011-09-20 00:26:24 +02:00
|
|
|
QList<Param> parameters;
|
|
|
|
|
|
|
|
InitCountry();
|
|
|
|
parameters << Param("songID", song_id)
|
|
|
|
<< Param("country", country_);
|
2011-11-16 00:34:36 +01:00
|
|
|
QNetworkReply* reply = CreateRequest("getSubscriberStreamKey", parameters);
|
2012-03-08 21:26:27 +01:00
|
|
|
|
|
|
|
// Wait for the reply
|
|
|
|
bool reply_has_timeouted = !WaitForReply(reply);
|
|
|
|
reply->deleteLater();
|
|
|
|
if (reply_has_timeouted)
|
2011-11-29 13:57:35 +01:00
|
|
|
return QUrl();
|
2012-03-08 21:26:27 +01:00
|
|
|
|
2011-09-20 00:26:24 +02:00
|
|
|
QVariantMap result = ExtractResult(reply);
|
2011-10-02 12:05:56 +02:00
|
|
|
server_id->clear();
|
|
|
|
server_id->append(result["StreamServerID"].toString());
|
|
|
|
stream_key->clear();
|
|
|
|
stream_key->append(result["StreamKey"].toString());
|
|
|
|
*length_nanosec = result["uSecs"].toLongLong() * 1000;
|
2011-11-29 23:52:19 +01:00
|
|
|
// 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();
|
2011-09-20 00:26:24 +02:00
|
|
|
|
|
|
|
return QUrl(result["url"].toString());
|
|
|
|
}
|
|
|
|
|
2011-10-05 21:59:15 +02:00
|
|
|
void GroovesharkService::Login(const QString& username, const QString& password) {
|
2011-09-13 22:32:10 +02:00
|
|
|
// 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<Param> parameters;
|
2011-11-16 00:34:36 +01:00
|
|
|
QNetworkReply *reply = CreateRequest("startSession", parameters, true);
|
2011-09-13 22:32:10 +02:00
|
|
|
|
2012-10-12 13:43:55 +02:00
|
|
|
NewClosure(reply, SIGNAL(finished()), this,
|
|
|
|
SLOT(SessionCreated(QNetworkReply*)), reply);
|
2011-09-13 22:32:10 +02:00
|
|
|
}
|
|
|
|
|
2012-10-12 13:43:55 +02:00
|
|
|
void GroovesharkService::SessionCreated(QNetworkReply* reply) {
|
2011-09-13 22:32:10 +02:00
|
|
|
reply->deleteLater();
|
|
|
|
|
2012-01-08 18:46:50 +01:00
|
|
|
if (reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() != 200) {
|
|
|
|
emit StreamError("Failed to create Grooveshark session: " +
|
|
|
|
reply->errorString());
|
|
|
|
emit LoginFinished(false);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-09-13 22:32:10 +02:00
|
|
|
QVariantMap result = ExtractResult(reply);
|
|
|
|
if (!result["success"].toBool()) {
|
2011-10-05 21:59:15 +02:00
|
|
|
qLog(Error) << "Grooveshark returned an error during session creation";
|
2011-09-13 22:32:10 +02:00
|
|
|
}
|
|
|
|
session_id_ = result["sessionID"].toString();
|
|
|
|
qLog(Debug) << "Session ID returned: " << session_id_;
|
|
|
|
|
|
|
|
AuthenticateSession();
|
|
|
|
}
|
|
|
|
|
2011-10-05 21:59:15 +02:00
|
|
|
void GroovesharkService::AuthenticateSession() {
|
2011-09-13 22:32:10 +02:00
|
|
|
QList<Param> parameters;
|
|
|
|
parameters << Param("login", username_)
|
|
|
|
<< Param("password", password_);
|
|
|
|
|
2011-11-16 00:34:36 +01:00
|
|
|
QNetworkReply *reply = CreateRequest("authenticate", parameters, true);
|
2012-10-12 13:43:55 +02:00
|
|
|
NewClosure(reply, SIGNAL(finished()), this,
|
|
|
|
SLOT(Authenticated(QNetworkReply*)), reply);
|
2011-09-13 22:32:10 +02:00
|
|
|
}
|
|
|
|
|
2012-10-12 13:43:55 +02:00
|
|
|
void GroovesharkService::Authenticated(QNetworkReply* reply) {
|
2011-09-13 22:32:10 +02:00
|
|
|
reply->deleteLater();
|
|
|
|
|
|
|
|
QVariantMap result = ExtractResult(reply);
|
|
|
|
// Check if the user has been authenticated correctly
|
2011-10-05 21:02:32 +02:00
|
|
|
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()) {
|
2011-10-05 21:59:15 +02:00
|
|
|
error = tr("User %1 doesn't have a Grooveshark Anywhere account").arg(username_);
|
2011-10-05 21:02:32 +02:00
|
|
|
login_state_ = LoginState_NoPremium;
|
|
|
|
}
|
|
|
|
if (!error.isEmpty()) {
|
2011-10-05 21:59:15 +02:00
|
|
|
QMessageBox::warning(NULL, tr("Grooveshark login error"), error, QMessageBox::Close);
|
2011-09-13 22:32:10 +02:00
|
|
|
ResetSessionId();
|
|
|
|
emit LoginFinished(false);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
login_state_ = LoginState_LoggedIn;
|
|
|
|
user_id_ = result["UserID"].toString();
|
|
|
|
emit LoginFinished(true);
|
2011-09-22 19:54:59 +02:00
|
|
|
EnsureItemsCreated();
|
2011-09-13 22:32:10 +02:00
|
|
|
}
|
|
|
|
|
2012-06-27 01:21:57 +02:00
|
|
|
void GroovesharkService::ClearSearchResults() {
|
|
|
|
if (search_)
|
|
|
|
search_->removeRows(0, search_->rowCount());
|
|
|
|
}
|
|
|
|
|
2011-10-05 21:59:15 +02:00
|
|
|
void GroovesharkService::Logout() {
|
2011-09-13 22:32:10 +02:00
|
|
|
ResetSessionId();
|
2011-12-22 20:45:44 +01:00
|
|
|
RemoveItems();
|
|
|
|
}
|
|
|
|
|
|
|
|
void GroovesharkService::RemoveItems() {
|
2011-10-02 14:47:03 +02:00
|
|
|
root_->removeRows(0, root_->rowCount());
|
2011-11-29 23:52:19 +01:00
|
|
|
// 'search', 'favorites', 'popular', ... items were root's children, and have
|
2011-11-19 18:56:29 +01:00
|
|
|
// been deleted: we should update these now invalid pointers
|
2011-10-02 14:47:03 +02:00
|
|
|
search_ = NULL;
|
2011-11-19 18:56:29 +01:00
|
|
|
popular_month_ = NULL;
|
|
|
|
popular_today_ = NULL;
|
2012-07-21 18:09:16 +02:00
|
|
|
library_ = NULL;
|
2011-11-02 00:02:49 +01:00
|
|
|
favorites_ = NULL;
|
2012-06-27 01:21:57 +02:00
|
|
|
subscribed_playlists_parent_ = NULL;
|
2011-11-29 23:52:19 +01:00
|
|
|
stations_ = NULL;
|
|
|
|
grooveshark_radio_ = NULL;
|
2012-06-27 01:21:57 +02:00
|
|
|
playlists_parent_ = NULL;
|
2011-11-02 00:02:49 +01:00
|
|
|
playlists_.clear();
|
2012-06-27 01:21:57 +02:00
|
|
|
subscribed_playlists_parent_ = NULL;
|
2011-11-25 01:00:58 +01:00
|
|
|
subscribed_playlists_.clear();
|
2012-08-09 00:51:00 +02:00
|
|
|
pending_retrieve_playlists_.clear();
|
2011-09-13 22:32:10 +02:00
|
|
|
}
|
|
|
|
|
2011-10-05 21:59:15 +02:00
|
|
|
void GroovesharkService::ResetSessionId() {
|
2011-09-13 22:32:10 +02:00
|
|
|
QSettings s;
|
2011-10-05 21:59:15 +02:00
|
|
|
s.beginGroup(GroovesharkService::kSettingsGroup);
|
2011-09-13 22:32:10 +02:00
|
|
|
|
|
|
|
session_id_.clear();
|
|
|
|
s.setValue("sessionid", session_id_);
|
|
|
|
}
|
|
|
|
|
2012-03-11 15:44:43 +01:00
|
|
|
void GroovesharkService::ShowContextMenu(const QPoint& global_pos) {
|
2011-09-13 22:32:10 +02:00
|
|
|
EnsureMenuCreated();
|
2011-11-02 23:41:58 +01:00
|
|
|
|
|
|
|
// Check if we should display actions
|
2011-11-05 02:34:49 +01:00
|
|
|
bool display_delete_playlist_action = false,
|
|
|
|
display_remove_from_playlist_action = false,
|
2012-03-26 23:57:26 +02:00
|
|
|
display_remove_from_favorites_action = false,
|
2012-07-21 18:09:16 +02:00
|
|
|
display_remove_from_library_action = false,
|
2012-03-27 00:43:47 +02:00
|
|
|
display_share_song_url = false,
|
|
|
|
display_share_playlist_url = false;
|
2011-11-05 02:34:49 +01:00
|
|
|
|
2012-03-11 15:44:43 +01:00
|
|
|
QModelIndex index(model()->current_index());
|
|
|
|
|
2011-11-07 19:37:29 +01:00
|
|
|
if (index.data(InternetModel::Role_Type).toInt() == InternetModel::Type_UserPlaylist &&
|
2011-11-24 20:18:42 +01:00
|
|
|
index.data(Role_PlaylistType).toInt() == UserPlaylist) {
|
2011-11-05 02:34:49 +01:00
|
|
|
display_delete_playlist_action = true;
|
|
|
|
}
|
2011-11-02 23:41:58 +01:00
|
|
|
// 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) {
|
2011-11-07 19:37:29 +01:00
|
|
|
int parent_playlist_type = index.parent().data(Role_PlaylistType).toInt();
|
|
|
|
if (parent_playlist_type == UserFavorites)
|
|
|
|
display_remove_from_favorites_action = true;
|
2012-07-21 18:09:16 +02:00
|
|
|
else if (parent_playlist_type == UserLibrary)
|
|
|
|
display_remove_from_library_action = true;
|
2011-11-25 01:00:58 +01:00
|
|
|
else if (parent_playlist_type == UserPlaylist)
|
2011-11-07 19:37:29 +01:00
|
|
|
display_remove_from_playlist_action = true;
|
2011-11-02 23:41:58 +01:00
|
|
|
}
|
2011-11-05 02:34:49 +01:00
|
|
|
delete_playlist_->setVisible(display_delete_playlist_action);
|
2011-11-28 21:59:25 +01:00
|
|
|
// If we can delete this playlist, we can also rename it
|
|
|
|
rename_playlist_->setVisible(display_delete_playlist_action);
|
2011-11-02 23:41:58 +01:00
|
|
|
remove_from_playlist_->setVisible(display_remove_from_playlist_action);
|
|
|
|
remove_from_favorites_->setVisible(display_remove_from_favorites_action);
|
2012-07-21 18:09:16 +02:00
|
|
|
remove_from_library_->setVisible(display_remove_from_library_action);
|
2011-11-02 23:41:58 +01:00
|
|
|
|
2012-03-27 00:43:47 +02:00
|
|
|
// Check if we can display actions to get URL for sharing songs/playlists:
|
|
|
|
// - share song
|
2012-06-27 21:19:30 +02:00
|
|
|
if (index.data(InternetModel::Role_Type).toInt() == InternetModel::Type_Track) {
|
2012-03-26 23:57:26 +02:00
|
|
|
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);
|
|
|
|
|
2012-03-27 00:43:47 +02:00
|
|
|
// - 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);
|
|
|
|
|
2011-09-13 22:32:10 +02:00
|
|
|
context_menu_->popup(global_pos);
|
|
|
|
}
|
|
|
|
|
2011-10-05 21:59:15 +02:00
|
|
|
void GroovesharkService::EnsureMenuCreated() {
|
2011-09-02 00:28:11 +02:00
|
|
|
if(!context_menu_) {
|
|
|
|
context_menu_ = new QMenu;
|
|
|
|
context_menu_->addActions(GetPlaylistActions());
|
2011-11-05 02:34:49 +01:00
|
|
|
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()));
|
2011-11-28 21:59:25 +01:00
|
|
|
rename_playlist_ = context_menu_->addAction(
|
|
|
|
IconLoader::Load("edit-rename"), tr("Rename Grooveshark playlist"),
|
|
|
|
this, SLOT(RenameCurrentPlaylist()));
|
2011-11-05 02:34:49 +01:00
|
|
|
context_menu_->addSeparator();
|
2011-11-02 23:41:58 +01:00
|
|
|
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()));
|
2012-07-21 18:09:16 +02:00
|
|
|
remove_from_library_ = context_menu_->addAction(
|
|
|
|
IconLoader::Load("list-remove"), tr("Remove from My Music"),
|
|
|
|
this, SLOT(RemoveCurrentFromLibrary()));
|
2012-03-26 23:57:26 +02:00
|
|
|
get_url_to_share_song_ = context_menu_->addAction(
|
2012-03-27 00:46:06 +02:00
|
|
|
tr("Get a URL to share this Grooveshark song"),
|
2012-03-26 23:57:26 +02:00
|
|
|
this, SLOT(GetCurrentSongUrlToShare()));
|
2012-03-27 00:43:47 +02:00
|
|
|
get_url_to_share_playlist_ = context_menu_->addAction(
|
2012-03-27 00:46:06 +02:00
|
|
|
tr("Get a URL to share this Grooveshark playlist"),
|
2012-03-27 00:43:47 +02:00
|
|
|
this, SLOT(GetCurrentPlaylistUrlToShare()));
|
2011-09-20 19:29:16 +02:00
|
|
|
context_menu_->addSeparator();
|
2012-03-26 23:57:26 +02:00
|
|
|
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()));
|
2011-12-22 20:45:44 +01:00
|
|
|
context_menu_->addSeparator();
|
2012-03-26 23:57:26 +02:00
|
|
|
context_menu_->addAction(IconLoader::Load("configure"),
|
|
|
|
tr("Configure Grooveshark..."),
|
|
|
|
this, SLOT(ShowConfig()));
|
2011-09-02 00:28:11 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-11-23 23:56:02 +01:00
|
|
|
void GroovesharkService::Homepage() {
|
|
|
|
QDesktopServices::openUrl(QUrl(kHomepage));
|
|
|
|
}
|
|
|
|
|
2011-12-22 20:45:44 +01:00
|
|
|
void GroovesharkService::RefreshItems() {
|
|
|
|
RemoveItems();
|
|
|
|
EnsureItemsCreated();
|
|
|
|
}
|
|
|
|
|
2011-10-05 21:59:15 +02:00
|
|
|
void GroovesharkService::EnsureItemsCreated() {
|
2011-10-14 00:10:18 +02:00
|
|
|
if (IsLoggedIn() && !search_) {
|
2011-09-22 19:54:59 +02:00
|
|
|
search_ = new QStandardItem(IconLoader::Load("edit-find"),
|
2012-06-27 01:21:57 +02:00
|
|
|
tr("Search results"));
|
|
|
|
search_->setToolTip(tr("Start typing something on the search box above to "
|
|
|
|
"fill this search results list"));
|
2012-07-29 01:35:05 +02:00
|
|
|
search_->setData(InternetModel::PlayBehaviour_MultipleItems,
|
2011-11-19 17:45:38 +01:00
|
|
|
InternetModel::Role_PlayBehaviour);
|
2011-09-22 19:54:59 +02:00
|
|
|
root_->appendRow(search_);
|
2011-11-19 17:45:38 +01:00
|
|
|
|
2012-06-27 01:21:57 +02:00
|
|
|
QStandardItem* popular = new QStandardItem(QIcon(":/star-on.png"),
|
2012-06-27 02:04:05 +02:00
|
|
|
tr("Popular songs"));
|
2012-06-27 01:21:57 +02:00
|
|
|
root_->appendRow(popular);
|
2011-11-24 23:42:22 +01:00
|
|
|
|
2011-11-19 18:56:29 +01:00
|
|
|
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);
|
2012-07-29 01:35:05 +02:00
|
|
|
popular_month_->setData(InternetModel::PlayBehaviour_MultipleItems,
|
2011-11-19 18:56:29 +01:00
|
|
|
InternetModel::Role_PlayBehaviour);
|
2012-06-27 01:21:57 +02:00
|
|
|
popular->appendRow(popular_month_);
|
2011-11-19 18:56:29 +01:00
|
|
|
|
|
|
|
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);
|
2012-07-29 01:35:05 +02:00
|
|
|
popular_today_->setData(InternetModel::PlayBehaviour_MultipleItems,
|
2011-11-19 18:56:29 +01:00
|
|
|
InternetModel::Role_PlayBehaviour);
|
2012-06-27 01:21:57 +02:00
|
|
|
popular->appendRow(popular_today_);
|
2011-11-19 18:56:29 +01:00
|
|
|
|
2012-06-27 01:21:57 +02:00
|
|
|
QStandardItem* radios_divider = new QStandardItem(QIcon(":last.fm/icon_radio.png"),
|
|
|
|
tr("Radios"));
|
2011-11-29 13:57:35 +01:00
|
|
|
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);
|
2012-06-27 01:21:57 +02:00
|
|
|
radios_divider->appendRow(stations_);
|
2011-11-29 13:57:35 +01:00
|
|
|
|
2011-11-29 23:52:19 +01:00
|
|
|
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);
|
2012-06-27 01:21:57 +02:00
|
|
|
radios_divider->appendRow(grooveshark_radio_);
|
2011-11-24 23:42:22 +01:00
|
|
|
|
2012-07-21 18:09:16 +02:00
|
|
|
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);
|
2012-07-29 01:35:05 +02:00
|
|
|
library_->setData(InternetModel::PlayBehaviour_MultipleItems,
|
2012-07-21 18:09:16 +02:00
|
|
|
InternetModel::Role_PlayBehaviour);
|
|
|
|
root_->appendRow(library_);
|
|
|
|
|
2011-11-19 17:45:38 +01:00
|
|
|
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);
|
2012-07-29 01:35:05 +02:00
|
|
|
favorites_->setData(InternetModel::PlayBehaviour_MultipleItems,
|
2011-11-19 17:45:38 +01:00
|
|
|
InternetModel::Role_PlayBehaviour);
|
|
|
|
root_->appendRow(favorites_);
|
|
|
|
|
2012-06-27 01:21:57 +02:00
|
|
|
playlists_parent_ = new QStandardItem(tr("Playlists"));
|
|
|
|
root_->appendRow(playlists_parent_);
|
|
|
|
|
|
|
|
subscribed_playlists_parent_ = new QStandardItem(tr("Subscribed playlists"));
|
|
|
|
root_->appendRow(subscribed_playlists_parent_);
|
2011-11-25 01:00:58 +01:00
|
|
|
|
2011-10-29 20:42:25 +02:00
|
|
|
RetrieveUserFavorites();
|
2012-07-21 18:09:16 +02:00
|
|
|
RetrieveUserLibrarySongs();
|
2011-09-24 12:06:31 +02:00
|
|
|
RetrieveUserPlaylists();
|
2011-11-25 01:00:58 +01:00
|
|
|
RetrieveSubscribedPlaylists();
|
2011-11-29 13:57:35 +01:00
|
|
|
RetrieveAutoplayTags();
|
2011-11-23 01:07:40 +01:00
|
|
|
RetrievePopularSongs();
|
2011-09-22 19:54:59 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-10-05 21:59:15 +02:00
|
|
|
void GroovesharkService::EnsureConnected() {
|
2011-09-22 19:54:59 +02:00
|
|
|
if (session_id_.isEmpty()) {
|
|
|
|
ShowConfig();
|
|
|
|
} else {
|
|
|
|
EnsureItemsCreated();
|
2011-09-02 00:28:11 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-11-05 02:34:49 +01:00
|
|
|
QStandardItem* GroovesharkService::CreatePlaylistItem(const QString& playlist_name,
|
|
|
|
int playlist_id) {
|
|
|
|
QStandardItem* item = new QStandardItem(playlist_name);
|
|
|
|
item->setData(InternetModel::Type_UserPlaylist, InternetModel::Role_Type);
|
2011-11-24 20:18:42 +01:00
|
|
|
item->setData(UserPlaylist, Role_PlaylistType);
|
2011-11-05 02:34:49 +01:00
|
|
|
item->setData(true, InternetModel::Role_CanLazyLoad);
|
|
|
|
item->setData(true, InternetModel::Role_CanBeModified);
|
2012-07-29 01:35:05 +02:00
|
|
|
item->setData(InternetModel::PlayBehaviour_MultipleItems, InternetModel::Role_PlayBehaviour);
|
2011-11-05 02:34:49 +01:00
|
|
|
item->setData(playlist_id, Role_UserPlaylistId);
|
|
|
|
return item;
|
|
|
|
}
|
|
|
|
|
2011-10-05 21:59:15 +02:00
|
|
|
void GroovesharkService::RetrieveUserPlaylists() {
|
2011-11-23 01:07:40 +01:00
|
|
|
task_playlists_id_ =
|
2012-02-12 14:41:50 +01:00
|
|
|
app_->task_manager()->StartTask(tr("Retrieving Grooveshark playlists"));
|
2011-11-16 00:34:36 +01:00
|
|
|
QNetworkReply* reply = CreateRequest("getUserPlaylists", QList<Param>());
|
2011-09-24 12:06:31 +02:00
|
|
|
|
2012-10-12 13:43:55 +02:00
|
|
|
NewClosure(reply, SIGNAL(finished()), this,
|
|
|
|
SLOT(UserPlaylistsRetrieved(QNetworkReply*)), reply);
|
2011-09-24 12:06:31 +02:00
|
|
|
}
|
|
|
|
|
2012-10-12 13:43:55 +02:00
|
|
|
void GroovesharkService::UserPlaylistsRetrieved(QNetworkReply* reply) {
|
2011-09-24 12:06:31 +02:00
|
|
|
reply->deleteLater();
|
|
|
|
|
|
|
|
QVariantMap result = ExtractResult(reply);
|
2012-05-16 01:30:18 +02:00
|
|
|
QList<PlaylistInfo> playlists = ExtractPlaylistInfo(result);
|
2011-09-24 12:06:31 +02:00
|
|
|
|
2012-05-16 01:30:18 +02:00
|
|
|
foreach(const PlaylistInfo& playlist_info, playlists) {
|
|
|
|
int playlist_id = playlist_info.id_;
|
|
|
|
const QString& playlist_name = playlist_info.name_;
|
2011-12-01 23:46:27 +01:00
|
|
|
QStandardItem* playlist_item =
|
|
|
|
CreatePlaylistItem(playlist_name, playlist_id);
|
2012-06-27 01:21:57 +02:00
|
|
|
playlists_parent_->appendRow(playlist_item);
|
|
|
|
|
2011-12-01 23:46:27 +01:00
|
|
|
// Keep in mind this playlist
|
|
|
|
playlists_.insert(playlist_id,
|
|
|
|
PlaylistInfo(playlist_id, playlist_name, playlist_item));
|
2012-06-27 01:21:57 +02:00
|
|
|
|
2011-09-24 12:06:31 +02:00
|
|
|
// Request playlist's songs
|
2011-12-01 23:46:27 +01:00
|
|
|
RefreshPlaylist(playlist_id);
|
2011-09-24 12:06:31 +02:00
|
|
|
}
|
2011-11-27 20:02:14 +01:00
|
|
|
|
|
|
|
if (playlists.isEmpty()) {
|
2012-02-12 14:41:50 +01:00
|
|
|
app_->task_manager()->SetTaskFinished(task_playlists_id_);
|
2011-11-27 20:02:14 +01:00
|
|
|
}
|
2011-09-24 12:06:31 +02:00
|
|
|
}
|
|
|
|
|
2012-10-12 13:43:55 +02:00
|
|
|
void GroovesharkService::PlaylistSongsRetrieved(
|
|
|
|
QNetworkReply* reply, int playlist_id) {
|
2011-09-24 12:06:31 +02:00
|
|
|
reply->deleteLater();
|
2012-10-12 13:43:55 +02:00
|
|
|
pending_retrieve_playlists_.remove(playlist_id);
|
|
|
|
PlaylistInfo* playlist_info = subscribed_playlists_.contains(playlist_id) ?
|
|
|
|
&subscribed_playlists_[playlist_id] : &playlists_[playlist_id];
|
|
|
|
playlist_info->item_->removeRows(0, playlist_info->item_->rowCount());
|
2011-10-29 20:42:25 +02:00
|
|
|
|
|
|
|
QVariantMap result = ExtractResult(reply);
|
|
|
|
SongList songs = ExtractSongs(result);
|
2012-06-27 01:55:51 +02:00
|
|
|
Song::SortSongsListAlphabetically(&songs);
|
|
|
|
|
2011-10-29 20:42:25 +02:00
|
|
|
foreach (const Song& song, songs) {
|
2012-06-27 21:19:30 +02:00
|
|
|
QStandardItem* child = CreateSongItem(song);
|
2012-10-12 13:43:55 +02:00
|
|
|
child->setData(playlist_info->id_, Role_UserPlaylistId);
|
2011-10-30 23:59:43 +01:00
|
|
|
child->setData(true, InternetModel::Role_CanBeModified);
|
2011-10-29 20:42:25 +02:00
|
|
|
|
2012-10-12 13:43:55 +02:00
|
|
|
playlist_info->item_->appendRow(child);
|
2011-11-05 02:42:17 +01:00
|
|
|
}
|
2011-10-30 23:59:43 +01:00
|
|
|
|
|
|
|
// Keep in mind this playlist
|
2012-10-12 13:43:55 +02:00
|
|
|
playlist_info->songs_ids_ = ExtractSongsIds(result);
|
2011-11-23 01:07:40 +01:00
|
|
|
|
|
|
|
if (pending_retrieve_playlists_.isEmpty()) {
|
2012-02-12 14:41:50 +01:00
|
|
|
app_->task_manager()->SetTaskFinished(task_playlists_id_);
|
2011-11-23 01:07:40 +01:00
|
|
|
}
|
2011-10-29 20:42:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void GroovesharkService::RetrieveUserFavorites() {
|
2011-11-23 01:07:40 +01:00
|
|
|
int task_id =
|
2012-02-12 14:41:50 +01:00
|
|
|
app_->task_manager()->StartTask(tr("Retrieving Grooveshark favorites songs"));
|
2011-11-16 00:34:36 +01:00
|
|
|
QNetworkReply* reply = CreateRequest("getUserFavoriteSongs", QList<Param>());
|
2011-10-29 20:42:25 +02:00
|
|
|
|
2011-11-23 01:07:40 +01:00
|
|
|
NewClosure(reply, SIGNAL(finished()),
|
|
|
|
this, SLOT(UserFavoritesRetrieved(QNetworkReply*, int)), reply, task_id);
|
2011-10-29 20:42:25 +02:00
|
|
|
}
|
|
|
|
|
2011-11-23 01:07:40 +01:00
|
|
|
void GroovesharkService::UserFavoritesRetrieved(QNetworkReply* reply, int task_id) {
|
2011-10-29 20:42:25 +02:00
|
|
|
reply->deleteLater();
|
2012-07-21 19:39:37 +02:00
|
|
|
app_->task_manager()->SetTaskFinished(task_id);
|
2011-10-29 20:42:25 +02:00
|
|
|
|
2012-06-02 14:21:56 +02:00
|
|
|
if (!favorites_) {
|
|
|
|
// The use probably logged out before the response arrived.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-11-19 17:45:38 +01:00
|
|
|
favorites_->removeRows(0, favorites_->rowCount());
|
2011-09-24 12:06:31 +02:00
|
|
|
|
|
|
|
QVariantMap result = ExtractResult(reply);
|
|
|
|
SongList songs = ExtractSongs(result);
|
2012-06-27 01:55:51 +02:00
|
|
|
Song::SortSongsListAlphabetically(&songs);
|
|
|
|
|
2011-09-24 12:06:31 +02:00
|
|
|
foreach (const Song& song, songs) {
|
2012-06-27 21:19:30 +02:00
|
|
|
QStandardItem* child = CreateSongItem(song);
|
2011-11-02 00:02:49 +01:00
|
|
|
child->setData(true, InternetModel::Role_CanBeModified);
|
2011-09-24 12:06:31 +02:00
|
|
|
|
2011-11-02 00:02:49 +01:00
|
|
|
favorites_->appendRow(child);
|
2011-09-24 12:06:31 +02:00
|
|
|
}
|
2011-11-23 01:07:40 +01:00
|
|
|
}
|
|
|
|
|
2012-07-21 18:09:16 +02:00
|
|
|
void GroovesharkService::RetrieveUserLibrarySongs() {
|
|
|
|
int task_id =
|
|
|
|
app_->task_manager()->StartTask(tr("Retrieving Grooveshark My Music songs"));
|
|
|
|
QNetworkReply* reply = CreateRequest("getUserLibrarySongs", QList<Param>());
|
|
|
|
|
|
|
|
NewClosure(reply, SIGNAL(finished()),
|
|
|
|
this, SLOT(UserLibrarySongsRetrieved(QNetworkReply*, int)), reply, task_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
void GroovesharkService::UserLibrarySongsRetrieved(QNetworkReply* reply, int task_id) {
|
|
|
|
reply->deleteLater();
|
2012-07-21 19:39:37 +02:00
|
|
|
app_->task_manager()->SetTaskFinished(task_id);
|
2012-07-21 18:09:16 +02:00
|
|
|
|
|
|
|
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);
|
2012-07-21 18:47:18 +02:00
|
|
|
Song::SortSongsListAlphabetically(&songs);
|
|
|
|
|
2012-07-21 18:09:16 +02:00
|
|
|
foreach (const Song& song, songs) {
|
2012-07-21 18:47:18 +02:00
|
|
|
QStandardItem* child = CreateSongItem(song);
|
2012-07-21 18:09:16 +02:00
|
|
|
child->setData(true, InternetModel::Role_CanBeModified);
|
|
|
|
|
|
|
|
library_->appendRow(child);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-11-23 01:07:40 +01:00
|
|
|
void GroovesharkService::RetrievePopularSongs() {
|
|
|
|
task_popular_id_ =
|
2012-02-12 14:41:50 +01:00
|
|
|
app_->task_manager()->StartTask(tr("Getting Grooveshark popular songs"));
|
2011-11-23 01:07:40 +01:00
|
|
|
RetrievePopularSongsMonth();
|
|
|
|
RetrievePopularSongsToday();
|
2011-09-24 12:06:31 +02:00
|
|
|
}
|
|
|
|
|
2011-11-19 18:56:29 +01:00
|
|
|
void GroovesharkService::RetrievePopularSongsMonth() {
|
|
|
|
QList<Param> 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);
|
2012-06-02 14:21:56 +02:00
|
|
|
|
|
|
|
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_);
|
|
|
|
}
|
|
|
|
|
2012-04-04 19:21:18 +02:00
|
|
|
if (!popular_month_)
|
|
|
|
return;
|
2012-06-02 14:21:56 +02:00
|
|
|
|
2011-11-19 18:56:29 +01:00
|
|
|
foreach (const Song& song, songs) {
|
2012-06-27 21:19:30 +02:00
|
|
|
QStandardItem* child = CreateSongItem(song);
|
2011-11-19 18:56:29 +01:00
|
|
|
popular_month_->appendRow(child);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void GroovesharkService::RetrievePopularSongsToday() {
|
|
|
|
QList<Param> 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);
|
2012-06-02 14:21:56 +02:00
|
|
|
|
|
|
|
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_);
|
|
|
|
}
|
|
|
|
|
2012-04-04 19:21:18 +02:00
|
|
|
if (!popular_today_)
|
|
|
|
return;
|
2012-06-02 14:21:56 +02:00
|
|
|
|
2011-11-19 18:56:29 +01:00
|
|
|
foreach (const Song& song, songs) {
|
2012-06-27 21:19:30 +02:00
|
|
|
QStandardItem* child = CreateSongItem(song);
|
2011-11-19 18:56:29 +01:00
|
|
|
popular_today_->appendRow(child);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-11-25 01:00:58 +01:00
|
|
|
void GroovesharkService::RetrieveSubscribedPlaylists() {
|
|
|
|
QNetworkReply* reply = CreateRequest("getUserPlaylistsSubscribed", QList<Param>());
|
|
|
|
NewClosure(reply, SIGNAL(finished()),
|
|
|
|
this, SLOT(SubscribedPlaylistsRetrieved(QNetworkReply*)), reply);
|
|
|
|
}
|
|
|
|
|
|
|
|
void GroovesharkService::SubscribedPlaylistsRetrieved(QNetworkReply* reply) {
|
|
|
|
reply->deleteLater();
|
2012-05-16 01:30:18 +02:00
|
|
|
|
2011-11-25 01:00:58 +01:00
|
|
|
QVariantMap result = ExtractResult(reply);
|
2012-05-16 01:30:18 +02:00
|
|
|
QList<PlaylistInfo> playlists = ExtractPlaylistInfo(result);
|
|
|
|
|
|
|
|
foreach(const PlaylistInfo& playlist_info, playlists) {
|
|
|
|
int playlist_id = playlist_info.id_;
|
|
|
|
const QString& playlist_name = playlist_info.name_;
|
2011-11-25 01:00:58 +01:00
|
|
|
|
|
|
|
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);
|
2012-05-17 01:52:05 +02:00
|
|
|
|
|
|
|
subscribed_playlists_.insert(playlist_id,
|
|
|
|
PlaylistInfo(playlist_id, playlist_name, playlist_item));
|
2012-06-27 01:21:57 +02:00
|
|
|
subscribed_playlists_parent_->appendRow(playlist_item);
|
2011-11-25 01:00:58 +01:00
|
|
|
|
|
|
|
// Request playlist's songs
|
2011-12-01 23:46:27 +01:00
|
|
|
RefreshPlaylist(playlist_id);
|
2011-11-25 01:00:58 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-11-29 13:57:35 +01:00
|
|
|
void GroovesharkService::RetrieveAutoplayTags() {
|
|
|
|
QNetworkReply* reply = CreateRequest("getAutoplayTags", QList<Param>());
|
|
|
|
NewClosure(reply, SIGNAL(finished()),
|
|
|
|
this, SLOT(AutoplayTagsRetrieved(QNetworkReply*)), reply);
|
|
|
|
}
|
|
|
|
|
|
|
|
void GroovesharkService::AutoplayTagsRetrieved(QNetworkReply* reply) {
|
|
|
|
reply->deleteLater();
|
|
|
|
QVariantMap result = ExtractResult(reply);
|
|
|
|
QVariantMap::const_iterator it;
|
2012-04-04 19:21:18 +02:00
|
|
|
if (!stations_)
|
|
|
|
return;
|
2011-11-29 13:57:35 +01:00
|
|
|
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<Param> parameters;
|
|
|
|
parameters << Param("tagID", tag_id);
|
|
|
|
QNetworkReply* reply = CreateRequest("startAutoplayTag", parameters);
|
2012-03-08 21:26:27 +01:00
|
|
|
|
|
|
|
bool reply_has_timeouted = !WaitForReply(reply);
|
2011-11-29 13:57:35 +01:00
|
|
|
reply->deleteLater();
|
2012-03-08 21:26:27 +01:00
|
|
|
if (reply_has_timeouted)
|
|
|
|
return Song();
|
|
|
|
|
2011-11-29 13:57:35 +01:00
|
|
|
QVariantMap result = ExtractResult(reply);
|
|
|
|
autoplay_state = result["autoplayState"].toMap();
|
|
|
|
return ExtractSong(result["nextSong"].toMap());
|
|
|
|
}
|
|
|
|
|
2011-11-29 23:52:19 +01:00
|
|
|
Song GroovesharkService::StartAutoplay(QVariantMap& autoplay_state) {
|
|
|
|
QList<Param> parameters;
|
|
|
|
QVariantList artists_ids_qvariant;
|
|
|
|
foreach (int artist_id, last_artists_ids_) {
|
|
|
|
artists_ids_qvariant << QVariant(artist_id);
|
|
|
|
}
|
|
|
|
QVariantList songs_ids_qvariant;
|
|
|
|
foreach (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);
|
2012-03-08 21:26:27 +01:00
|
|
|
|
|
|
|
bool reply_has_timeouted = !WaitForReply(reply);
|
2011-11-29 23:52:19 +01:00
|
|
|
reply->deleteLater();
|
2012-03-08 21:26:27 +01:00
|
|
|
if (reply_has_timeouted)
|
|
|
|
return Song();
|
|
|
|
|
2011-11-29 23:52:19 +01:00
|
|
|
QVariantMap result = ExtractResult(reply);
|
|
|
|
autoplay_state = result["autoplayState"].toMap();
|
|
|
|
return ExtractSong(result["nextSong"].toMap());
|
|
|
|
}
|
|
|
|
|
2011-11-29 13:57:35 +01:00
|
|
|
Song GroovesharkService::GetAutoplaySong(QVariantMap& autoplay_state) {
|
|
|
|
QList<Param> parameters;
|
|
|
|
parameters << Param("autoplayState", autoplay_state);
|
|
|
|
QNetworkReply* reply = CreateRequest("getAutoplaySong", parameters);
|
2012-03-08 21:26:27 +01:00
|
|
|
|
|
|
|
bool reply_has_timeouted = !WaitForReply(reply);
|
2011-11-29 13:57:35 +01:00
|
|
|
reply->deleteLater();
|
2012-03-08 21:26:27 +01:00
|
|
|
if (reply_has_timeouted)
|
|
|
|
return Song();
|
|
|
|
|
2011-11-29 13:57:35 +01:00
|
|
|
QVariantMap result = ExtractResult(reply);
|
|
|
|
autoplay_state = result["autoplayState"].toMap();
|
|
|
|
return ExtractSong(result["nextSong"].toMap());
|
|
|
|
}
|
|
|
|
|
2011-10-05 21:59:15 +02:00
|
|
|
void GroovesharkService::MarkStreamKeyOver30Secs(const QString& stream_key,
|
2011-10-02 12:05:56 +02:00
|
|
|
const QString& server_id) {
|
|
|
|
QList<Param> parameters;
|
|
|
|
parameters << Param("streamKey", stream_key)
|
|
|
|
<< Param("streamServerID", server_id);
|
|
|
|
|
2011-11-16 00:34:36 +01:00
|
|
|
QNetworkReply* reply = CreateRequest("markStreamKeyOver30Secs", parameters);
|
2012-10-12 13:43:55 +02:00
|
|
|
NewClosure(reply, SIGNAL(finished()), this,
|
|
|
|
SLOT(StreamMarked(QNetworkReply*)), reply);
|
2011-10-02 12:05:56 +02:00
|
|
|
}
|
|
|
|
|
2012-10-12 13:43:55 +02:00
|
|
|
void GroovesharkService::StreamMarked(QNetworkReply* reply) {
|
2011-10-02 12:05:56 +02:00
|
|
|
reply->deleteLater();
|
|
|
|
QVariantMap result = ExtractResult(reply);
|
|
|
|
if (!result["success"].toBool()) {
|
2011-10-05 21:59:15 +02:00
|
|
|
qLog(Warning) << "Grooveshark markStreamKeyOver30Secs failed";
|
2011-10-02 12:05:56 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-10-05 21:59:15 +02:00
|
|
|
void GroovesharkService::MarkSongComplete(const QString& song_id,
|
2011-10-02 12:05:56 +02:00
|
|
|
const QString& stream_key,
|
|
|
|
const QString& server_id) {
|
|
|
|
QList<Param> parameters;
|
|
|
|
parameters << Param("songID", song_id)
|
|
|
|
<< Param("streamKey", stream_key)
|
|
|
|
<< Param("streamServerID", server_id);
|
|
|
|
|
2011-11-16 00:34:36 +01:00
|
|
|
QNetworkReply* reply = CreateRequest("markSongComplete", parameters);
|
2012-10-12 13:43:55 +02:00
|
|
|
NewClosure(reply, SIGNAL(finished()), this,
|
|
|
|
SLOT(SongMarkedAsComplete(QNetworkReply*)), reply);
|
2011-10-02 12:05:56 +02:00
|
|
|
}
|
|
|
|
|
2012-10-12 13:43:55 +02:00
|
|
|
void GroovesharkService::SongMarkedAsComplete(QNetworkReply* reply) {
|
2011-10-02 12:05:56 +02:00
|
|
|
reply->deleteLater();
|
|
|
|
QVariantMap result = ExtractResult(reply);
|
|
|
|
if (!result["success"].toBool()) {
|
2011-10-05 21:59:15 +02:00
|
|
|
qLog(Warning) << "Grooveshark markSongComplete failed";
|
2011-10-02 12:05:56 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-10-05 21:59:15 +02:00
|
|
|
void GroovesharkService::ItemDoubleClicked(QStandardItem* item) {
|
2011-10-02 14:47:03 +02:00
|
|
|
if (item == root_) {
|
|
|
|
EnsureConnected();
|
|
|
|
}
|
2011-09-02 00:28:11 +02:00
|
|
|
}
|
|
|
|
|
2011-11-29 13:57:35 +01:00
|
|
|
GeneratorPtr GroovesharkService::CreateGenerator(QStandardItem* item) {
|
|
|
|
GeneratorPtr ret;
|
|
|
|
if (!item ||
|
|
|
|
item->data(InternetModel::Role_Type).toInt() != InternetModel::Type_SmartPlaylist) {
|
|
|
|
return ret;
|
|
|
|
}
|
2011-11-29 23:52:19 +01:00
|
|
|
|
|
|
|
if (item == grooveshark_radio_) {
|
|
|
|
if (last_artists_ids_.isEmpty()) {
|
|
|
|
QMessageBox::warning(NULL, tr("Error"),
|
2011-12-13 17:27:47 +01:00
|
|
|
tr("To start Grooveshark radio, you should first listen to a few other Grooveshark songs"));
|
2011-11-29 23:52:19 +01:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
ret = GeneratorPtr(new GroovesharkRadio(this));
|
|
|
|
} else {
|
|
|
|
int tag_id = item->data(Role_UserPlaylistId).toInt();
|
|
|
|
ret = GeneratorPtr(new GroovesharkRadio(this ,tag_id));
|
|
|
|
}
|
2011-11-29 13:57:35 +01:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-10-30 23:59:43 +01:00
|
|
|
void GroovesharkService::DropMimeData(const QMimeData* data, const QModelIndex& index) {
|
|
|
|
if (!data) {
|
|
|
|
return;
|
|
|
|
}
|
2011-11-02 00:02:49 +01:00
|
|
|
|
|
|
|
// Get Grooveshark songs' ids, if any.
|
|
|
|
QList<int> data_songs_ids = ExtractSongsIds(data->urls());
|
|
|
|
if (data_songs_ids.isEmpty()) {
|
|
|
|
// There is none: probably means user didn't dropped Grooveshark songs
|
2011-10-30 23:59:43 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-11-02 00:02:49 +01:00
|
|
|
int type = index.data(InternetModel::Role_Type).toInt();
|
|
|
|
int parent_type = index.parent().data(InternetModel::Role_Type).toInt();
|
|
|
|
|
2011-11-07 19:37:29 +01:00
|
|
|
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) {
|
|
|
|
foreach (int song_id, data_songs_ids) {
|
|
|
|
AddUserFavoriteSong(song_id);
|
|
|
|
}
|
2012-07-21 18:09:16 +02:00
|
|
|
} 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);
|
2011-11-07 19:37:29 +01:00
|
|
|
} 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<int> songs_ids = playlist.songs_ids_;
|
|
|
|
songs_ids << data_songs_ids;
|
|
|
|
|
|
|
|
SetPlaylistSongs(playlist_id, songs_ids);
|
2011-11-02 00:02:49 +01:00
|
|
|
}
|
|
|
|
}
|
2011-10-30 23:59:43 +01:00
|
|
|
}
|
|
|
|
|
2011-11-06 16:12:44 +01:00
|
|
|
QList<QAction*> GroovesharkService::playlistitem_actions(const Song& song) {
|
|
|
|
// Clear previous actions
|
|
|
|
while (!playlistitem_actions_.isEmpty()) {
|
|
|
|
QAction* action = playlistitem_actions_.takeFirst();
|
|
|
|
QMenu* menu = action->menu();
|
|
|
|
if (menu)
|
|
|
|
delete 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);
|
|
|
|
|
2012-07-21 18:09:16 +02:00
|
|
|
// 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);
|
|
|
|
|
2011-11-06 16:12:44 +01:00
|
|
|
// 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();
|
|
|
|
foreach (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);
|
|
|
|
|
2012-03-27 00:46:06 +02:00
|
|
|
QAction* share_song = new QAction(tr("Get a URL to share this Grooveshark song"), this);
|
2011-11-10 00:56:27 +01:00
|
|
|
connect(share_song, SIGNAL(triggered()), SLOT(GetCurrentSongUrlToShare()));
|
|
|
|
playlistitem_actions_.append(share_song);
|
|
|
|
|
2011-11-06 16:12:44 +01:00
|
|
|
// Keep in mind the current song id
|
|
|
|
current_song_id_ = ExtractSongId(song.url());
|
|
|
|
|
|
|
|
return playlistitem_actions_;
|
|
|
|
}
|
|
|
|
|
2011-11-10 00:56:27 +01:00
|
|
|
void GroovesharkService::GetCurrentSongUrlToShare() {
|
|
|
|
GetSongUrlToShare(current_song_id_);
|
|
|
|
}
|
|
|
|
|
|
|
|
void GroovesharkService::GetSongUrlToShare(int song_id) {
|
|
|
|
QList<Param> parameters;
|
|
|
|
parameters << Param("songID", song_id);
|
2011-11-16 00:34:36 +01:00
|
|
|
QNetworkReply* reply = CreateRequest("getSongURLFromSongID", parameters);
|
2011-11-10 00:56:27 +01:00
|
|
|
|
|
|
|
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();
|
2012-03-27 00:43:47 +02:00
|
|
|
ShowUrlBox(tr("Grooveshark song's URL"), url);
|
|
|
|
}
|
|
|
|
|
|
|
|
void GroovesharkService::GetCurrentPlaylistUrlToShare() {
|
|
|
|
GetPlaylistUrlToShare(current_playlist_id_);
|
|
|
|
}
|
|
|
|
|
|
|
|
void GroovesharkService::GetPlaylistUrlToShare(int playlist_id) {
|
|
|
|
QList<Param> 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);
|
|
|
|
}
|
2011-11-10 00:56:27 +01:00
|
|
|
|
2012-03-27 00:43:47 +02:00
|
|
|
void GroovesharkService::ShowUrlBox(const QString& title, const QString& url) {
|
2011-11-10 00:56:27 +01:00
|
|
|
QMessageBox url_box;
|
2012-03-27 00:43:47 +02:00
|
|
|
url_box.setWindowTitle(title);
|
2012-03-26 23:32:42 +02:00
|
|
|
url_box.setWindowIcon(QIcon(":/icon.png"));
|
2011-11-10 00:56:27 +01:00
|
|
|
url_box.setText(url);
|
|
|
|
url_box.setStandardButtons(QMessageBox::Ok);
|
2011-11-11 02:42:48 +01:00
|
|
|
QPushButton* copy_to_clipboard_button =
|
|
|
|
url_box.addButton(tr("Copy to clipboard"), QMessageBox::ActionRole);
|
2011-11-10 00:56:27 +01:00
|
|
|
|
|
|
|
url_box.exec();
|
|
|
|
|
|
|
|
if (url_box.clickedButton() == copy_to_clipboard_button) {
|
|
|
|
QApplication::clipboard()->setText(url);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-11-06 16:12:44 +01:00
|
|
|
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<int> songs_ids = playlist.songs_ids_;
|
|
|
|
songs_ids << current_song_id_;
|
|
|
|
|
|
|
|
SetPlaylistSongs(playlist_id, songs_ids);
|
|
|
|
}
|
|
|
|
|
2011-10-30 23:59:43 +01:00
|
|
|
void GroovesharkService::SetPlaylistSongs(int playlist_id, const QList<int>& songs_ids) {
|
2011-12-01 23:46:27 +01:00
|
|
|
// 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;
|
2011-11-23 01:07:40 +01:00
|
|
|
int task_id =
|
2012-02-12 14:41:50 +01:00
|
|
|
app_->task_manager()->StartTask(tr("Update Grooveshark playlist"));
|
2011-11-23 01:07:40 +01:00
|
|
|
|
2011-10-30 23:59:43 +01:00
|
|
|
QList<Param> parameters;
|
|
|
|
|
|
|
|
// Convert song ids to QVariant
|
2011-11-02 23:41:58 +01:00
|
|
|
QVariantList songs_ids_qvariant;
|
2011-10-30 23:59:43 +01:00
|
|
|
foreach (int song_id, songs_ids) {
|
|
|
|
songs_ids_qvariant << QVariant(song_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
parameters << Param("playlistID", playlist_id)
|
|
|
|
<< Param("songIDs", songs_ids_qvariant);
|
|
|
|
|
2011-11-16 00:34:36 +01:00
|
|
|
QNetworkReply* reply = CreateRequest("setPlaylistSongs", parameters);
|
2011-10-30 23:59:43 +01:00
|
|
|
|
|
|
|
NewClosure(reply, SIGNAL(finished()),
|
2011-11-23 01:07:40 +01:00
|
|
|
this, SLOT(PlaylistSongsSet(QNetworkReply*, int, int)),
|
|
|
|
reply, playlist_id, task_id);
|
2011-10-30 23:59:43 +01:00
|
|
|
}
|
|
|
|
|
2011-11-23 01:07:40 +01:00
|
|
|
void GroovesharkService::PlaylistSongsSet(QNetworkReply* reply, int playlist_id, int task_id) {
|
2011-10-30 23:59:43 +01:00
|
|
|
reply->deleteLater();
|
2012-02-12 14:41:50 +01:00
|
|
|
app_->task_manager()->SetTaskFinished(task_id);
|
2011-10-30 23:59:43 +01:00
|
|
|
|
|
|
|
QVariantMap result = ExtractResult(reply);
|
|
|
|
if (!result["success"].toBool()) {
|
|
|
|
qLog(Warning) << "Grooveshark setPlaylistSongs failed";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-12-01 23:46:27 +01:00
|
|
|
RefreshPlaylist(playlist_id);
|
2011-10-30 23:59:43 +01:00
|
|
|
}
|
|
|
|
|
2011-12-01 23:46:27 +01:00
|
|
|
void GroovesharkService::RefreshPlaylist(int playlist_id) {
|
2011-10-30 23:59:43 +01:00
|
|
|
QList<Param> parameters;
|
|
|
|
parameters << Param("playlistID", playlist_id);
|
2011-11-16 00:34:36 +01:00
|
|
|
QNetworkReply* reply = CreateRequest("getPlaylistSongs", parameters);
|
2012-10-12 13:43:55 +02:00
|
|
|
NewClosure(reply, SIGNAL(finished()), this,
|
|
|
|
SLOT(PlaylistSongsRetrieved(QNetworkReply*, int)), reply, playlist_id);
|
|
|
|
pending_retrieve_playlists_.insert(playlist_id);
|
2011-10-30 23:59:43 +01:00
|
|
|
}
|
|
|
|
|
2011-11-05 02:34:49 +01:00
|
|
|
void GroovesharkService::CreateNewPlaylist() {
|
|
|
|
QString name = QInputDialog::getText(NULL,
|
|
|
|
tr("Create a new Grooveshark playlist"),
|
|
|
|
tr("Name"),
|
|
|
|
QLineEdit::Normal);
|
|
|
|
if (name.isEmpty()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
QList<Param> parameters;
|
|
|
|
parameters << Param("name", name)
|
|
|
|
<< Param("songIDs", QVariantList());
|
2011-11-16 00:34:36 +01:00
|
|
|
QNetworkReply* reply = CreateRequest("createPlaylist", parameters);
|
2011-11-05 02:34:49 +01:00
|
|
|
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);
|
2011-12-01 23:46:27 +01:00
|
|
|
PlaylistInfo playlist_info(playlist_id, name, new_playlist_item);
|
2011-11-05 02:34:49 +01:00
|
|
|
playlist_info.item_ = new_playlist_item;
|
2012-06-27 01:21:57 +02:00
|
|
|
playlists_parent_->appendRow(new_playlist_item);
|
2011-11-05 02:34:49 +01:00
|
|
|
playlists_.insert(playlist_id, playlist_info);
|
|
|
|
}
|
|
|
|
|
|
|
|
void GroovesharkService::DeleteCurrentPlaylist() {
|
2012-03-11 15:44:43 +01:00
|
|
|
if (model()->current_index().data(InternetModel::Role_Type).toInt() !=
|
2011-11-05 02:34:49 +01:00
|
|
|
InternetModel::Type_UserPlaylist) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-03-11 15:44:43 +01:00
|
|
|
int playlist_id = model()->current_index().data(Role_UserPlaylistId).toInt();
|
2011-11-05 02:34:49 +01:00
|
|
|
DeletePlaylist(playlist_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
void GroovesharkService::DeletePlaylist(int playlist_id) {
|
|
|
|
if (!playlists_.contains(playlist_id)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
boost::scoped_ptr<QMessageBox> 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<Param> parameters;
|
|
|
|
parameters << Param("playlistID", playlist_id);
|
2011-11-16 00:34:36 +01:00
|
|
|
QNetworkReply* reply = CreateRequest("deletePlaylist", parameters);
|
2011-11-05 02:34:49 +01:00
|
|
|
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);
|
2012-06-27 01:21:57 +02:00
|
|
|
playlists_parent_->removeRow(playlist_info.item_->row());
|
2011-11-05 02:34:49 +01:00
|
|
|
}
|
|
|
|
|
2011-11-28 21:59:25 +01:00
|
|
|
void GroovesharkService::RenameCurrentPlaylist() {
|
2012-03-11 15:44:43 +01:00
|
|
|
const QModelIndex& index(model()->current_index());
|
|
|
|
|
|
|
|
if (index.data(InternetModel::Role_Type).toInt() != InternetModel::Type_UserPlaylist
|
|
|
|
|| index.data(Role_PlaylistType).toInt() != UserPlaylist) {
|
2011-11-28 21:59:25 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-03-11 15:44:43 +01:00
|
|
|
const int playlist_id = index.data(Role_UserPlaylistId).toInt();
|
2011-11-28 21:59:25 +01:00
|
|
|
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(NULL,
|
|
|
|
tr("Rename \"%1\" playlist").arg(old_name),
|
|
|
|
tr("Name"),
|
2011-12-22 20:25:45 +01:00
|
|
|
QLineEdit::Normal,
|
|
|
|
old_name);
|
2011-11-28 21:59:25 +01:00
|
|
|
if (new_name.isEmpty()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
QList<Param> 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);
|
|
|
|
}
|
|
|
|
|
2011-11-02 00:02:49 +01:00
|
|
|
void GroovesharkService::AddUserFavoriteSong(int song_id) {
|
2012-02-12 14:41:50 +01:00
|
|
|
int task_id = app_->task_manager()->StartTask(tr("Adding song to favorites"));
|
2011-11-02 00:02:49 +01:00
|
|
|
QList<Param> parameters;
|
|
|
|
parameters << Param("songID", song_id);
|
2011-11-16 00:34:36 +01:00
|
|
|
QNetworkReply* reply = CreateRequest("addUserFavoriteSong", parameters);
|
2011-11-02 00:02:49 +01:00
|
|
|
NewClosure(reply, SIGNAL(finished()),
|
2011-11-23 01:07:40 +01:00
|
|
|
this, SLOT(UserFavoriteSongAdded(QNetworkReply*, int)),
|
|
|
|
reply, task_id);
|
2011-11-02 00:02:49 +01:00
|
|
|
}
|
|
|
|
|
2011-11-23 01:07:40 +01:00
|
|
|
void GroovesharkService::UserFavoriteSongAdded(QNetworkReply* reply, int task_id) {
|
2011-11-02 00:02:49 +01:00
|
|
|
reply->deleteLater();
|
2012-02-12 14:41:50 +01:00
|
|
|
app_->task_manager()->SetTaskFinished(task_id);
|
2011-11-02 00:02:49 +01:00
|
|
|
|
|
|
|
QVariantMap result = ExtractResult(reply);
|
|
|
|
if (!result["success"].toBool()) {
|
|
|
|
qLog(Warning) << "Grooveshark addUserFavoriteSong failed";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// Refresh user's favorites list
|
|
|
|
RetrieveUserFavorites();
|
|
|
|
}
|
|
|
|
|
2012-07-21 18:31:08 +02:00
|
|
|
void GroovesharkService::AddUserLibrarySongs(const QList<int>& songs_ids) {
|
2012-07-21 18:09:16 +02:00
|
|
|
int task_id = app_->task_manager()->StartTask(tr("Adding song to My Music"));
|
|
|
|
QList<Param> parameters;
|
|
|
|
|
|
|
|
// Convert songs ids to QVariant
|
|
|
|
QVariantList songs_ids_qvariant;
|
|
|
|
foreach (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();
|
|
|
|
}
|
|
|
|
|
2011-11-02 23:41:58 +01:00
|
|
|
void GroovesharkService::RemoveCurrentFromPlaylist() {
|
2012-05-11 21:28:28 +02:00
|
|
|
const QModelIndexList& indexes(model()->selected_indexes());
|
|
|
|
QMap<int, QList<int> > playlists_songs_ids;
|
|
|
|
foreach (const QModelIndex& index, indexes) {
|
2012-03-11 15:44:43 +01:00
|
|
|
|
2012-05-11 21:28:28 +02:00
|
|
|
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;
|
|
|
|
}
|
2011-11-02 23:41:58 +01:00
|
|
|
}
|
|
|
|
|
2012-05-11 21:28:28 +02:00
|
|
|
for (QMap<int, QList<int> >::const_iterator it = playlists_songs_ids.constBegin();
|
|
|
|
it != playlists_songs_ids.constEnd();
|
|
|
|
++it) {
|
|
|
|
RemoveFromPlaylist(it.key(), it.value());
|
2011-11-02 23:41:58 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-05-11 21:28:28 +02:00
|
|
|
void GroovesharkService::RemoveFromPlaylist(int playlist_id,
|
|
|
|
const QList<int>& songs_ids_to_remove) {
|
2011-11-02 23:41:58 +01:00
|
|
|
if (!playlists_.contains(playlist_id)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
QList<int> songs_ids = playlists_[playlist_id].songs_ids_;
|
2012-05-11 21:28:28 +02:00
|
|
|
foreach (const int song_id, songs_ids_to_remove) {
|
|
|
|
songs_ids.removeOne(song_id);
|
|
|
|
}
|
2011-11-02 23:41:58 +01:00
|
|
|
|
|
|
|
SetPlaylistSongs(playlist_id, songs_ids);
|
|
|
|
}
|
|
|
|
|
|
|
|
void GroovesharkService::RemoveCurrentFromFavorites() {
|
2012-05-11 21:46:07 +02:00
|
|
|
const QModelIndexList& indexes(model()->selected_indexes());
|
|
|
|
QList<int> songs_ids;
|
|
|
|
foreach (const QModelIndex& index, indexes) {
|
2012-03-11 15:44:43 +01:00
|
|
|
|
2012-05-11 21:46:07 +02:00
|
|
|
if (index.parent().data(Role_PlaylistType).toInt() != UserFavorites) {
|
|
|
|
continue;
|
|
|
|
}
|
2011-11-02 23:41:58 +01:00
|
|
|
|
2012-05-11 21:46:07 +02:00
|
|
|
int song_id = ExtractSongId(index.data(InternetModel::Role_Url).toUrl());
|
|
|
|
if (song_id) {
|
|
|
|
songs_ids << song_id;
|
|
|
|
}
|
2011-11-02 23:41:58 +01:00
|
|
|
}
|
2012-05-11 21:46:07 +02:00
|
|
|
|
|
|
|
RemoveFromFavorites(songs_ids);
|
2011-11-02 23:41:58 +01:00
|
|
|
}
|
|
|
|
|
2012-05-11 21:46:07 +02:00
|
|
|
void GroovesharkService::RemoveFromFavorites(const QList<int>& songs_ids_to_remove) {
|
|
|
|
if (songs_ids_to_remove.isEmpty())
|
|
|
|
return;
|
|
|
|
|
2012-07-21 18:09:16 +02:00
|
|
|
int task_id = app_->task_manager()->StartTask(tr("Removing songs from favorites"));
|
2011-11-02 23:41:58 +01:00
|
|
|
QList<Param> parameters;
|
2012-05-11 21:46:07 +02:00
|
|
|
|
|
|
|
// Convert song ids to QVariant
|
|
|
|
QVariantList songs_ids_qvariant;
|
|
|
|
foreach (const int song_id, songs_ids_to_remove) {
|
|
|
|
songs_ids_qvariant << QVariant(song_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
parameters << Param("songIDs", songs_ids_qvariant);
|
2011-11-16 00:34:36 +01:00
|
|
|
QNetworkReply* reply = CreateRequest("removeUserFavoriteSongs", parameters);
|
2011-11-02 23:41:58 +01:00
|
|
|
NewClosure(reply, SIGNAL(finished()), this,
|
2012-07-21 18:09:16 +02:00
|
|
|
SLOT(SongsRemovedFromFavorites(QNetworkReply*, int)), reply, task_id);
|
2011-11-02 23:41:58 +01:00
|
|
|
}
|
|
|
|
|
2012-07-21 18:09:16 +02:00
|
|
|
void GroovesharkService::SongsRemovedFromFavorites(QNetworkReply* reply, int task_id) {
|
2012-02-12 14:41:50 +01:00
|
|
|
app_->task_manager()->SetTaskFinished(task_id);
|
2011-11-02 23:41:58 +01:00
|
|
|
reply->deleteLater();
|
|
|
|
|
|
|
|
QVariantMap result = ExtractResult(reply);
|
|
|
|
if (!result["success"].toBool()) {
|
|
|
|
qLog(Warning) << "Grooveshark removeUserFavoriteSongs failed";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
RetrieveUserFavorites();
|
|
|
|
}
|
|
|
|
|
2012-07-21 18:09:16 +02:00
|
|
|
void GroovesharkService::RemoveCurrentFromLibrary() {
|
|
|
|
const QModelIndexList& indexes(model()->selected_indexes());
|
|
|
|
QList<int> songs_ids;
|
|
|
|
|
|
|
|
foreach (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<int>& 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<Param> parameters;
|
|
|
|
|
|
|
|
// Convert song ids to QVariant
|
|
|
|
QVariantList songs_ids_qvariant;
|
|
|
|
foreach (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<Param>& params,
|
|
|
|
bool use_https) {
|
|
|
|
|
2011-09-02 00:28:11 +02:00
|
|
|
QVariantMap request_params;
|
|
|
|
request_params.insert("method", method_name);
|
|
|
|
|
2011-09-13 22:32:10 +02:00
|
|
|
QVariantMap header;
|
|
|
|
header.insert("wsKey", kApiKey);
|
2011-11-16 00:34:36 +01:00
|
|
|
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
|
2011-09-13 22:32:10 +02:00
|
|
|
qLog(Warning) << "Session ID is empty: will not be added to query";
|
|
|
|
}
|
2011-11-16 00:34:36 +01:00
|
|
|
} else {
|
|
|
|
header.insert("sessionID", session_id_);
|
2011-09-13 22:32:10 +02:00
|
|
|
}
|
|
|
|
request_params.insert("header", header);
|
2011-09-02 00:28:11 +02:00
|
|
|
|
|
|
|
QVariantMap parameters;
|
|
|
|
foreach(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);
|
2011-09-13 22:32:10 +02:00
|
|
|
if (use_https) {
|
|
|
|
url.setScheme("https");
|
|
|
|
}
|
2011-09-20 00:26:24 +02:00
|
|
|
url.setQueryItems( QList<QPair<QString, QString> >() << QPair<QString, QString>("sig", Utilities::HmacMd5(api_key_, post_params).toHex()));
|
2011-09-02 00:28:11 +02:00
|
|
|
QNetworkRequest req(url);
|
|
|
|
QNetworkReply *reply = network_->post(req, post_params);
|
|
|
|
|
2012-01-08 18:46:50 +01:00
|
|
|
if (use_https) {
|
|
|
|
connect(reply, SIGNAL(sslErrors(QList<QSslError>)),
|
|
|
|
SLOT(RequestSslErrors(QList<QSslError>)));
|
|
|
|
}
|
|
|
|
|
2011-09-02 00:28:11 +02:00
|
|
|
return reply;
|
|
|
|
}
|
2011-09-13 22:32:10 +02:00
|
|
|
|
2012-01-08 18:46:50 +01:00
|
|
|
void GroovesharkService::RequestSslErrors(const QList<QSslError>& errors) {
|
|
|
|
QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
|
|
|
|
|
|
|
|
foreach (const QSslError& error, errors) {
|
|
|
|
emit StreamError("SSL error occurred in Grooveshark request for " +
|
|
|
|
reply->url().toString() + ": " + error.errorString());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-11-29 13:57:35 +01:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2011-10-05 21:59:15 +02:00
|
|
|
QVariantMap GroovesharkService::ExtractResult(QNetworkReply* reply) {
|
2011-09-13 22:32:10 +02:00
|
|
|
QJson::Parser parser;
|
|
|
|
bool ok;
|
|
|
|
QVariantMap result = parser.parse(reply, &ok).toMap();
|
|
|
|
if (!ok) {
|
2011-10-05 21:59:15 +02:00
|
|
|
qLog(Error) << "Error while parsing Grooveshark result";
|
2011-09-13 22:32:10 +02:00
|
|
|
}
|
2011-11-06 18:40:06 +01:00
|
|
|
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["message"].toString();
|
|
|
|
switch (error["code"].toInt()) {
|
|
|
|
case 100: // User auth required
|
|
|
|
case 102: // User premium 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;
|
|
|
|
}
|
|
|
|
}
|
2011-09-13 22:32:10 +02:00
|
|
|
return result["result"].toMap();
|
|
|
|
}
|
2011-09-24 12:06:31 +02:00
|
|
|
|
2011-10-05 21:59:15 +02:00
|
|
|
SongList GroovesharkService::ExtractSongs(const QVariantMap& result) {
|
2011-09-24 12:06:31 +02:00
|
|
|
QVariantList result_songs = result["songs"].toList();
|
|
|
|
SongList songs;
|
|
|
|
for (int i=0; i<result_songs.size(); ++i) {
|
|
|
|
QVariantMap result_song = result_songs[i].toMap();
|
2011-11-29 13:57:35 +01:00
|
|
|
songs << ExtractSong(result_song);
|
2011-09-24 12:06:31 +02:00
|
|
|
}
|
|
|
|
return songs;
|
|
|
|
}
|
2011-10-30 23:59:43 +01:00
|
|
|
|
2011-11-29 13:57:35 +01:00
|
|
|
Song GroovesharkService::ExtractSong(const QVariantMap& result_song) {
|
|
|
|
Song song;
|
2011-12-01 21:46:16 +01:00
|
|
|
if (!result_song.isEmpty()) {
|
|
|
|
int song_id = result_song["SongID"].toInt();
|
|
|
|
QString song_name = result_song["SongName"].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();
|
2012-02-28 23:22:09 +01:00
|
|
|
qint64 duration = result_song["EstimateDuration"].toInt() * kNsecPerSec;
|
|
|
|
song.Init(song_name, artist_name, album_name, duration);
|
2012-03-08 23:44:35 +01:00
|
|
|
QVariant cover = result_song["CoverArtFilename"];
|
|
|
|
if (cover.isValid()) {
|
|
|
|
song.set_art_automatic(QString(kUrlCover) + cover.toString());
|
|
|
|
}
|
2012-02-28 23:22:09 +01:00
|
|
|
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());
|
|
|
|
}
|
2011-12-01 21:46:16 +01:00
|
|
|
// 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
|
2012-09-26 17:09:13 +02:00
|
|
|
song.set_url(QUrl(QString("grooveshark://%1/%2/%3").arg(artist_id).arg(album_id).arg(song_id)));
|
2011-12-01 21:46:16 +01:00
|
|
|
}
|
2011-11-29 13:57:35 +01:00
|
|
|
return song;
|
|
|
|
}
|
|
|
|
|
2011-10-30 23:59:43 +01:00
|
|
|
QList<int> GroovesharkService::ExtractSongsIds(const QVariantMap& result) {
|
|
|
|
QVariantList result_songs = result["songs"].toList();
|
|
|
|
QList<int> 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;
|
|
|
|
}
|
|
|
|
|
2011-11-02 23:41:58 +01:00
|
|
|
QList<int> GroovesharkService::ExtractSongsIds(const QList<QUrl>& urls) {
|
2011-10-30 23:59:43 +01:00
|
|
|
QList<int> songs_ids;
|
|
|
|
foreach (const QUrl& url, urls) {
|
2011-11-02 23:41:58 +01:00
|
|
|
int song_id = ExtractSongId(url);
|
|
|
|
if (song_id) {
|
|
|
|
songs_ids << song_id;
|
2011-10-30 23:59:43 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return songs_ids;
|
|
|
|
}
|
2011-11-02 23:41:58 +01:00
|
|
|
|
|
|
|
int GroovesharkService::ExtractSongId(const QUrl& url) {
|
|
|
|
if (url.scheme() == "grooveshark") {
|
2011-11-29 23:52:19 +01:00
|
|
|
QStringList ids = url.toString().remove("grooveshark://").split("/");
|
|
|
|
if (ids.size() == 3)
|
|
|
|
// Returns the third id: song id
|
|
|
|
return ids[2].toInt();
|
2011-11-02 23:41:58 +01:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2012-05-16 01:30:18 +02:00
|
|
|
|
|
|
|
QList<GroovesharkService::PlaylistInfo> GroovesharkService::ExtractPlaylistInfo(const QVariantMap& result) {
|
|
|
|
QVariantList playlists_qvariant = result["playlists"].toList();
|
|
|
|
|
|
|
|
QList<PlaylistInfo> playlists;
|
|
|
|
|
|
|
|
// Get playlists info
|
|
|
|
foreach (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
|
2012-06-27 01:21:57 +02:00
|
|
|
qSort(playlists.begin(), playlists.end());
|
2012-05-16 01:30:18 +02:00
|
|
|
|
|
|
|
return playlists;
|
|
|
|
}
|