1
0
mirror of https://github.com/clementine-player/Clementine synced 2024-12-16 19:31:02 +01:00

Support for playing tracks from Spotify

This commit is contained in:
David Sansome 2011-08-29 03:26:59 +01:00
parent c1041ed6d4
commit 5aca9b7984
7 changed files with 121 additions and 1 deletions

View File

@ -224,6 +224,8 @@ void SpotifyClient::HandleMessage(const spotify_pb::SpotifyMessage& message) {
LoadImage(QStringFromStdString(message.image_request().id()));
} else if (message.has_sync_playlist_request()) {
SyncPlaylist(message.sync_playlist_request());
} else if (message.has_browse_album_request()) {
BrowseAlbum(QStringFromStdString(message.browse_album_request().uri()));
}
}
@ -856,3 +858,45 @@ void SpotifyClient::ImageLoaded(sp_image* image, void* userdata) {
SpotifyClient* me = reinterpret_cast<SpotifyClient*>(userdata);
me->TryImageAgain(image);
}
void SpotifyClient::BrowseAlbum(const QString& uri) {
// Get a link object from the URI
sp_link* link = sp_link_create_from_string(uri.toStdString().c_str());
if (!link) {
SendPlaybackError("Invalid Album URI");
return;
}
// Get the track from the link
sp_album* album = sp_link_as_album(link);
if (!album) {
SendPlaybackError("Spotify URI was not an album");
sp_link_release(link);
return;
}
sp_albumbrowse* browse =
sp_albumbrowse_create(session_, album, &AlbumBrowseComplete, this);
pending_album_browses_[browse] = uri;
}
void SpotifyClient::AlbumBrowseComplete(sp_albumbrowse* result, void* userdata) {
SpotifyClient* me = reinterpret_cast<SpotifyClient*>(userdata);
if (!me->pending_album_browses_.contains(result))
return;
QString uri = me->pending_album_browses_.take(result);
spotify_pb::SpotifyMessage message;
spotify_pb::BrowseAlbumResponse* msg = message.mutable_browse_album_response();
msg->set_uri(DataCommaSizeFromQString(uri));
const int count = sp_albumbrowse_num_tracks(result);
for (int i=0 ; i<count ; ++i) {
me->ConvertTrack(sp_albumbrowse_track(result, i), msg->add_track());
}
me->handler_->SendMessage(message);
}

View File

@ -92,6 +92,9 @@ private:
// Spotify image callbacks.
static void SP_CALLCONV ImageLoaded(sp_image* image, void* userdata);
// Spotify album browse callbacks.
static void SP_CALLCONV AlbumBrowseComplete(sp_albumbrowse* result, void* userdata);
// Request handlers.
void Login(const QString& username, const QString& password);
void Search(const spotify_pb::SearchRequest& req);
@ -99,6 +102,7 @@ private:
void SyncPlaylist(const spotify_pb::SyncPlaylistRequest& req);
void StartPlayback(const spotify_pb::PlaybackRequest& req);
void LoadImage(const QString& id_b64);
void BrowseAlbum(const QString& uri);
void SendPlaylistList();
@ -158,6 +162,7 @@ private:
QList<PendingImageRequest> pending_image_requests_;
QMap<sp_image*, int> image_callbacks_registered_;
QMap<sp_search*, spotify_pb::SearchRequest> pending_searches_;
QMap<sp_albumbrowse*, QString> pending_album_browses_;
int media_length_msec_;
};

View File

