mirror of
https://github.com/clementine-player/Clementine
synced 2025-02-01 11:56:45 +01:00
Add the ability to play streaming songs from GrooveShark
This commit is contained in:
parent
d380c2e49d
commit
5dfa4f4838
@ -130,6 +130,7 @@ set(SOURCES
|
||||
internet/groovesharksearchplaylisttype.cpp
|
||||
internet/groovesharkservice.cpp
|
||||
internet/groovesharksettingspage.cpp
|
||||
internet/groovesharkurlhandler.cpp
|
||||
internet/icecastbackend.cpp
|
||||
internet/icecastfilterwidget.cpp
|
||||
internet/icecastmodel.cpp
|
||||
@ -369,6 +370,7 @@ set(HEADERS
|
||||
internet/groovesharksearchplaylisttype.h
|
||||
internet/groovesharkservice.h
|
||||
internet/groovesharksettingspage.h
|
||||
internet/groovesharkurlhandler.h
|
||||
internet/icecastbackend.h
|
||||
internet/icecastfilterwidget.h
|
||||
internet/icecastmodel.h
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <QMessageBox>
|
||||
#include <QNetworkReply>
|
||||
#include <QNetworkRequest>
|
||||
#include <QTimer>
|
||||
|
||||
#include <qjson/parser.h>
|
||||
#include <qjson/serializer.h>
|
||||
@ -28,6 +29,7 @@
|
||||
|
||||
#include "internetmodel.h"
|
||||
#include "groovesharksearchplaylisttype.h"
|
||||
#include "groovesharkurlhandler.h"
|
||||
|
||||
#include "core/database.h"
|
||||
#include "core/logging.h"
|
||||
@ -57,10 +59,11 @@ const char* GrooveSharkService::kUrl = "http://api.grooveshark.com/ws/3.0/";
|
||||
|
||||
const int GrooveSharkService::kSongSearchLimit = 50;
|
||||
|
||||
typedef QPair<QString, QString> Param;
|
||||
typedef QPair<QString, QVariant> Param;
|
||||
|
||||
GrooveSharkService::GrooveSharkService(InternetModel *parent)
|
||||
: InternetService(kServiceName, parent, parent),
|
||||
url_handler_(new GrooveSharkUrlHandler(this, this)),
|
||||
pending_search_playlist_(NULL),
|
||||
root_(NULL),
|
||||
search_(NULL),
|
||||
@ -69,6 +72,7 @@ GrooveSharkService::GrooveSharkService(InternetModel *parent)
|
||||
api_key_(QByteArray::fromBase64(kApiSecret)),
|
||||
login_state_(LoginState_OtherError) {
|
||||
|
||||
model()->player()->RegisterUrlHandler(url_handler_);
|
||||
model()->player()->playlists()->RegisterSpecialPlaylistType(new GrooveSharkSearchPlaylistType(this));
|
||||
|
||||
// Get already existing (authenticated) session id, if any
|
||||
@ -156,6 +160,57 @@ void GrooveSharkService::SearchSongsFinished() {
|
||||
pending_search_playlist_->InsertSongs(songs);
|
||||
}
|
||||
|
||||
void GrooveSharkService::InitCountry() {
|
||||
if (!country_.isEmpty())
|
||||
return;
|
||||
// Get country info
|
||||
QNetworkReply *reply_country;
|
||||
|
||||
reply_country = CreateRequest("getCountry", QList<Param>(), true);
|
||||
// Wait for the reply
|
||||
{
|
||||
QEventLoop event_loop;
|
||||
QTimer timeout_timer;
|
||||
connect(&timeout_timer, SIGNAL(timeout()), &event_loop, SLOT(quit()));
|
||||
connect(reply_country, SIGNAL(finished()), &event_loop, SLOT(quit()));
|
||||
timeout_timer.start(3000);
|
||||
event_loop.exec();
|
||||
if (!timeout_timer.isActive()) {
|
||||
qLog(Error) << "GrooveShark request timeout";
|
||||
return;
|
||||
}
|
||||
timeout_timer.stop();
|
||||
}
|
||||
country_ = ExtractResult(reply_country);
|
||||
}
|
||||
|
||||
QUrl GrooveSharkService::GetStreamingUrlFromSongId(const QString& song_id) {
|
||||
QList<Param> parameters;
|
||||
QNetworkReply *reply;
|
||||
|
||||
InitCountry();
|
||||
parameters << Param("songID", song_id)
|
||||
<< Param("country", country_);
|
||||
reply = CreateRequest("getSubscriberStreamKey", parameters, true);
|
||||
// Wait for the 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(3000);
|
||||
event_loop.exec();
|
||||
if (!timeout_timer.isActive()) {
|
||||
qLog(Error) << "GrooveShark request timeout";
|
||||
return QUrl();
|
||||
}
|
||||
timeout_timer.stop();
|
||||
}
|
||||
QVariantMap result = ExtractResult(reply);
|
||||
|
||||
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
|
||||
@ -310,7 +365,7 @@ QNetworkReply* GrooveSharkService::CreateRequest(const QString& method_name, QLi
|
||||
if (use_https) {
|
||||
url.setScheme("https");
|
||||
}
|
||||
url.setQueryItems( QList<Param>() << Param("sig", Utilities::HmacMd5(api_key_, post_params).toHex()));
|
||||
url.setQueryItems( QList<QPair<QString, QString> >() << QPair<QString, QString>("sig", Utilities::HmacMd5(api_key_, post_params).toHex()));
|
||||
QNetworkRequest req(url);
|
||||
QNetworkReply *reply = network_->post(req, post_params);
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "internetmodel.h"
|
||||
#include "internetservice.h"
|
||||
|
||||
class GrooveSharkUrlHandler;
|
||||
class NetworkAccessManager;
|
||||
class Playlist;
|
||||
class QMenu;
|
||||
@ -53,12 +54,13 @@ class GrooveSharkService : public InternetService {
|
||||
void ShowContextMenu(const QModelIndex& index, const QPoint& global_pos);
|
||||
|
||||
void Search(const QString& text, Playlist* playlist, bool now = false);
|
||||
// User should be logged in to be able to generate streaming urls
|
||||
QUrl GetStreamingUrlFromSongId(const QString& song_id);
|
||||
void Login(const QString& username, const QString& password);
|
||||
void Logout();
|
||||
bool IsLoggedIn() { return !session_id_.isEmpty(); }
|
||||
// Persisted in the settings and updated on each Login().
|
||||
LoginState login_state() const { return login_state_; }
|
||||
|
||||
const QString& session_id() { return session_id_; }
|
||||
|
||||
|
||||
@ -90,19 +92,20 @@ class GrooveSharkService : public InternetService {
|
||||
|
||||
void OpenSearchTab();
|
||||
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<QPair<QString, QString> > params,
|
||||
QNetworkReply* CreateRequest(const QString& method_name, const QList<QPair<QString, QVariant> > params,
|
||||
bool need_authentication = false,
|
||||
bool use_https = false);
|
||||
// Convenient function for extracting result from reply, checking resulst's
|
||||
// validity, and deleting reply object
|
||||
// Convenient function for extracting result from reply
|
||||
QVariantMap ExtractResult(QNetworkReply* reply);
|
||||
void ResetSessionId();
|
||||
|
||||
|
||||
GrooveSharkUrlHandler* url_handler_;
|
||||
Playlist* pending_search_playlist_;
|
||||
|
||||
QStandardItem* root_;
|
||||
@ -117,6 +120,7 @@ class GrooveSharkService : public InternetService {
|
||||
QString password_; // In fact, password's md5 hash
|
||||
QString user_id_;
|
||||
QString session_id_;
|
||||
QMap<QString, QVariant> country_;
|
||||
QByteArray api_key_;
|
||||
|
||||
LoginState login_state_;
|
||||
|
35
src/internet/groovesharkurlhandler.cpp
Normal file
35
src/internet/groovesharkurlhandler.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
/* This file is part of Clementine.
|
||||
Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
|
||||
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/>.
|
||||
*/
|
||||
|
||||
#include "groovesharkservice.h"
|
||||
#include "groovesharkurlhandler.h"
|
||||
|
||||
#include "core/logging.h"
|
||||
|
||||
GrooveSharkUrlHandler::GrooveSharkUrlHandler(GrooveSharkService* service, QObject* parent)
|
||||
: UrlHandler(parent),
|
||||
service_(service) {
|
||||
}
|
||||
|
||||
UrlHandler::LoadResult GrooveSharkUrlHandler::StartLoading(const QUrl& url) {
|
||||
QString song_id = url.toString().remove("grooveshark://");
|
||||
QUrl streaming_url = service_->GetStreamingUrlFromSongId(song_id);
|
||||
qLog(Debug) << "GrooveShark Streaming URL: " << streaming_url;
|
||||
return LoadResult(url, LoadResult::TrackAvailable, streaming_url);
|
||||
}
|
||||
|
||||
|
39
src/internet/groovesharkurlhandler.h
Normal file
39
src/internet/groovesharkurlhandler.h
Normal file
@ -0,0 +1,39 @@
|
||||
/* This file is part of Clementine.
|
||||
Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
|
||||
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/>.
|
||||
*/
|
||||
|
||||
#ifndef GROOVESHARKURLHANDLER_H
|
||||
#define GROOVESHARKURLHANDLER_H
|
||||
|
||||
#include "core/urlhandler.h"
|
||||
|
||||
class GrooveSharkService;
|
||||
|
||||
class GrooveSharkUrlHandler : public UrlHandler {
|
||||
public:
|
||||
GrooveSharkUrlHandler(GrooveSharkService* service, QObject* parent);
|
||||
|
||||
QString scheme() const { return "grooveshark"; }
|
||||
LoadResult StartLoading(const QUrl& url);
|
||||
|
||||
private:
|
||||
GrooveSharkService* service_;
|
||||
QString last_song_id_;
|
||||
QString last_server_id_;
|
||||
QString last_stream_key;
|
||||
};
|
||||
|
||||
#endif // GROOVESHARKURLHANDLER_H
|
Loading…
x
Reference in New Issue
Block a user