diff options
| -rw-r--r-- | libpiano/src/main.c | 12 | ||||
| -rw-r--r-- | libpiano/src/piano.h | 5 | ||||
| -rw-r--r-- | libpiano/src/xml.c | 10 | ||||
| -rw-r--r-- | libpiano/src/xml.h | 3 | ||||
| -rw-r--r-- | src/main.c | 77 | ||||
| -rw-r--r-- | src/pianobar.1 | 8 | ||||
| -rw-r--r-- | src/settings.c | 6 | ||||
| -rw-r--r-- | src/settings.h | 4 | ||||
| -rw-r--r-- | src/ui_act.c | 61 | ||||
| -rw-r--r-- | src/ui_act.h | 1 | 
10 files changed, 146 insertions, 41 deletions
| diff --git a/libpiano/src/main.c b/libpiano/src/main.c index 16d30d7..2bf8426 100644 --- a/libpiano/src/main.c +++ b/libpiano/src/main.c @@ -133,10 +133,10 @@ void PianoDestroyStations (PianoStation_t *stations) {   *	@param piano handle   *	@return nothing   */ -void PianoDestroyPlaylist (PianoHandle_t *ph) { +void PianoDestroyPlaylist (PianoSong_t *playlist) {  	PianoSong_t *curSong, *lastSong; -	curSong = ph->playlist; +	curSong = playlist;  	while (curSong != NULL) {  		PianoFree (curSong->audioUrl, 0);  		PianoFree (curSong->artist, 0); @@ -152,7 +152,6 @@ void PianoDestroyPlaylist (PianoHandle_t *ph) {  		curSong = curSong->next;  		PianoFree (lastSong, sizeof (*lastSong));  	} -	ph->playlist = NULL;  }  /*	frees the whole piano handle structure @@ -176,7 +175,6 @@ void PianoDestroy (PianoHandle_t *ph) {  		curGenreCat = curGenreCat->next;  		PianoFree (lastGenreCat, sizeof (*lastGenreCat));  	} -	PianoDestroyPlaylist (ph);  	memset (ph, 0, sizeof (*ph));  } @@ -255,9 +253,11 @@ PianoReturn_t PianoGetStations (PianoHandle_t *ph) {  /*	get next songs for station (usually four tracks)   *	@param piano handle   *	@param station id + *	@param audio format + *	@param return value: playlist   */  PianoReturn_t PianoGetPlaylist (PianoHandle_t *ph, const char *stationId, -		PianoAudioFormat_t format) { +		PianoAudioFormat_t format, PianoSong_t **retPlaylist) {  	char xmlSendBuf[PIANO_SEND_BUFFER_SIZE], *retStr;  	PianoReturn_t ret; @@ -283,7 +283,7 @@ PianoReturn_t PianoGetPlaylist (PianoHandle_t *ph, const char *stationId,  	if ((ret = PianoHttpPost (&ph->waith, xmlSendBuf, &retStr)) ==  			PIANO_RET_OK) { -		ret = PianoXmlParsePlaylist (ph, retStr); +		ret = PianoXmlParsePlaylist (ph, retStr, retPlaylist);  		PianoFree (retStr, 0);  	} diff --git a/libpiano/src/piano.h b/libpiano/src/piano.h index 3bb9108..cd3e8ca 100644 --- a/libpiano/src/piano.h +++ b/libpiano/src/piano.h @@ -90,7 +90,6 @@ typedef struct PianoHandle {  	PianoUserInfo_t user;  	/* linked lists */  	PianoStation_t *stations; -	PianoSong_t *playlist;  	PianoGenreCategory_t *genreStations;  } PianoHandle_t; @@ -109,13 +108,13 @@ typedef enum {PIANO_RET_OK, PIANO_RET_ERR, PIANO_RET_XML_INVALID,  void PianoInit (PianoHandle_t *);  void PianoDestroy (PianoHandle_t *); -void PianoDestroyPlaylist (PianoHandle_t *); +void PianoDestroyPlaylist (PianoSong_t *);  void PianoDestroySearchResult (PianoSearchResult_t *);  PianoReturn_t PianoConnect (PianoHandle_t *, const char *, const char *);  PianoReturn_t PianoGetStations (PianoHandle_t *);  PianoReturn_t PianoGetPlaylist (PianoHandle_t *, const char *, -		PianoAudioFormat_t); +		PianoAudioFormat_t, PianoSong_t **);  PianoReturn_t PianoRateTrack (PianoHandle_t *, PianoSong_t *,  		PianoSongRating_t); diff --git a/libpiano/src/xml.c b/libpiano/src/xml.c index 8e8fb2a..8d34a32 100644 --- a/libpiano/src/xml.c +++ b/libpiano/src/xml.c @@ -484,8 +484,10 @@ PianoReturn_t PianoXmlParseAddSeed (PianoHandle_t *ph, char *xml,  /*	parses playlist; used when searching too   *	@param piano handle   *	@param xml document + *	@param return: playlist   */ -PianoReturn_t PianoXmlParsePlaylist (PianoHandle_t *ph, char *xml) { +PianoReturn_t PianoXmlParsePlaylist (PianoHandle_t *ph, char *xml, +		PianoSong_t **retPlaylist) {  	ezxml_t xmlDoc, dataNode;  	PianoReturn_t ret; @@ -508,10 +510,10 @@ PianoReturn_t PianoXmlParsePlaylist (PianoHandle_t *ph, char *xml) {  		PianoXmlStructParser (ezxml_child (dataNode, "struct"),  				PianoXmlParsePlaylistCb, tmpSong);  		/* begin linked list or append */ -		if (ph->playlist == NULL) { -			ph->playlist = tmpSong; +		if (*retPlaylist == NULL) { +			*retPlaylist = tmpSong;  		} else { -			PianoSong_t *curSong = ph->playlist; +			PianoSong_t *curSong = *retPlaylist;  			while (curSong->next != NULL) {  				curSong = curSong->next;  			} diff --git a/libpiano/src/xml.h b/libpiano/src/xml.h index 5c0e5c2..7d1f1b2 100644 --- a/libpiano/src/xml.h +++ b/libpiano/src/xml.h @@ -28,7 +28,8 @@ THE SOFTWARE.  PianoReturn_t PianoXmlParseUserinfo (PianoHandle_t *ph, const char *xml);  PianoReturn_t PianoXmlParseStations (PianoHandle_t *ph, const char *xml); -PianoReturn_t PianoXmlParsePlaylist (PianoHandle_t *ph, const char *xml); +PianoReturn_t PianoXmlParsePlaylist (PianoHandle_t *ph, const char *xml, +		PianoSong_t **);  PianoReturn_t PianoXmlParseSearch (const char *searchXml,  		PianoSearchResult_t *searchResult);  PianoReturn_t PianoXmlParseSimple (const char *xml); @@ -62,8 +62,9 @@ int main (int argc, char **argv) {  	BarSettings_t settings;  	pthread_t playerThread;  	WardrobeHandle_t wh; -	/* currently playing */ -	PianoSong_t *curSong = NULL; +	/* playlist; first item is current song */ +	PianoSong_t *playlist = NULL; +	PianoSong_t *songHistory = NULL;  	PianoStation_t *curStation = NULL;  	WardrobeSong_t scrobbleSong;  	char doQuit = 0; @@ -204,53 +205,79 @@ int main (int argc, char **argv) {  				player.mode == PLAYER_FREED) {  			if (curStation != NULL) {  				/* what's next? */ -				if (curSong != NULL) { -					curSong = curSong->next; +				if (playlist != NULL) { +					if (settings.history != 0) { +						/* prepend song to history list */ +						PianoSong_t *tmpSong = songHistory; +						songHistory = playlist; +						/* select next song */ +						playlist = playlist->next; +						songHistory->next = tmpSong; + +						/* limit history's length */ +						/* start with 1, so we're stopping at n-1 and have the +						 * chance to set ->next = NULL */ +						unsigned int i = 1; +						tmpSong = songHistory; +						while (i < settings.history && tmpSong != NULL) { +							tmpSong = tmpSong->next; +							++i; +						} +						/* if too many songs in history... */ +						if (tmpSong != NULL) { +							PianoSong_t *delSong = tmpSong->next; +							tmpSong->next = NULL; +							if (delSong != NULL) { +								PianoDestroyPlaylist (delSong); +							} +						} +					} else { +						/* don't keep history */ +						playlist = playlist->next; +					}  				} -				if (curSong == NULL) { +				if (playlist == NULL) {  					PianoReturn_t pRet = PIANO_RET_ERR;  					BarUiMsg (MSG_INFO, "Receiving new playlist... "); -					PianoDestroyPlaylist (&ph);  					if ((pRet = BarUiPrintPianoStatus (PianoGetPlaylist (&ph, -							curStation->id, settings.audioFormat))) != -							PIANO_RET_OK) { +							curStation->id, settings.audioFormat, +							&playlist))) != PIANO_RET_OK) {  						curStation = NULL;  					} else { -						curSong = ph.playlist; -						if (curSong == NULL) { +						if (playlist == NULL) {  							BarUiMsg (MSG_INFO, "No tracks left.\n");  							curStation = NULL;  						}  					}  					BarUiStartEventCmd (&settings, "stationfetchplaylist", -							curStation, curSong, pRet); +							curStation, playlist, pRet);  				}  				/* song ready to play */ -				if (curSong != NULL) { -					BarUiPrintSong (curSong, curStation->isQuickMix ? +				if (playlist != NULL) { +					BarUiPrintSong (playlist, curStation->isQuickMix ?  							PianoFindStationById (ph.stations, -							curSong->stationId) : NULL); -					/* setup artist and song name for scrobbling (curSong +							playlist->stationId) : NULL); +					/* setup artist and song name for scrobbling (playlist  					 * may be NULL later) */  					WardrobeSongInit (&scrobbleSong); -					scrobbleSong.artist = strdup (curSong->artist); -					scrobbleSong.title = strdup (curSong->title); -					scrobbleSong.album = strdup (curSong->album); +					scrobbleSong.artist = strdup (playlist->artist); +					scrobbleSong.title = strdup (playlist->title); +					scrobbleSong.album = strdup (playlist->album);  					scrobbleSong.started = time (NULL);  					/* setup player */  					memset (&player, 0, sizeof (player));  					WaitressInit (&player.waith); -					WaitressSetUrl (&player.waith, curSong->audioUrl); +					WaitressSetUrl (&player.waith, playlist->audioUrl); -					player.gain = curSong->fileGain; -					player.audioFormat = curSong->audioFormat; +					player.gain = playlist->fileGain; +					player.audioFormat = playlist->audioFormat;  					/* throw event */  					BarUiStartEventCmd (&settings, "songstart", curStation, -							curSong, PIANO_RET_OK); +							playlist, PIANO_RET_OK);  					/* start player */  					pthread_create (&playerThread, NULL, BarPlayerThread, @@ -274,8 +301,8 @@ int main (int argc, char **argv) {  			while (curShortcut != NULL) {  				if (curShortcut->key == buf) { -					curShortcut->cmd (&ph, &player, &settings, &curSong, -							&curStation, &doQuit, curFd); +					curShortcut->cmd (&ph, &player, &settings, &playlist, +							&curStation, &songHistory, &doQuit, curFd);  					break;  				}  				curShortcut = curShortcut->next; @@ -310,6 +337,8 @@ int main (int argc, char **argv) {  		fclose (ctlFd);  	}  	PianoDestroy (&ph); +	PianoDestroyPlaylist (songHistory); +	PianoDestroyPlaylist (playlist);  	WardrobeDestroy (&wh);  	ao_shutdown();  	BarSettingsDestroy (&settings); diff --git a/src/pianobar.1 b/src/pianobar.1 index 87eabda..b8f5446 100644 --- a/src/pianobar.1 +++ b/src/pianobar.1 @@ -63,6 +63,10 @@ Explain why this song is played.  Add genre station provided by pandora.  .TP +.B act_history = h +Show history. + +.TP  .B act_songinfo = i  Print information about currently played song/station. @@ -133,6 +137,10 @@ File that is executed when event occurs. The file is called with the event type  as it's first argument. More information is supplied through stdin.  .TP +.B history = 5 +Keep a history of the last n songs (5, by default). You can rate these songs. + +.TP  .B lastfm_user = your_username  If you want to send your played songs to last.fm set this to your last.fm  username. diff --git a/src/settings.c b/src/settings.c index a7d6f61..1726a78 100644 --- a/src/settings.c +++ b/src/settings.c @@ -149,6 +149,8 @@ void BarSettingsRead (BarSettings_t *settings) {  				"act_songexplain", NULL},  			{'g', BarUiActStationFromGenre, "add genre station",  				"act_stationaddbygenre", NULL}, +			{'h', BarUiActHistory, "song history", +				"act_history", NULL},  			{'i', BarUiActSongInfo,  				"print information about current song/station",  				"act_songinfo", NULL}, @@ -181,6 +183,7 @@ void BarSettingsRead (BarSettings_t *settings) {  		settings->audioFormat = PIANO_AF_MP3;  		#endif  	#endif +	settings->history = 5;  	BarGetXdgConfigDir (PACKAGE "/config", configfile, sizeof (configfile));  	if ((configfd = fopen (configfile, "r")) == NULL) { @@ -192,6 +195,7 @@ void BarSettingsRead (BarSettings_t *settings) {  		return;  	} +	/* read config file */  	while (!feof (configfd)) {  		memset (val, 0, sizeof (*val));  		memset (key, 0, sizeof (*key)); @@ -233,6 +237,8 @@ void BarSettingsRead (BarSettings_t *settings) {  			settings->autostartStation = strdup (val);  		} else if (strcmp ("event_command", key) == 0) {  			settings->eventCmd = strdup (val); +		} else if (strcmp ("history", key) == 0) { +			settings->history = atoi (val);  		}  	} diff --git a/src/settings.h b/src/settings.h index b3811a6..3d98ec6 100644 --- a/src/settings.h +++ b/src/settings.h @@ -30,7 +30,8 @@ THE SOFTWARE.  #define BAR_KS_ARGS PianoHandle_t *ph, struct audioPlayer *player, \  		struct BarSettings *settings, PianoSong_t **curSong, \ -		PianoStation_t **curStation, char *doQuit, FILE *curFd +		PianoStation_t **curStation, PianoSong_t **songHistory, char *doQuit, \ +		FILE *curFd  struct BarSettings {  	char *username; @@ -50,6 +51,7 @@ struct BarSettings {  	PianoAudioFormat_t audioFormat;  	char *autostartStation;  	char *eventCmd; +	unsigned int history;  };  typedef struct BarSettings BarSettings_t; diff --git a/src/ui_act.c b/src/ui_act.c index a3d33ed..5510b2f 100644 --- a/src/ui_act.c +++ b/src/ui_act.c @@ -163,7 +163,7 @@ void BarUiActDeleteStation (BAR_KS_ARGS) {  		if ((pRet = BarUiPrintPianoStatus (PianoDeleteStation (ph,  				*curStation))) == PIANO_RET_OK) {  			BarUiDoSkipSong (player); -			PianoDestroyPlaylist (ph); +			PianoDestroyPlaylist (*curSong);  			*curSong = NULL;  			*curStation = NULL;  		} @@ -315,7 +315,7 @@ void BarUiActRenameStation (BAR_KS_ARGS) {   */  void BarUiActSelectStation (BAR_KS_ARGS) {  	BarUiDoSkipSong (player); -	PianoDestroyPlaylist (ph); +	PianoDestroyPlaylist (*curSong);  	*curSong = NULL;  	*curStation = BarUiSelectStation (ph, "Select station: ", curFd);  	if (*curStation != NULL) { @@ -386,3 +386,60 @@ void BarUiActQuit (BAR_KS_ARGS) {  	*doQuit = 1;  	BarUiDoSkipSong (player);  } + +/*	song history + */ +void BarUiActHistory (BAR_KS_ARGS) { +	char selectBuf[2]; +	PianoSong_t *selectedSong; + +	if (*songHistory != NULL) { +		selectedSong = BarUiSelectSong (*songHistory, curFd); +		if (selectedSong != NULL) { +			BarUiMsg (MSG_QUESTION, "%s - %s: [l]ove or [b]an? ", +					selectedSong->artist, selectedSong->title); +			BarReadline (selectBuf, sizeof (selectBuf), "lbs", 1, 0, curFd); +			if (selectBuf[0] == 'l' || selectBuf[0] == 'b') { +				PianoReturn_t pRet = PIANO_RET_ERR; +				/* make sure we're transforming the _original_ station (not +				 * curStation) */ +				PianoStation_t *songStation = +						PianoFindStationById (ph->stations, +								selectedSong->stationId); + +				if (songStation == NULL) { +					BarUiMsg (MSG_ERR, "Station does not exist any more.\n"); +					return; +				} + +				if (!BarTransformIfShared (ph, songStation)) { +					return; +				} + +				switch (selectBuf[0]) { +					case 'l': +						/* love */ +						/* FIXME: copy&waste */ +						BarUiMsg (MSG_INFO, "Loving song... "); +						pRet = BarUiPrintPianoStatus (PianoRateTrack (ph, +								selectedSong, PIANO_RATE_LOVE)); +						BarUiStartEventCmd (settings, "songlove", songStation, +								selectedSong, pRet); +						break; +					 +					case 'b': +						/* ban */ +						BarUiMsg (MSG_INFO, "Banning song... "); +						pRet = BarUiPrintPianoStatus (PianoRateTrack (ph, +								selectedSong, PIANO_RATE_BAN)); +						BarUiStartEventCmd (settings, "songban", songStation, +								selectedSong, pRet); +						break; +				} /* end switch */ +			} /* end if selectBuf[0] */ +		} /* end if selectedSong != NULL */ +	} else { +		BarUiMsg (MSG_INFO, (settings->history == 0) ? "History disabled.\n" : +				"No history yet.\n"); +	} +} diff --git a/src/ui_act.h b/src/ui_act.h index bbb5904..f6c3285 100644 --- a/src/ui_act.h +++ b/src/ui_act.h @@ -46,5 +46,6 @@ void BarUiActPrintUpcoming (BAR_KS_ARGS);  void BarUiActSelectQuickMix (BAR_KS_ARGS);  void BarUiActQuit (BAR_KS_ARGS);  void BarUiActDebug (BAR_KS_ARGS); +void BarUiActHistory (BAR_KS_ARGS);  #endif /* _UI_ACT_H */ | 
