diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/config.h | 2 | ||||
-rw-r--r-- | src/libpiano/response.c | 27 | ||||
-rw-r--r-- | src/player.c | 27 | ||||
-rw-r--r-- | src/ui.c | 84 | ||||
-rw-r--r-- | src/ui_act.c | 8 |
5 files changed, 102 insertions, 46 deletions
diff --git a/src/config.h b/src/config.h index f3d3d3e..850c4aa 100644 --- a/src/config.h +++ b/src/config.h @@ -3,7 +3,7 @@ /* package name */ #define PACKAGE "pianobar" -#define VERSION "2022.04.01-dev" +#define VERSION "2024.12.21-dev" /* glibc feature test macros, define _before_ including other files */ #define _POSIX_C_SOURCE 200809L diff --git a/src/libpiano/response.c b/src/libpiano/response.c index 1e79261..0be8872 100644 --- a/src/libpiano/response.c +++ b/src/libpiano/response.c @@ -206,7 +206,7 @@ PianoReturn_t PianoResponse (PianoHandle_t *ph, PianoRequest_t *req) { break; } - for (int i = 0; i < json_object_array_length (stations); i++) { + for (unsigned int i = 0; i < json_object_array_length (stations); i++) { PianoStation_t *tmpStation; json_object *s = json_object_array_get_idx (stations, i); @@ -229,7 +229,7 @@ PianoReturn_t PianoResponse (PianoHandle_t *ph, PianoRequest_t *req) { if (mix != NULL) { PianoStation_t *curStation = ph->stations; PianoListForeachP (curStation) { - for (int i = 0; i < json_object_array_length (mix); i++) { + for (unsigned int i = 0; i < json_object_array_length (mix); i++) { json_object *id = json_object_array_get_idx (mix, i); if (strcmp (json_object_get_string (id), curStation->id) == 0) { @@ -256,7 +256,7 @@ PianoReturn_t PianoResponse (PianoHandle_t *ph, PianoRequest_t *req) { } assert (items != NULL); - for (int i = 0; i < json_object_array_length (items); i++) { + for (unsigned int i = 0; i < json_object_array_length (items); i++) { json_object *s = json_object_array_get_idx (items, i); PianoSong_t *song; @@ -377,7 +377,7 @@ PianoReturn_t PianoResponse (PianoHandle_t *ph, PianoRequest_t *req) { /* get artists */ json_object *artists; if (json_object_object_get_ex (result, "artists", &artists)) { - for (int i = 0; i < json_object_array_length (artists); i++) { + for (unsigned int i = 0; i < json_object_array_length (artists); i++) { json_object *a = json_object_array_get_idx (artists, i); PianoArtist_t *artist; @@ -396,7 +396,7 @@ PianoReturn_t PianoResponse (PianoHandle_t *ph, PianoRequest_t *req) { /* get songs */ json_object *songs; if (json_object_object_get_ex (result, "songs", &songs)) { - for (int i = 0; i < json_object_array_length (songs); i++) { + for (unsigned int i = 0; i < json_object_array_length (songs); i++) { json_object *s = json_object_array_get_idx (songs, i); PianoSong_t *song; @@ -456,7 +456,7 @@ PianoReturn_t PianoResponse (PianoHandle_t *ph, PianoRequest_t *req) { /* get genre stations */ json_object *categories; if (json_object_object_get_ex (result, "categories", &categories)) { - for (int i = 0; i < json_object_array_length (categories); i++) { + for (unsigned int i = 0; i < json_object_array_length (categories); i++) { json_object *c = json_object_array_get_idx (categories, i); PianoGenreCategory_t *tmpGenreCategory; @@ -471,7 +471,7 @@ PianoReturn_t PianoResponse (PianoHandle_t *ph, PianoRequest_t *req) { /* get genre subnodes */ json_object *stations; if (json_object_object_get_ex (c, "stations", &stations)) { - for (int k = 0; + for (unsigned int k = 0; k < json_object_array_length (stations); k++) { json_object *s = json_object_array_get_idx (stations, k); @@ -520,12 +520,13 @@ PianoReturn_t PianoResponse (PianoHandle_t *ph, PianoRequest_t *req) { assert (reqData != NULL); json_object *explanations; - if (json_object_object_get_ex (result, "explanations", &explanations)) { + if (json_object_object_get_ex (result, "explanations", &explanations) && + json_object_array_length (explanations) > 0) { reqData->retExplain = malloc (strSize * sizeof (*reqData->retExplain)); strncpy (reqData->retExplain, "We're playing this track " "because it features ", strSize); - for (int i = 0; i < json_object_array_length (explanations); i++) { + for (unsigned int i = 0; i < json_object_array_length (explanations); i++) { json_object *e = json_object_array_get_idx (explanations, i); json_object *f; @@ -573,7 +574,7 @@ PianoReturn_t PianoResponse (PianoHandle_t *ph, PianoRequest_t *req) { /* songs */ json_object *songs; if (json_object_object_get_ex (music, "songs", &songs)) { - for (int i = 0; i < json_object_array_length (songs); i++) { + for (unsigned int i = 0; i < json_object_array_length (songs); i++) { json_object *s = json_object_array_get_idx (songs, i); PianoSong_t *seedSong; @@ -594,7 +595,7 @@ PianoReturn_t PianoResponse (PianoHandle_t *ph, PianoRequest_t *req) { /* artists */ json_object *artists; if (json_object_object_get_ex (music, "artists", &artists)) { - for (int i = 0; i < json_object_array_length (artists); i++) { + for (unsigned int i = 0; i < json_object_array_length (artists); i++) { json_object *a = json_object_array_get_idx (artists, i); PianoArtist_t *seedArtist; @@ -622,7 +623,7 @@ PianoReturn_t PianoResponse (PianoHandle_t *ph, PianoRequest_t *req) { continue; } assert (json_object_is_type (val, json_type_array)); - for (int i = 0; i < json_object_array_length (val); i++) { + for (unsigned int i = 0; i < json_object_array_length (val); i++) { json_object *s = json_object_array_get_idx (val, i); PianoSong_t *feedbackSong; @@ -665,7 +666,7 @@ PianoReturn_t PianoResponse (PianoHandle_t *ph, PianoRequest_t *req) { json_object *availableModes; if (json_object_object_get_ex (result, "availableModes", &availableModes)) { - for (int i = 0; i < json_object_array_length (availableModes); i++) { + for (unsigned int i = 0; i < json_object_array_length (availableModes); i++) { json_object *val = json_object_array_get_idx (availableModes, i); assert (json_object_is_type (val, json_type_object)); diff --git a/src/player.c b/src/player.c index 875f473..bded009 100644 --- a/src/player.c +++ b/src/player.c @@ -235,7 +235,7 @@ static bool openStream (player_t * const player) { softfail ("avcodec_parameters_to_context"); } - AVCodec * const decoder = avcodec_find_decoder (cp->codec_id); + const AVCodec * const decoder = avcodec_find_decoder (cp->codec_id); if (decoder == NULL) { softfail ("find_decoder"); } @@ -282,11 +282,13 @@ static bool openFilter (player_t * const player) { /* abuffer */ AVRational time_base = player->st->time_base; + char channelLayout[128]; + av_channel_layout_describe(&player->cctx->ch_layout, channelLayout, sizeof(channelLayout)); snprintf (strbuf, sizeof (strbuf), - "time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=0x%"PRIx64, + "time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=%s", time_base.num, time_base.den, cp->sample_rate, av_get_sample_fmt_name (player->cctx->sample_fmt), - cp->channel_layout); + channelLayout); if ((ret = avfilter_graph_create_filter (&player->fabuf, avfilter_get_by_name ("abuffer"), "source", strbuf, NULL, player->fgraph)) < 0) { @@ -340,7 +342,7 @@ static bool openDevice (player_t * const player) { memset (&aoFmt, 0, sizeof (aoFmt)); aoFmt.bits = av_get_bytes_per_sample (avformat) * 8; assert (aoFmt.bits > 0); - aoFmt.channels = cp->channels; + aoFmt.channels = cp->ch_layout.nb_channels; aoFmt.rate = getSampleRate (player); aoFmt.byte_format = AO_FMT_NATIVE; @@ -431,8 +433,12 @@ static int play (player_t * const player) { } else if (ret < 0) { /* error, abort */ /* mark the EOF, so that BarAoPlayThread can quit*/ - debugPrint (DEBUG_AUDIO, "av_read_frame failed with code %i, sending " - "NULL frame\n", ret); + char error[AV_ERROR_MAX_STRING_SIZE]; + if (av_strerror(ret, error, sizeof(error)) < 0) { + strncpy (error, "(unknown)", sizeof(error)-1); + } + debugPrint (DEBUG_AUDIO, "av_read_frame failed with code %i (%s), " + "sending NULL frame\n", ret, error); pthread_mutex_lock (&player->aoplayLock); const int rt = av_buffersrc_add_frame (player->fabuf, NULL); assert (rt == 0); @@ -508,7 +514,7 @@ static void finish (player_t * const player) { player->fgraph = NULL; } if (player->cctx != NULL) { - avcodec_close (player->cctx); + avcodec_free_context (&player->cctx); player->cctx = NULL; } if (player->fctx != NULL) { @@ -533,7 +539,9 @@ void *BarPlayerThread (void *data) { if (openFilter (player) && openDevice (player)) { changeMode (player, PLAYER_PLAYING); BarPlayerSetVolume (player); - retry = play (player) == AVERROR_INVALIDDATA && + const int ret = play (player); + retry = (ret == AVERROR_INVALIDDATA || + ret == -ECONNRESET) && !player->interrupted; } else { /* filter missing or audio device busy */ @@ -583,8 +591,7 @@ void *BarAoPlayThread (void *data) { } pthread_mutex_unlock (&player->aoplayLock); - const int numChannels = av_get_channel_layout_nb_channels ( - filteredFrame->channel_layout); + const int numChannels = filteredFrame->ch_layout.nb_channels; const int bps = av_get_bytes_per_sample (filteredFrame->format); ao_play (player->aoDev, (char *) filteredFrame->data[0], filteredFrame->nb_samples * numChannels * bps); @@ -161,8 +161,8 @@ static size_t httpFetchCb (char *ptr, size_t size, size_t nmemb, /* libcurl progress callback. aborts the current request if user pressed ^C */ -int progressCb (void * const data, double dltotal, double dlnow, - double ultotal, double ulnow) { +int progressCb (void * const data, curl_off_t dltotal, curl_off_t dlnow, + curl_off_t ultotal, curl_off_t ulnow) { const sig_atomic_t lint = *((sig_atomic_t *) data); if (lint) { return 1; @@ -224,8 +224,8 @@ static CURLcode BarPianoHttpRequest (CURL * const http, setAndCheck (CURLOPT_POSTFIELDS, req->postData); setAndCheck (CURLOPT_WRITEFUNCTION, httpFetchCb); setAndCheck (CURLOPT_WRITEDATA, &buffer); - setAndCheck (CURLOPT_PROGRESSFUNCTION, progressCb); - setAndCheck (CURLOPT_PROGRESSDATA, &lint); + setAndCheck (CURLOPT_XFERINFOFUNCTION, progressCb); + setAndCheck (CURLOPT_XFERINFODATA, &lint); setAndCheck (CURLOPT_NOPROGRESS, 0); setAndCheck (CURLOPT_POST, 1); setAndCheck (CURLOPT_TIMEOUT, settings->timeout); @@ -844,6 +844,49 @@ size_t BarUiListSongs (const BarApp_t * const app, return i; } +enum { + NO_DURATION = 0, +}; +#define NO_POSTFIX "" + +/* Print song information to the eventcmd stream + * @param Event command stream. + * @param Song information. + * @param Printed key name postfix, use NO_POSTFIX to print bare keys. + * @param Override song length from song parameter, use NO_DURATION if unavailable. + */ +static void BarUiEventcmdPrintSong (FILE * restrict stream, + const PianoSong_t * const song, const char * const postfix, + const unsigned int songDuration) { + assert (song != NULL); + assert (stream != NULL); + assert (postfix != NULL); + + fprintf (stream, + "artist%s=%s\n" + "title%s=%s\n" + "album%s=%s\n" + "coverArt%s=%s\n" + "rating%s=%i\n" + "detailUrl%s=%s\n" + "songDuration%s=%u\n", + postfix, + song->artist, + postfix, + song->title, + postfix, + song->album, + postfix, + song->coverArt, + postfix, + song->rating, + postfix, + song->detailUrl, + postfix, + songDuration == NO_DURATION ? song->length : songDuration + ); +} + /* Excute external event handler * @param settings containing the cmdline * @param event type @@ -900,36 +943,37 @@ void BarUiStartEventCmd (const BarSettings_t *settings, const char *type, pthread_mutex_unlock (&player->lock); fprintf (pipeWriteFd, - "artist=%s\n" - "title=%s\n" - "album=%s\n" - "coverArt=%s\n" "stationName=%s\n" "songStationName=%s\n" "pRet=%i\n" "pRetStr=%s\n" "wRet=%i\n" "wRetStr=%s\n" - "songDuration=%u\n" - "songPlayed=%u\n" - "rating=%i\n" - "detailUrl=%s\n", - curSong == NULL ? "" : curSong->artist, - curSong == NULL ? "" : curSong->title, - curSong == NULL ? "" : curSong->album, - curSong == NULL ? "" : curSong->coverArt, + "songPlayed=%u\n", curStation == NULL ? "" : curStation->name, songStation == NULL ? "" : songStation->name, pRet, PianoErrorToStr (pRet), wRet, curl_easy_strerror (wRet), - songDuration, - songPlayed, - curSong == NULL ? PIANO_RATE_NONE : curSong->rating, - curSong == NULL ? "" : curSong->detailUrl + songPlayed ); + if (curSong != NULL) { + BarUiEventcmdPrintSong (pipeWriteFd, curSong, NO_POSTFIX, songDuration); + } + + const PianoSong_t *nextSong = PianoListNextP (curSong); + if (nextSong != NULL) { + unsigned int i = 0; + PianoListForeachP (nextSong) { + char postfix[16]; + snprintf (postfix, sizeof(postfix)-1, "Next%i", i); + BarUiEventcmdPrintSong (pipeWriteFd, nextSong, postfix, NO_DURATION); + i++; + } + } + if (stations != NULL) { /* send station list */ PianoStation_t **sortedStations = NULL; diff --git a/src/ui_act.c b/src/ui_act.c index 30bd4e5..fa5c43b 100644 --- a/src/ui_act.c +++ b/src/ui_act.c @@ -271,8 +271,12 @@ BarUiActCallback(BarUiActExplain) { BarUiMsg (&app->settings, MSG_INFO, "Receiving explanation... "); if (BarUiActDefaultPianoCall (PIANO_REQUEST_EXPLAIN, &reqData)) { - BarUiMsg (&app->settings, MSG_INFO, "%s\n", reqData.retExplain); - free (reqData.retExplain); + if (reqData.retExplain == NULL) { + BarUiMsg (&app->settings, MSG_ERR, "No explanation provided.\n"); + } else { + BarUiMsg (&app->settings, MSG_INFO, "%s\n", reqData.retExplain); + free (reqData.retExplain); + } } BarUiActDefaultEventcmd ("songexplain"); } |