Skip to content

Instantly share code, notes, and snippets.

Created January 19, 2014 15:08
Show Gist options
  • Save anonymous/8506110 to your computer and use it in GitHub Desktop.
Save anonymous/8506110 to your computer and use it in GitHub Desktop.
diff --git a/src/libpiano/piano.h b/src/libpiano/piano.h
index ce66171..6242242 100644
--- a/src/libpiano/piano.h
+++ b/src/libpiano/piano.h
@@ -94,6 +94,7 @@ typedef struct PianoSong {
char *feedbackId;
char *detailUrl;
char *trackToken;
+ char *adToken;
float fileGain;
PianoSongRating_t rating;
PianoAudioFormat_t audioFormat;
@@ -169,6 +170,7 @@ typedef enum {
PIANO_REQUEST_GET_STATION_INFO = 20,
PIANO_REQUEST_DELETE_FEEDBACK = 21,
PIANO_REQUEST_DELETE_SEED = 22,
+ PIANO_REQUEST_GET_AD_METADATA = 23,
} PianoRequestType_t;
typedef struct PianoRequest {
@@ -244,6 +246,10 @@ typedef struct {
PianoStation_t *station;
} PianoRequestDataDeleteSeed_t;
+typedef struct {
+ char *token;
+} PianoRequestDataGetAdMetadata_t;
+
/* pandora error code offset */
#define PIANO_RET_OFFSET 1024
typedef enum {
diff --git a/src/libpiano/request.c b/src/libpiano/request.c
index 82bf350..8a424df 100644
--- a/src/libpiano/request.c
+++ b/src/libpiano/request.c
@@ -80,6 +80,10 @@ PianoReturn_t PianoRequest (PianoHandle_t *ph, PianoRequest_t *req,
json_object_new_string ("5"));
json_object_object_add (j, "includeUrls",
json_object_new_boolean (true));
+ json_object_object_add (j, "returnDeviceType",
+ json_object_new_boolean (true));
+ json_object_object_add (j, "returnUpdatePromptVersions",
+ json_object_new_boolean (true));
snprintf (req->urlPath, sizeof (req->urlPath),
PIANO_RPC_PATH "method=auth.partnerLogin");
break;
@@ -133,6 +137,22 @@ PianoReturn_t PianoRequest (PianoHandle_t *ph, PianoRequest_t *req,
json_object_object_add (j, "stationToken",
json_object_new_string (reqData->station->id));
+ json_object_object_add (j, "includeTrackLength",
+ json_object_new_boolean (true));
+ json_object_object_add (j, "includeAudioToken",
+ json_object_new_boolean (true));
+ json_object_object_add (j, "xplatformAdCapable",
+ json_object_new_boolean (true));
+ json_object_object_add (j, "includeAudioReceiptUrl",
+ json_object_new_boolean (true));
+ json_object_object_add (j, "includeCompetitiveSepIndicator",
+ json_object_new_boolean (true));
+ json_object_object_add (j, "includeCompletePlaylist",
+ json_object_new_boolean (true));
+ json_object_object_add (j, "includeTrackOptions",
+ json_object_new_boolean (true));
+ json_object_object_add (j, "audioAdPodCapable",
+ json_object_new_boolean (true));
method = "station.getPlaylist";
break;
@@ -398,6 +418,27 @@ PianoReturn_t PianoRequest (PianoHandle_t *ph, PianoRequest_t *req,
break;
}
+ case PIANO_REQUEST_GET_AD_METADATA: {
+ PianoRequestDataGetAdMetadata_t *reqData = req->data;
+
+ assert (reqData != NULL);
+ assert (reqData->token != NULL);
+
+ json_object_object_add (j, "adToken",
+ json_object_new_string (reqData->token));
+ json_object_object_add (j, "returnAdTrackingTokens",
+ json_object_new_boolean (true));
+ json_object_object_add (j, "supportAudioAds",
+ json_object_new_boolean (true));
+ json_object_object_add (j, "includeBannerAd",
+ json_object_new_boolean (true));
+ json_object_object_add (j, "includeListeningHours",
+ json_object_new_boolean (true));
+
+ method = "ad.getAdMetadata";
+ break;
+ }
+
/* "high-level" wrapper */
case PIANO_REQUEST_RATE_SONG: {
/* love/ban song */
diff --git a/src/libpiano/response.c b/src/libpiano/response.c
index 41bbfd3..7ef9a92 100644
--- a/src/libpiano/response.c
+++ b/src/libpiano/response.c
@@ -26,6 +26,7 @@ THE SOFTWARE.
#define _DARWIN_C_SOURCE /* strdup() on OS X */
#endif
+#include <stdio.h>
#include <json.h>
#include <string.h>
#include <assert.h>
@@ -37,7 +38,12 @@ THE SOFTWARE.
#include "crypt.h"
static char *PianoJsonStrdup (json_object *j, const char *key) {
- return strdup (json_object_get_string (json_object_object_get (j, key)));
+ json_object * const o = json_object_object_get (j, key);
+ if (o != NULL) {
+ return strdup (json_object_get_string (o));
+ } else {
+ return NULL;
+ }
}
static void PianoJsonParseStation (json_object *j, PianoStation_t *s) {
@@ -232,18 +238,12 @@ PianoReturn_t PianoResponse (PianoHandle_t *ph, PianoRequest_t *req) {
return PIANO_RET_OUT_OF_MEMORY;
}
- if (json_object_object_get (s, "artistName") == NULL) {
- free (song);
- continue;
- }
-
/* get audio url based on selected quality */
static const char *qualityMap[] = {"", "lowQuality", "mediumQuality",
"highQuality"};
assert (reqData->quality < sizeof (qualityMap)/sizeof (*qualityMap));
static const char *formatMap[] = {"", "aacplus", "mp3"};
json_object *map = json_object_object_get (s, "audioUrlMap");
- assert (map != NULL);
if (map != NULL) {
map = json_object_object_get (map, qualityMap[reqData->quality]);
@@ -275,6 +275,7 @@ PianoReturn_t PianoResponse (PianoHandle_t *ph, PianoRequest_t *req) {
song->stationId = PianoJsonStrdup (s, "stationId");
song->coverArt = PianoJsonStrdup (s, "albumArtUrl");
song->detailUrl = PianoJsonStrdup (s, "songDetailUrl");
+ song->adToken = PianoJsonStrdup (s, "adToken");
song->fileGain = json_object_get_double (
json_object_object_get (s, "trackGain"));
switch (json_object_get_int (json_object_object_get (s,
@@ -591,6 +592,11 @@ PianoReturn_t PianoResponse (PianoHandle_t *ph, PianoRequest_t *req) {
}
break;
}
+
+ case PIANO_REQUEST_GET_AD_METADATA: {
+ printf ("ad.getAdMetadata returned: %s\n", req->responseData);
+ break;
+ }
}
cleanup:
diff --git a/src/libwaitress/waitress.c b/src/libwaitress/waitress.c
index af3cc1a..1e6247d 100644
--- a/src/libwaitress/waitress.c
+++ b/src/libwaitress/waitress.c
@@ -923,7 +923,7 @@ static WaitressReturn_t WaitressSendRequest (WaitressHandle_t *waith) {
WRITE_RET (buf, strlen (buf));
snprintf (buf, WAITRESS_BUFFER_SIZE,
- "Host: %s\r\nUser-Agent: " PACKAGE "\r\nConnection: Close\r\n",
+ "Host: %s\r\nUser-Agent: Pandora/1.2.3 Android/4.4.1 12345\r\nConnection: Close\r\n",
waith->url.host);
WRITE_RET (buf, strlen (buf));
diff --git a/src/main.c b/src/main.c
index 4cca654..2bd7959 100644
--- a/src/main.c
+++ b/src/main.c
@@ -224,6 +224,7 @@ static void BarMainGetPlaylist (BarApp_t *app) {
PianoReturn_t pRet;
WaitressReturn_t wRet;
PianoRequestDataGetPlaylist_t reqData;
+
reqData.station = app->curStation;
reqData.quality = app->settings.audioQuality;
@@ -246,6 +247,18 @@ static void BarMainGetPlaylist (BarApp_t *app) {
/* start new player thread
*/
static void BarMainStartPlayback (BarApp_t *app, pthread_t *playerThread) {
+ PianoReturn_t pRet;
+ WaitressReturn_t wRet;
+ PianoRequestDataGetAdMetadata_t adReqData;
+
+ if (app->playlist->adToken != NULL) {
+ adReqData.token = app->playlist->adToken;
+ BarUiMsg (&app->settings, MSG_INFO, "Fetching ads with token %s... ",
+ adReqData.token);
+ BarUiPianoCall (app, PIANO_REQUEST_GET_AD_METADATA,
+ &adReqData, &pRet, &wRet);
+ }
+
BarUiPrintSong (&app->settings, app->playlist, app->curStation->isQuickMix ?
PianoFindStationById (app->ph.stations,
app->playlist->stationId) : NULL);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment