diff --git a/src/SpotifyArduino.cpp b/src/SpotifyArduino.cpp index e3fe108..321417e 100644 --- a/src/SpotifyArduino.cpp +++ b/src/SpotifyArduino.cpp @@ -1025,6 +1025,89 @@ int SpotifyArduino::searchForSong(String query, int limit, processSearch searchC return statusCode; } +int SpotifyArduino::getPlaylist(String query, int limit, String market, processPlaylist playlistCallback, PlaylistResult results[]) +{ + +#ifdef SPOTIFY_DEBUG + Serial.println(SPOTIFY_PLAYLIST_ENDPOINT); + printStack(); +#endif + + // Get from https://arduinojson.org/v6/assistant/ + const size_t bufferSize = playlistDetailsBufferSize; + if (autoTokenRefresh) + { + checkAndRefreshAccessToken(); + } + + int statusCode = makeGetRequest((SPOTIFY_PLAYLIST_ENDPOINT + query + "?market=" + market + "&fields=tracks.items%28track%28name%2Curi%2Calbum%28name%2Curi%29%2Cartists%28name%2Curi%29%29").c_str(), _bearerToken); +#ifdef SPOTIFY_DEBUG + Serial.print("Status Code: "); + Serial.println(statusCode); +#endif + if (statusCode > 0) + { + skipHeaders(); + } + + if (statusCode == 200) + { + + // Allocate DynamicJsonDocument + DynamicJsonDocument doc(bufferSize); + + // Parse JSON object +#ifndef SPOTIFY_PRINT_JSON_PARSE + DeserializationError error = deserializeJson(doc, *client); +#else + ReadLoggingStream loggingStream(*client, Serial); + DeserializationError error = deserializeJson(doc, loggingStream); +#endif + //serializeJsonPretty(doc, Serial); + if (!error) + { + + uint8_t totalResults = doc["tracks"]["items"].size(); + + Serial.print("Total Results: "); + Serial.println(totalResults); + + PlaylistResult playlistResult; + for (int i = 0; i < totalResults; i++) + { + //Polling track information + JsonObject result = doc["tracks"]["items"][i]["track"]; + playlistResult.trackUri = result["uri"].as(); + playlistResult.trackName = result["name"].as(); + playlistResult.albumUri = result["album"]["uri"].as(); + playlistResult.albumName = result["album"]["name"].as(); + + playlistResult.artistName = result["artists"][0]["name"]; + playlistResult.artistUri = result["artists"][0]["uri"]; + + results[i] = playlistResult; + + if (i >= limit-1 || !playlistCallback(playlistResult, i, totalResults)) + { + //Break at the limit or when indicated + break; + } + } + } + else + { +#ifdef SPOTIFY_SERIAL_OUTPUT + Serial.print(F("deserializeJson() failed with code ")); + Serial.println(error.c_str()); +#endif + statusCode = -1; + } + } + + closeClient(); + return statusCode; +} + int SpotifyArduino::commonGetImage(char *imageUrl) { #ifdef SPOTIFY_DEBUG diff --git a/src/SpotifyArduino.h b/src/SpotifyArduino.h index 102ca46..5f7dffc 100644 --- a/src/SpotifyArduino.h +++ b/src/SpotifyArduino.h @@ -78,11 +78,13 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #define SPOTIFY_SEEK_ENDPOINT "/v1/me/player/seek" +#define SPOTIFY_PLAYLIST_ENDPOINT "/v1/playlists/" + #define SPOTIFY_TOKEN_ENDPOINT "/api/token" #define SPOTIFY_NUM_ALBUM_IMAGES 3 // Max spotify returns is 3, but the third one is probably too big for an ESP -#define SPOTIFY_MAX_NUM_ARTISTS 5 +#define SPOTIFY_MAX_NUM_ARTISTS 5 #define SPOTIFY_ACCESS_TOKEN_LENGTH 309 @@ -146,6 +148,16 @@ struct SearchResult int numImages; }; +struct PlaylistResult +{ + const char *albumName; + const char *albumUri; + const char *trackName; + const char *trackUri; + const char *artistName; + const char *artistUri; +}; + struct CurrentlyPlaying { SpotifyArtist artists[SPOTIFY_MAX_NUM_ARTISTS]; @@ -167,6 +179,8 @@ typedef void (*processCurrentlyPlaying)(CurrentlyPlaying currentlyPlaying); typedef void (*processPlayerDetails)(PlayerDetails playerDetails); typedef bool (*processDevices)(SpotifyDevice device, int index, int numDevices); typedef bool (*processSearch)(SearchResult result, int index, int numResults); +typedef bool (*processPlaylist)(PlaylistResult result, int index, int numResults); + class SpotifyArduino { @@ -207,6 +221,9 @@ class SpotifyArduino //Search int searchForSong(String query, int limit, processSearch searchCallback, SearchResult results[]); + //Playlist + int getPlaylist(String query, int limit, String market, processPlaylist playlistCallback, PlaylistResult results[]); + // Image methods bool getImage(char *imageUrl, Stream *file); bool getImage(char *imageUrl, uint8_t **image, int *imageLength); @@ -216,6 +233,7 @@ class SpotifyArduino int playerDetailsBufferSize = 2000; int getDevicesBufferSize = 3000; int searchDetailsBufferSize = 3000; + int playlistDetailsBufferSize = 3000; bool autoTokenRefresh = true; Client *client; void lateInit(const char *clientId, const char *clientSecret, const char *refreshToken = "");