diff options
author | Michał Cichoń <michcic@gmail.com> | 2018-10-30 13:12:47 +0100 |
---|---|---|
committer | Michał Cichoń <michcic@gmail.com> | 2018-10-30 13:12:47 +0100 |
commit | cb6789b17f81d29c6884c27715c705083e09a5db (patch) | |
tree | d6a47c38ff7dcb937992b15dc3c2d051bb877ac8 /src | |
parent | cd5c65097ecf03480f477e47e0bb706dbf705a21 (diff) | |
parent | 82a13ad77bfcf2c6dc37fe0d1d55f93372db6509 (diff) | |
download | pianobar-windows-2018.10.30.tar.gz pianobar-windows-2018.10.30.tar.bz2 pianobar-windows-2018.10.30.zip |
Merge branch 'release/2018.10.30'HEAD2018.10.30master
Diffstat (limited to 'src')
-rw-r--r-- | src/config.h | 2 | ||||
-rw-r--r-- | src/http/http.c | 16 | ||||
-rw-r--r-- | src/http/http.h | 2 | ||||
-rw-r--r-- | src/libpiano/piano.c | 6 | ||||
-rw-r--r-- | src/libpiano/piano.h | 3 | ||||
-rw-r--r-- | src/libpiano/request.c | 6 | ||||
-rw-r--r-- | src/libpiano/response.c | 12 | ||||
-rw-r--r-- | src/main.c | 11 | ||||
-rw-r--r-- | src/main.h | 2 | ||||
-rw-r--r-- | src/settings.c | 15 | ||||
-rw-r--r-- | src/settings.h | 5 | ||||
-rw-r--r-- | src/ui.c | 63 | ||||
-rw-r--r-- | src/ui.h | 7 | ||||
-rw-r--r-- | src/ui_act.c | 14 |
14 files changed, 116 insertions, 48 deletions
diff --git a/src/config.h b/src/config.h index 42a0b11..a8af710 100644 --- a/src/config.h +++ b/src/config.h @@ -3,7 +3,7 @@ /* package name */ #define PACKAGE "pianobar" -#define VERSION "2017.05.18" +#define VERSION "2018.10.30" #define TITLE "Pianobar" diff --git a/src/http/http.c b/src/http/http.c index 4576d04..9457fab 100644 --- a/src/http/http.c +++ b/src/http/http.c @@ -41,7 +41,7 @@ struct _http_t { static char* HttpToString(const wchar_t* wideString, int size); static wchar_t* HttpToWideString(const char* string, int size); -static bool HttpCreateConnection (http_t http); +static bool HttpCreateConnection (http_t http, unsigned int timeOut); static void HttpCloseConnection (http_t http); static void HttpSetLastError (http_t http, const char* message); static void HttpSetLastErrorW (http_t http, const wchar_t* message); @@ -75,7 +75,7 @@ static wchar_t* HttpToWideString(const char* string, int size) { } -static bool HttpCreateConnection (http_t http) { +static bool HttpCreateConnection (http_t http, unsigned int timeOut) { INTERNET_PORT defaultPort = INTERNET_DEFAULT_PORT; HttpCloseConnection (http); @@ -89,10 +89,10 @@ static bool HttpCreateConnection (http_t http) { WINHTTP_SAFE(http->session != NULL); WinHttpSetTimeouts(http->session, - 60 * 1000, // DNS time-out - 60 * 1000, // connect time-out - 30 * 1000, // send time-out - 30 * 1000); // receive time-out + timeOut * 1000, // DNS time-out + timeOut * 1000, // connect time-out + timeOut * 1000, // send time-out + timeOut * 1000); // receive time-out http->connection = WinHttpConnect( http->session, @@ -187,7 +187,7 @@ static char* HttpFormatWinHttpError (DWORD errorCode) { return HttpFormatWinApiError(errorCode, NULL); } -bool HttpInit(http_t* http, const char* endpoint, const char* securePort) { +bool HttpInit(http_t* http, const char* endpoint, const char* securePort, unsigned int timeOut) { http_t out = malloc(sizeof(struct _http_t)); if (!out) return false; @@ -196,7 +196,7 @@ bool HttpInit(http_t* http, const char* endpoint, const char* securePort) { out->endpoint = HttpToWideString(endpoint, -1); out->securePort = HttpToWideString(securePort, -1); - if (!HttpCreateConnection (out)) { + if (!HttpCreateConnection (out, timeOut)) { HttpDestroy (out); return false; } diff --git a/src/http/http.h b/src/http/http.h index 5ea617f..415b0d0 100644 --- a/src/http/http.h +++ b/src/http/http.h @@ -32,7 +32,7 @@ THE SOFTWARE. typedef struct _http_t *http_t; -bool HttpInit (http_t*, const char*, const char*); +bool HttpInit (http_t*, const char*, const char*, unsigned int); void HttpDestroy (http_t); bool HttpSetAutoProxy (http_t, const char*); diff --git a/src/libpiano/piano.c b/src/libpiano/piano.c index c496ea1..7f1eff9 100644 --- a/src/libpiano/piano.c +++ b/src/libpiano/piano.c @@ -214,7 +214,11 @@ void PianoDestroyRequest (PianoRequest_t *req) { */ PianoStation_t *PianoFindStationById (PianoStation_t * const stations, const char * const searchStation) { - assert (searchStation != NULL); + assert (stations != NULL); + + if (searchStation == NULL) { + return NULL; + } PianoStation_t *currStation = stations; PianoListForeachP (currStation) { diff --git a/src/libpiano/piano.h b/src/libpiano/piano.h index 2dbf607..b595249 100644 --- a/src/libpiano/piano.h +++ b/src/libpiano/piano.h @@ -64,7 +64,8 @@ typedef struct PianoStation { typedef enum { PIANO_RATE_NONE = 0, PIANO_RATE_LOVE = 1, - PIANO_RATE_BAN = 2 + PIANO_RATE_BAN = 2, + PIANO_RATE_TIRED = 3, } PianoSongRating_t; /* UNKNOWN should be 0, because memset sets audio format to 0 */ diff --git a/src/libpiano/request.c b/src/libpiano/request.c index 5d499af..0df7005 100644 --- a/src/libpiano/request.c +++ b/src/libpiano/request.c @@ -156,6 +156,7 @@ PianoReturn_t PianoRequest (PianoHandle_t *ph, PianoRequest_t *req, case PIANO_REQUEST_GET_STATIONS: { /* get stations, user must be authenticated */ assert (ph->user.listenerId != NULL); + method = "user.getStationList"; break; } @@ -186,7 +187,8 @@ PianoReturn_t PianoRequest (PianoHandle_t *ph, PianoRequest_t *req, assert (reqData != NULL); assert (reqData->trackToken != NULL); assert (reqData->stationId != NULL); - assert (reqData->rating != PIANO_RATE_NONE); + assert (reqData->rating != PIANO_RATE_NONE && + reqData->rating != PIANO_RATE_TIRED); json_object_object_add (j, "stationToken", json_object_new_string (reqData->stationId)); @@ -397,6 +399,8 @@ PianoReturn_t PianoRequest (PianoHandle_t *ph, PianoRequest_t *req, json_object_new_string (reqData->station->id)); json_object_object_add (j, "includeExtendedAttributes", json_object_new_boolean (true)); + json_object_object_add (j, "includeExtraParams", + json_object_new_boolean (true)); method = "station.getStation"; break; diff --git a/src/libpiano/response.c b/src/libpiano/response.c index e37824e..fcc28b1 100644 --- a/src/libpiano/response.c +++ b/src/libpiano/response.c @@ -436,8 +436,13 @@ PianoReturn_t PianoResponse (PianoHandle_t *ph, PianoRequest_t *req) { break; } + case PIANO_REQUEST_ADD_TIRED_SONG: { + PianoSong_t * const song = req->data; + song->rating = PIANO_RATE_TIRED; + break; + } + case PIANO_REQUEST_ADD_SEED: - case PIANO_REQUEST_ADD_TIRED_SONG: case PIANO_REQUEST_SET_QUICKMIX: case PIANO_REQUEST_BOOKMARK_SONG: case PIANO_REQUEST_BOOKMARK_ARTIST: @@ -634,6 +639,11 @@ PianoReturn_t PianoResponse (PianoHandle_t *ph, PianoRequest_t *req) { feedbackSong->rating = getBoolDefault (s, "isPositive", false) ? PIANO_RATE_LOVE : PIANO_RATE_BAN; + json_object *v; + feedbackSong->length = + json_object_object_get_ex (s, "trackLength", &v) ? + json_object_get_int (v) : 0; + info->feedback = PianoListAppendP (info->feedback, feedbackSong); } @@ -248,9 +248,9 @@ static void BarMainStartPlayback(BarApp_t *app) PIANO_RET_OK); if (!BarPlayer2Play(app->player)) - ++app->playerErrors; + ++app->retries; else - app->playerErrors = 0; + app->retries = 0; } } @@ -265,11 +265,11 @@ static void BarMainPlayerCleanup(BarApp_t *app) BarConsoleSetTitle(TITLE); - if (app->playerErrors >= app->settings.maxPlayerErrors) + if (app->retries >= app->settings.maxRetry) { /* don't continue playback if thread reports too many error */ app->nextStation = NULL; - app->playerErrors = 0; + app->retries = 0; } } @@ -411,7 +411,8 @@ int main(int argc, char **argv) app.settings.keys[BAR_KS_HELP]); } - HttpInit(&app.http2, app.settings.rpcHost, app.settings.rpcTlsPort); + HttpInit(&app.http2, app.settings.rpcHost, app.settings.rpcTlsPort, + app.settings.timeout); if (app.settings.controlProxy) HttpSetProxy(app.http2, app.settings.controlProxy); @@ -46,6 +46,6 @@ typedef struct { PianoStation_t *curStation, *nextStation; char doQuit; BarReadline_t rl; - unsigned int playerErrors; + unsigned int retries; } BarApp_t; diff --git a/src/settings.c b/src/settings.c index 4f0ef8c..affb7f2 100644 --- a/src/settings.c +++ b/src/settings.c @@ -129,6 +129,7 @@ void BarSettingsDestroy (BarSettings_t *settings) { free (settings->eventCmd); free (settings->loveIcon); free (settings->banIcon); + free (settings->tiredIcon); free (settings->atIcon); free (settings->npSongFormat); free (settings->npStationFormat); @@ -172,11 +173,14 @@ void BarSettingsRead (BarSettings_t *settings) { settings->autoselect = true; settings->history = 5; settings->volume = 0; + settings->timeout = 30; /* seconds */ settings->gainMul = 1.0; - settings->maxPlayerErrors = 5; + /* should be > 4, otherwise expired audio urls (403) can stop playback */ + settings->maxRetry = 5; settings->sortOrder = BAR_SORT_NAME_AZ; settings->loveIcon = strdup (" <3"); settings->banIcon = strdup (" </3"); + settings->tiredIcon = strdup (" zZ"); settings->atIcon = strdup (" @ "); settings->npSongFormat = strdup ("\"%t\" by \"%a\" on \"%l\"%r%@%s"); settings->npStationFormat = strdup ("Station \"%n\" (%i)"); @@ -351,8 +355,10 @@ void BarSettingsRead (BarSettings_t *settings) { settings->eventCmd = BarSettingsExpandTilde (val, userhome); } else if (streq ("history", key)) { settings->history = atoi (val); - } else if (streq ("max_player_errors", key)) { - settings->maxPlayerErrors = atoi (val); + } else if (streq ("max_retry", key)) { + settings->maxRetry = atoi (val); + } else if (streq ("timeout", key)) { + settings->timeout = atoi (val); } else if (streq ("sort", key)) { size_t i; static const char *mapping[] = {"name_az", @@ -374,6 +380,9 @@ void BarSettingsRead (BarSettings_t *settings) { } else if (streq ("ban_icon", key)) { free (settings->banIcon); settings->banIcon = strdup (val); + } else if (streq ("tired_icon", key)) { + free (settings->tiredIcon); + settings->tiredIcon = strdup (val); } else if (streq ("at_icon", key)) { free (settings->atIcon); settings->atIcon = strdup (val); diff --git a/src/settings.h b/src/settings.h index 0edb544..719c39b 100644 --- a/src/settings.h +++ b/src/settings.h @@ -86,7 +86,7 @@ typedef struct { typedef struct { bool autoselect; - unsigned int history, maxPlayerErrors; + unsigned int history, maxRetry, timeout; int volume; float gainMul; BarStationSorting_t sortOrder; @@ -98,8 +98,7 @@ typedef struct { char *bindTo; char *autostartStation; char *eventCmd; - char *loveIcon; - char *banIcon; + char *loveIcon, *banIcon, *tiredIcon; char *atIcon; char *npSongFormat; char *npStationFormat; @@ -388,20 +388,21 @@ PianoStation_t *BarUiSelectStation (BarApp_t *app, PianoStation_t *stations, } /* let user pick one song - * @param pianobar settings + * @param app * @param song list * @param input fds * @return pointer to selected item in song list or NULL */ -PianoSong_t *BarUiSelectSong (const BarSettings_t *settings, +PianoSong_t *BarUiSelectSong (const BarApp_t * const app, PianoSong_t *startSong, BarReadline_t rl) { + const BarSettings_t * const settings = &app->settings; PianoSong_t *tmpSong = NULL; char buf[100]; memset (buf, 0, sizeof (buf)); do { - BarUiListSongs (settings, startSong, buf); + BarUiListSongs (app, startSong, buf); BarUiMsg (settings, MSG_QUESTION, "Select song: "); if (BarReadlineStr (buf, sizeof (buf), rl, BAR_RL_DEFAULT) == 0) { @@ -498,7 +499,7 @@ char *BarUiSelectMusicId (BarApp_t *app, PianoStation_t *station, musicId = strdup (tmpArtist->musicId); } } else if (*selectBuf == 't') { - tmpSong = BarUiSelectSong (&app->settings, searchResult.songs, + tmpSong = BarUiSelectSong (app, searchResult.songs, app->rl); if (tmpSong != NULL) { musicId = strdup (tmpSong->musicId); @@ -506,7 +507,7 @@ char *BarUiSelectMusicId (BarApp_t *app, PianoStation_t *station, } } else if (searchResult.songs != NULL) { /* songs found */ - tmpSong = BarUiSelectSong (&app->settings, searchResult.songs, + tmpSong = BarUiSelectSong (app, searchResult.songs, app->rl); if (tmpSong != NULL) { musicId = strdup (tmpSong->musicId); @@ -614,6 +615,23 @@ void BarUiPrintStation (const BarSettings_t *settings, BarUiMsg (settings, MSG_PLAYING, "%s", outstr); } +static const char *ratingToIcon (const BarSettings_t * const settings, + const PianoSong_t * const song) { + switch (song->rating) { + case PIANO_RATE_LOVE: + return settings->loveIcon; + + case PIANO_RATE_BAN: + return settings->banIcon; + + case PIANO_RATE_TIRED: + return settings->tiredIcon; + + default: + return ""; + } +} + /* Print song infos (artist, title, album, loved) * @param pianobar settings * @param the song @@ -623,7 +641,7 @@ void BarUiPrintSong (const BarSettings_t *settings, const PianoSong_t *song, const PianoStation_t *station) { char outstr[512]; const char *vals[] = {song->title, song->artist, song->album, - (song->rating == PIANO_RATE_LOVE) ? settings->loveIcon : "", + ratingToIcon (settings, song), station != NULL ? settings->atIcon : "", station != NULL ? station->name : "", song->detailUrl}; @@ -644,23 +662,44 @@ void BarUiPrintSong (const BarSettings_t *settings, * @param artist/song filter string * @return # of songs */ -size_t BarUiListSongs (const BarSettings_t *settings, +size_t BarUiListSongs (const BarApp_t * const app, const PianoSong_t *song, const char *filter) { + const BarSettings_t * const settings = &app->settings; size_t i = 0; - char digits[8]; PianoListForeachP (song) { if (filter == NULL || (filter != NULL && (BarStrCaseStr (song->artist, filter) != NULL || BarStrCaseStr (song->title, filter) != NULL))) { - char outstr[512]; + const char * const deleted = "(deleted)", * const empty = ""; + const char *stationName = empty; + + const PianoStation_t * const station = + PianoFindStationById (app->ph.stations, song->stationId); + if (station != NULL && station != app->curStation) { + stationName = station->name; + } else if (station == NULL && song->stationId != NULL) { + stationName = deleted; + } + + char outstr[512], digits[8], duration[8] = "??:??"; const char *vals[] = {digits, song->artist, song->title, - (song->rating == PIANO_RATE_LOVE) ? settings->loveIcon : - ((song->rating == PIANO_RATE_BAN) ? settings->banIcon : "")}; + ratingToIcon (settings, song), + duration, + stationName != empty ? settings->atIcon : "", + stationName, + }; + /* pre-format a few strings */ snprintf (digits, sizeof (digits) / sizeof (*digits), "%2zu", i); + const unsigned int length = song->length; + if (length > 0) { + snprintf (duration, sizeof (duration), "%02u:%02u", + length / 60, length % 60); + } + BarUiCustomFormat (outstr, sizeof (outstr), settings->listSongFormat, - "iatr", vals); + "iatrd@s", vals); BarUiAppendNewline (outstr, sizeof (outstr)); BarUiMsg (settings, MSG_LIST, "%s", outstr); } @@ -38,14 +38,15 @@ typedef void (*BarUiSelectStationCallback_t) (BarApp_t *app, char *buf); void BarUiMsg (const BarSettings_t *, const BarUiMsg_t, const char *, ...) __attribute__((format(printf, 3, 4))); PianoStation_t *BarUiSelectStation (BarApp_t *, PianoStation_t *, const char *, BarUiSelectStationCallback_t, bool); -PianoSong_t *BarUiSelectSong (const BarSettings_t *, PianoSong_t *, - BarReadline_t); +PianoSong_t *BarUiSelectSong (const BarApp_t * const app, + PianoSong_t *startSong, BarReadline_t rl); PianoArtist_t *BarUiSelectArtist (BarApp_t *, PianoArtist_t *); char *BarUiSelectMusicId (BarApp_t *, PianoStation_t *, const char *); void BarUiPrintStation (const BarSettings_t *, PianoStation_t *); void BarUiPrintSong (const BarSettings_t *, const PianoSong_t *, const PianoStation_t *); -size_t BarUiListSongs (const BarSettings_t *, const PianoSong_t *, const char *); +size_t BarUiListSongs (const BarApp_t * const app, + const PianoSong_t *song, const char *filter); void BarUiStartEventCmd (const BarSettings_t *, const char *, const PianoStation_t *, const PianoSong_t *, const player2_t * const, PianoStation_t *, PianoReturn_t); diff --git a/src/ui_act.c b/src/ui_act.c index a036f19..b1ed8a4 100644 --- a/src/ui_act.c +++ b/src/ui_act.c @@ -482,7 +482,7 @@ BarUiActCallback(BarUiActTempBanSong) { BarUiActCallback(BarUiActPrintUpcoming) { PianoSong_t * const nextSong = PianoListNextP (selSong); if (nextSong != NULL) { - BarUiListSongs (&app->settings, nextSong, NULL); + BarUiListSongs (app, nextSong, NULL); } else { BarUiMsg (&app->settings, MSG_INFO, "No songs in queue.\n"); } @@ -537,15 +537,15 @@ BarUiActCallback(BarUiActSelectQuickMix) { if (selStation->isQuickMix) { PianoStation_t *toggleStation; while ((toggleStation = BarUiSelectStation (app, app->ph.stations, - "Toggle quickmix for station: ", + "Toggle QuickMix for station: ", BarUiActQuickmixCallback, false)) != NULL) { toggleStation->useQuickMix = !toggleStation->useQuickMix; } - BarUiMsg (&app->settings, MSG_INFO, "Setting quickmix stations... "); + BarUiMsg (&app->settings, MSG_INFO, "Setting QuickMix stations... "); BarUiActDefaultPianoCall (PIANO_REQUEST_SET_QUICKMIX, NULL); BarUiActDefaultEventcmd ("stationquickmixtoggle"); } else { - BarUiMsg (&app->settings, MSG_ERR, "Not a QuickMix station.\n"); + BarUiMsg (&app->settings, MSG_ERR, "Please select a QuickMix station first.\n"); } } @@ -563,7 +563,7 @@ BarUiActCallback(BarUiActHistory) { PianoSong_t *histSong; if (app->songHistory != NULL) { - histSong = BarUiSelectSong (&app->settings, app->songHistory, + histSong = BarUiSelectSong (app, app->songHistory, app->rl); if (histSong != NULL) { BarKeyShortcutId_t action; @@ -815,7 +815,7 @@ BarUiActCallback(BarUiActManageStation) { BarUiActDefaultEventcmd ("stationdeleteartistseed"); } } else if (selectBuf[0] == 's') { - PianoSong_t *song = BarUiSelectSong (&app->settings, + PianoSong_t *song = BarUiSelectSong (app, reqData.info.songSeeds, app->rl); if (song != NULL) { PianoRequestDataDeleteSeed_t subReqData; @@ -842,7 +842,7 @@ BarUiActCallback(BarUiActManageStation) { BarUiActDefaultEventcmd ("stationdeletestationseed"); } } else if (selectBuf[0] == 'f') { - PianoSong_t *song = BarUiSelectSong (&app->settings, + PianoSong_t *song = BarUiSelectSong (app, reqData.info.feedback, app->rl); if (song != NULL) { BarUiMsg (&app->settings, MSG_INFO, "Deleting feedback... "); |