diff --git a/spotifyblob/blob/spotifyclient.cpp b/spotifyblob/blob/spotifyclient.cpp index 1e2778908..d8dc3ae57 100644 --- a/spotifyblob/blob/spotifyclient.cpp +++ b/spotifyblob/blob/spotifyclient.cpp @@ -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(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(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 ; iConvertTrack(sp_albumbrowse_track(result, i), msg->add_track()); + } + + me->handler_->SendMessage(message); +} diff --git a/spotifyblob/blob/spotifyclient.h b/spotifyblob/blob/spotifyclient.h index c67822b92..5ee132a0f 100644 --- a/spotifyblob/blob/spotifyclient.h +++ b/spotifyblob/blob/spotifyclient.h @@ -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 pending_image_requests_; QMap image_callbacks_registered_; QMap pending_searches_; + QMap pending_album_browses_; int media_length_msec_; }; diff --git a/spotifyblob/common/spotifymessages.proto b/spotifyblob/common/spotifymessages.proto index 18d12d16a..6f132e1f5 100644 --- a/spotifyblob/common/spotifymessages.proto +++ b/spotifyblob/common/spotifymessages.proto @@ -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; } diff --git a/src/globalsearch/spotifysearchprovider.cpp b/src/globalsearch/spotifysearchprovider.cpp index 91f385cb7..fafc5a128 100644 --- a/src/globalsearch/spotifysearchprovider.cpp +++ b/src/globalsearch/spotifysearchprovider.cpp @@ -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::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 ; isongs << song; + } + + emit TracksLoaded(orig_id, mime_data); } diff --git a/src/globalsearch/spotifysearchprovider.h b/src/globalsearch/spotifysearchprovider.h index 9ca97973b..7daa553e3 100644 --- a/src/globalsearch/spotifysearchprovider.h +++ b/src/globalsearch/spotifysearchprovider.h @@ -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 queries_; QMap pending_art_; + QMap pending_tracks_; }; #endif // SPOTIFYSEARCHPROVIDER_H diff --git a/src/internet/spotifyserver.cpp b/src/internet/spotifyserver.cpp index 9bda3738e..90c5364e2 100644 --- a/src/internet/spotifyserver.cpp +++ b/src/internet/spotifyserver.cpp @@ -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); +} diff --git a/src/internet/spotifyserver.h b/src/internet/spotifyserver.h index 4b17249a7..cc7cde05a 100644 --- a/src/internet/spotifyserver.h +++ b/src/internet/spotifyserver.h @@ -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();