@ -128,6 +128,15 @@ message ImageResponse {
optional bytes data = 2;
}
message BrowseAlbumRequest {
required string uri = 1;
}
message BrowseAlbumResponse {
required string uri = 1;
repeated Track track = 2;
}
message SpotifyMessage {
optional LoginRequest login_request = 1;
optional LoginResponse login_response = 2;
@ -142,4 +151,6 @@ message SpotifyMessage {
optional ImageResponse image_response = 11;
optional SyncPlaylistRequest sync_playlist_request = 12;
optional SyncPlaylistProgress sync_playlist_progress = 13;
optional BrowseAlbumRequest browse_album_request = 14;
optional BrowseAlbumResponse browse_album_response = 15;
}

View File

@ -20,6 +20,8 @@
#include "internet/internetmodel.h"
#include "internet/spotifyserver.h"
#include "internet/spotifyservice.h"
#include "playlist/songmimedata.h"
#include "spotifyblob/common/spotifymessagehandler.h"
SpotifySearchProvider::SpotifySearchProvider(QObject* parent)
: SearchProvider(parent),
@ -44,6 +46,8 @@ SpotifyServer* SpotifySearchProvider::server() {
SLOT(SearchFinishedSlot(spotify_pb::SearchResponse)));
connect(server_, SIGNAL(ImageLoaded(QString,QImage)),
SLOT(ArtLoadedSlot(QString,QImage)));
connect(server_, SIGNAL(AlbumBrowseResults(spotify_pb::BrowseAlbumResponse)),
SLOT(AlbumBrowseResponse(spotify_pb::BrowseAlbumResponse)));
connect(server_, SIGNAL(destroyed()), SLOT(ServerDestroyed()));
return service_->server();
@ -134,7 +138,48 @@ void SpotifySearchProvider::ArtLoadedSlot(const QString& id, const QImage& image
}
void SpotifySearchProvider::LoadTracksAsync(int id, const Result& result) {
emit TracksLoaded(id, NULL);
switch (result.type_) {
case Result::Type_Track: {
SongMimeData* mime_data = new SongMimeData;
mime_data->songs = SongList() << result.metadata_;
emit TracksLoaded(id, mime_data);
break;
}
case Result::Type_Album: {
SpotifyServer* s = server();
if (!s) {
emit TracksLoaded(id, NULL);
return;
}
QString uri = result.metadata_.url().toString();
pending_tracks_[uri] = id;
s->AlbumBrowse(uri);
break;
}
}
}
void SpotifySearchProvider::AlbumBrowseResponse(const spotify_pb::BrowseAlbumResponse& response) {
QString uri = QStringFromStdString(response.uri());
QMap<QString, int>::iterator it = pending_tracks_.find(uri);
if (it == pending_tracks_.end())
return;
const int orig_id = it.value();
pending_tracks_.erase(it);
SongMimeData* mime_data = new SongMimeData;
for (int i=0 ; i<response.track_size() ; ++i) {
Song song;
SpotifyService::SongFromProtobuf(response.track(i), &song);
mime_data->songs << song;
}
emit TracksLoaded(orig_id, mime_data);
}

View File

@ -40,6 +40,8 @@ private slots:
void SearchFinishedSlot(const spotify_pb::SearchResponse& response);
void ArtLoadedSlot(const QString& id, const QImage& image);
void AlbumBrowseResponse(const spotify_pb::BrowseAlbumResponse& response);
private:
struct PendingState {
int orig_id_;
@ -54,6 +56,7 @@ private:
QMap<QString, PendingState> queries_;
QMap<QString, int> pending_art_;
QMap<QString, int> pending_tracks_;
};
#endif // SPOTIFYSEARCHPROVIDER_H

View File

@ -134,6 +134,8 @@ void SpotifyServer::HandleMessage(const spotify_pb::SpotifyMessage& message) {
}
} else if (message.has_sync_playlist_progress()) {
emit SyncPlaylistProgress(message.sync_playlist_progress());
} else if (message.has_browse_album_response()) {
emit AlbumBrowseResults(message.browse_album_response());
}
}
@ -214,3 +216,11 @@ void SpotifyServer::LoadImage(const QString& id) {
req->set_id(DataCommaSizeFromQString(id));
SendMessage(message);
}
void SpotifyServer::AlbumBrowse(const QString& uri) {
spotify_pb::SpotifyMessage message;
spotify_pb::BrowseAlbumRequest* req = message.mutable_browse_album_request();
req->set_uri(DataCommaSizeFromQString(uri));
SendMessage(message);
}

View File

@ -46,6 +46,7 @@ public:
void StartPlayback(const QString& uri, quint16 port);
void Search(const QString& text, int limit, int limit_album = 0);
void LoadImage(const QString& id);
void AlbumBrowse(const QString& uri);
int server_port() const;
@ -61,6 +62,7 @@ signals:
void SearchResults(const spotify_pb::SearchResponse& response);
void ImageLoaded(const QString& id, const QImage& image);
void SyncPlaylistProgress(const spotify_pb::SyncPlaylistProgress& progress);
void AlbumBrowseResults(const spotify_pb::BrowseAlbumResponse& response);
private slots:
void NewConnection();