Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

piano: Select quality instead of audio format

Pandora limited the audio formats we can request explicitly. Don’t rely
on this and use the formats available with the given partner
credentials. Closes #271.
  • Loading branch information...
commit 524abb97453f2140fcd3a7fa66d9d43851af19e1 1 parent b32348d
@PromyLOPh authored
View
5 contrib/pianobar.1
@@ -156,9 +156,8 @@ Increase volume.
Replacement for %@ in station format string. It's " @ " by default.
.TP
-.B audio_format = {aacplus-lofi,aacplus,mp3,mp3-hifi}
-Select audio format. aacplus is default if both libraries (faad, mad) are
-available. mp3-hifi is available for Pandora One customers only.
+.B audio_quality = {high, medium, low}
+Select audio quality.
.TP
.B autoselect = {1,0}
View
4 src/libpiano/piano.c
@@ -254,6 +254,10 @@ const char *PianoErrorToStr (PianoReturn_t ret) {
return "Wrong email address or password.";
break;
+ case PIANO_RET_QUALITY_UNAVAILABLE:
+ return "Selected audio quality is not available.";
+ break;
+
/* pandora error messages */
case PIANO_RET_P_INTERNAL:
return "Internal error.";
View
12 src/libpiano/piano.h
@@ -65,10 +65,15 @@ typedef enum {
PIANO_AF_UNKNOWN = 0,
PIANO_AF_AACPLUS = 1,
PIANO_AF_MP3 = 2,
- PIANO_AF_MP3_HI = 3,
- PIANO_AF_AACPLUS_LO = 4,
} PianoAudioFormat_t;
+typedef enum {
+ PIANO_AQ_UNKNOWN = 0,
+ PIANO_AQ_LOW = 1,
+ PIANO_AQ_MEDIUM = 2,
+ PIANO_AQ_HIGH = 3,
+} PianoAudioQuality_t;
+
typedef struct PianoSong {
char *artist;
char *stationId;
@@ -178,7 +183,7 @@ typedef struct {
typedef struct {
PianoStation_t *station;
- PianoAudioFormat_t format;
+ PianoAudioQuality_t quality;
PianoSong_t *retPlaylist;
} PianoRequestDataGetPlaylist_t;
@@ -245,6 +250,7 @@ typedef enum {
PIANO_RET_CONTINUE_REQUEST = 3,
PIANO_RET_OUT_OF_MEMORY = 4,
PIANO_RET_INVALID_LOGIN = 5,
+ PIANO_RET_QUALITY_UNAVAILABLE = 6,
/* pandora error codes */
PIANO_RET_P_INTERNAL = PIANO_RET_OFFSET+0,
View
31 src/libpiano/request.c
@@ -36,34 +36,6 @@ THE SOFTWARE.
#include "piano.h"
#include "crypt.h"
-/* convert audio format id to string
- * @param format id
- * @return constant string
- */
-static const char *PianoAudioFormatToString (PianoAudioFormat_t format) {
- switch (format) {
- case PIANO_AF_AACPLUS_LO:
- return "HTTP_32_AACPLUS";
- break;
-
- case PIANO_AF_AACPLUS:
- return "HTTP_64_AACPLUS";
- break;
-
- case PIANO_AF_MP3:
- return "HTTP_128_MP3";
- break;
-
- case PIANO_AF_MP3_HI:
- return "HTTP_192_MP3";
- break;
-
- default:
- return NULL;
- break;
- }
-}
-
/* prepare piano request (initializes request type, urlpath and postData)
* @param piano handle
* @param request structure
@@ -156,14 +128,11 @@ PianoReturn_t PianoRequest (PianoHandle_t *ph, PianoRequest_t *req,
assert (reqData != NULL);
assert (reqData->station != NULL);
assert (reqData->station->id != NULL);
- assert (reqData->format != PIANO_AF_UNKNOWN);
req->secure = true;
json_object_object_add (j, "stationToken",
json_object_new_string (reqData->station->id));
- json_object_object_add (j, "additionalAudioUrl",
- json_object_new_string (PianoAudioFormatToString (reqData->format)));
method = "station.getPlaylist";
break;
View
35 src/libpiano/response.c
@@ -228,6 +228,7 @@ PianoReturn_t PianoResponse (PianoHandle_t *ph, PianoRequest_t *req) {
assert (req->responseData != NULL);
assert (reqData != NULL);
+ assert (reqData->quality != PIANO_AQ_UNKNOWN);
json_object *items = json_object_object_get (result, "items");
assert (items != NULL);
@@ -245,7 +246,37 @@ PianoReturn_t PianoResponse (PianoHandle_t *ph, PianoRequest_t *req) {
continue;
}
- song->audioUrl = PianoJsonStrdup (s, "additionalAudioUrl");
+ /* 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]);
+
+ if (map != NULL) {
+ const char *encoding = json_object_get_string (
+ json_object_object_get (map, "encoding"));
+ assert (encoding != NULL);
+ for (size_t k = 0; k < sizeof (formatMap)/sizeof (*formatMap); k++) {
+ if (strcmp (formatMap[k], encoding) == 0) {
+ song->audioFormat = k;
+ break;
+ }
+ }
+ song->audioUrl = PianoJsonStrdup (map, "audioUrl");
+ } else {
+ /* requested quality is not available */
+ ret = PIANO_RET_QUALITY_UNAVAILABLE;
+ free (song);
+ PianoDestroyPlaylist (playlist);
+ goto cleanup;
+ }
+ }
+
song->artist = PianoJsonStrdup (s, "artistName");
song->album = PianoJsonStrdup (s, "albumName");
song->title = PianoJsonStrdup (s, "songName");
@@ -255,7 +286,6 @@ PianoReturn_t PianoResponse (PianoHandle_t *ph, PianoRequest_t *req) {
song->detailUrl = PianoJsonStrdup (s, "songDetailUrl");
song->fileGain = json_object_get_double (
json_object_object_get (s, "trackGain"));
- song->audioFormat = reqData->format;
switch (json_object_get_int (json_object_object_get (s,
"songRating"))) {
case 1:
@@ -665,6 +695,7 @@ PianoReturn_t PianoResponse (PianoHandle_t *ph, PianoRequest_t *req) {
}
}
+cleanup:
json_object_put (j);
return ret;
View
2  src/main.c
@@ -163,7 +163,7 @@ static void BarMainGetPlaylist (BarApp_t *app) {
WaitressReturn_t wRet;
PianoRequestDataGetPlaylist_t reqData;
reqData.station = app->curStation;
- reqData.format = app->settings.audioFormat;
+ reqData.quality = app->settings.audioQuality;
BarUiMsg (&app->settings, MSG_INFO, "Receiving new playlist... ");
if (!BarUiPianoCall (app, PIANO_REQUEST_GET_PLAYLIST,
View
4 src/player.c
@@ -428,7 +428,6 @@ void *BarPlayerThread (void *data) {
switch (player->audioFormat) {
#ifdef ENABLE_FAAD
- case PIANO_AF_AACPLUS_LO:
case PIANO_AF_AACPLUS:
player->aacHandle = NeAACDecOpen();
/* set aac conf */
@@ -443,7 +442,6 @@ void *BarPlayerThread (void *data) {
#ifdef ENABLE_MAD
case PIANO_AF_MP3:
- case PIANO_AF_MP3_HI:
mad_stream_init (&player->mp3Stream);
mad_frame_init (&player->mp3Frame);
mad_synth_init (&player->mp3Synth);
@@ -472,7 +470,6 @@ void *BarPlayerThread (void *data) {
switch (player->audioFormat) {
#ifdef ENABLE_FAAD
- case PIANO_AF_AACPLUS_LO:
case PIANO_AF_AACPLUS:
NeAACDecClose(player->aacHandle);
free (player->sampleSize);
@@ -481,7 +478,6 @@ void *BarPlayerThread (void *data) {
#ifdef ENABLE_MAD
case PIANO_AF_MP3:
- case PIANO_AF_MP3_HI:
mad_synth_finish (&player->mp3Synth);
mad_frame_finish (&player->mp3Frame);
mad_stream_finish (&player->mp3Stream);
View
24 src/settings.c
@@ -121,13 +121,7 @@ void BarSettingsRead (BarSettings_t *settings) {
sizeof (dispatchActions) / sizeof (*dispatchActions));
/* apply defaults */
- #ifdef ENABLE_FAAD
- settings->audioFormat = PIANO_AF_AACPLUS;
- #else
- #ifdef ENABLE_MAD
- settings->audioFormat = PIANO_AF_MP3;
- #endif
- #endif
+ settings->audioQuality = PIANO_AQ_HIGH;
settings->autoselect = true;
settings->history = 5;
settings->volume = 0;
@@ -226,15 +220,13 @@ void BarSettingsRead (BarSettings_t *settings) {
break;
}
}
- } else if (streq ("audio_format", key)) {
- if (streq (val, "aacplus")) {
- settings->audioFormat = PIANO_AF_AACPLUS;
- } else if (streq (val, "aacplus-lofi")) {
- settings->audioFormat = PIANO_AF_AACPLUS_LO;
- } else if (streq (val, "mp3")) {
- settings->audioFormat = PIANO_AF_MP3;
- } else if (streq (val, "mp3-hifi")) {
- settings->audioFormat = PIANO_AF_MP3_HI;
+ } else if (streq ("audio_quality", key)) {
+ if (streq (val, "low")) {
+ settings->audioQuality = PIANO_AQ_LOW;
+ } else if (streq (val, "medium")) {
+ settings->audioQuality = PIANO_AQ_MEDIUM;
+ } else if (streq (val, "high")) {
+ settings->audioQuality = PIANO_AQ_HIGH;
}
} else if (streq ("autostart_station", key)) {
settings->autostartStation = strdup (val);
View
2  src/settings.h
@@ -84,7 +84,7 @@ typedef struct {
unsigned int history;
int volume;
BarStationSorting_t sortOrder;
- PianoAudioFormat_t audioFormat;
+ PianoAudioQuality_t audioQuality;
char *username;
char *password;
char *controlProxy; /* non-american listeners need this */
Please sign in to comment.
Something went wrong with that request. Please try again.