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... "); | 
