From 6a62ae4231c2ce10b6623e32198f40f0a2a8e777 Mon Sep 17 00:00:00 2001 From: Lars-Dominik Braun Date: Tue, 15 Dec 2009 17:08:19 +0100 Subject: New history feature Default key is 'h', playlists are no longer part of PianoHandle_t now (=> libpiano's api changed) --- src/main.c | 77 ++++++++++++++++++++++++++++++++++++++++------------------ src/pianobar.1 | 8 ++++++ src/settings.c | 6 +++++ src/settings.h | 4 ++- src/ui_act.c | 61 ++++++++++++++++++++++++++++++++++++++++++++-- src/ui_act.h | 1 + 6 files changed, 130 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/main.c b/src/main.c index 08eac48..fc6fc76 100644 --- a/src/main.c +++ b/src/main.c @@ -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 @@ -62,6 +62,10 @@ Explain why this song is played. .B act_stationaddbygenre = g 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. @@ -132,6 +136,10 @@ will use this proxy. The music is streamed directly. 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 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 */ -- cgit v1.2.3