diff options
author | Lars-Dominik Braun <lars@6xq.net> | 2013-08-04 18:53:43 +0200 |
---|---|---|
committer | Lars-Dominik Braun <lars@6xq.net> | 2013-08-07 17:37:33 +0200 |
commit | ee2e73cd7b5a1de68c8316e916c4ef3a88302bed (patch) | |
tree | e952d75d075598123d5ecbe92f14838ce75f6db5 | |
parent | 36ea2f13f87b9310219790c3cee498201d54f8e0 (diff) | |
download | pianobar-ee2e73cd7b5a1de68c8316e916c4ef3a88302bed.tar.gz pianobar-ee2e73cd7b5a1de68c8316e916c4ef3a88302bed.tar.bz2 pianobar-ee2e73cd7b5a1de68c8316e916c4ef3a88302bed.zip |
piano: Generic linked lists
Introduces generic linked list structure and functions (like append,
delete, …). Removes a lot of copy&pasted code and improves code
readability/reusability.
Heads up: This change breaks libpiano’s ABI.
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | src/libpiano/list.c | 112 | ||||
-rw-r--r-- | src/libpiano/piano.c | 27 | ||||
-rw-r--r-- | src/libpiano/piano.h | 42 | ||||
-rw-r--r-- | src/libpiano/request.c | 6 | ||||
-rw-r--r-- | src/libpiano/response.c | 163 | ||||
-rw-r--r-- | src/main.c | 6 | ||||
-rw-r--r-- | src/ui.c | 73 | ||||
-rw-r--r-- | src/ui_act.c | 37 |
9 files changed, 239 insertions, 231 deletions
@@ -48,10 +48,12 @@ LIBPIANO_SRC:=\ ${LIBPIANO_DIR}/crypt.c \ ${LIBPIANO_DIR}/piano.c \ ${LIBPIANO_DIR}/request.c \ - ${LIBPIANO_DIR}/response.c + ${LIBPIANO_DIR}/response.c \ + ${LIBPIANO_DIR}/list.c LIBPIANO_HDR:=\ ${LIBPIANO_DIR}/config.h \ ${LIBPIANO_DIR}/crypt.h \ + ${LIBPIANO_DIR}/list.h \ ${LIBPIANO_DIR}/piano.h \ ${LIBPIANO_DIR}/piano_private.h LIBPIANO_OBJ:=${LIBPIANO_SRC:.c=.o} diff --git a/src/libpiano/list.c b/src/libpiano/list.c new file mode 100644 index 0000000..2e83ab0 --- /dev/null +++ b/src/libpiano/list.c @@ -0,0 +1,112 @@ +/* +Copyright (c) 2013 + Lars-Dominik Braun <lars@6xq.net> + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include <assert.h> + +#include "piano.h" + +#define PianoListForeach(l) for (; (l) != NULL; (l) = (void *) (l)->next) + +/* append element e to list l, return new list head + */ +void *PianoListAppend (PianoListHead_t * const l, PianoListHead_t * const e) { + assert (e != NULL); + assert (e->next == NULL); + + if (l == NULL) { + return e; + } else { + PianoListHead_t *curr = l; + while (curr->next != NULL) { + curr = curr->next; + } + curr->next = e; + return l; + } +} + +/* prepend element e to list l, returning new list head + */ +void *PianoListPrepend (PianoListHead_t * const l, PianoListHead_t * const e) { + assert (e != NULL); + assert (e->next == NULL); + + e->next = l; + return e; +} + +/* delete element e from list l, return new list head + */ +void *PianoListDelete (PianoListHead_t * const l, PianoListHead_t * const e) { + assert (l != NULL); + assert (e != NULL); + + PianoListHead_t *first = l, *curr = l, *prev = NULL; + PianoListForeach (curr) { + if (curr == e) { + /* found it! */ + if (prev != NULL) { + prev->next = curr->next; + } else { + /* no successor */ + first = curr->next; + } + break; + } + prev = curr; + } + + return first; +} + +/* get nth element of list + */ +void *PianoListGet (PianoListHead_t * const l, const size_t n) { + PianoListHead_t *curr = l; + size_t i = n; + + PianoListForeach (curr) { + if (i == 0) { + return curr; + } + --i; + } + + return NULL; +} + +/* count elements in list l + */ +size_t PianoListCount (const PianoListHead_t * const l) { + assert (l != NULL); + + size_t count = 0; + const PianoListHead_t *curr = l; + + PianoListForeach (curr) { + ++count; + } + + return count; +} + diff --git a/src/libpiano/piano.c b/src/libpiano/piano.c index 9020a6a..b519f49 100644 --- a/src/libpiano/piano.c +++ b/src/libpiano/piano.c @@ -1,5 +1,5 @@ /* -Copyright (c) 2008-2012 +Copyright (c) 2008-2013 Lars-Dominik Braun <lars@6xq.net> Permission is hereby granted, free of charge, to any person obtaining a copy @@ -80,7 +80,7 @@ static void PianoDestroyArtists (PianoArtist_t *artists) { free (curArtist->musicId); free (curArtist->seedId); lastArtist = curArtist; - curArtist = curArtist->next; + curArtist = (PianoArtist_t *) curArtist->head.next; free (lastArtist); } } @@ -113,7 +113,7 @@ static void PianoDestroyStations (PianoStation_t *stations) { curStation = stations; while (curStation != NULL) { lastStation = curStation; - curStation = curStation->next; + curStation = (PianoStation_t *) curStation->head.next; PianoDestroyStation (lastStation); free (lastStation); } @@ -141,7 +141,7 @@ void PianoDestroyPlaylist (PianoSong_t *playlist) { free (curSong->detailUrl); free (curSong->trackToken); lastSong = curSong; - curSong = curSong->next; + curSong = (PianoSong_t *) curSong->head.next; free (lastSong); } } @@ -163,7 +163,7 @@ static void PianoDestroyGenres (PianoGenre_t *genres) { free (curGenre->name); free (curGenre->musicId); lastGenre = curGenre; - curGenre = curGenre->next; + curGenre = (PianoGenre_t *) curGenre->head.next; free (lastGenre); } } @@ -201,7 +201,7 @@ void PianoDestroy (PianoHandle_t *ph) { PianoDestroyGenres (curGenreCat->genres); free (curGenreCat->name); lastGenreCat = curGenreCat; - curGenreCat = curGenreCat->next; + curGenreCat = (PianoGenreCategory_t *) curGenreCat->head.next; free (lastGenreCat); } memset (ph, 0, sizeof (*ph)); @@ -221,14 +221,17 @@ void PianoDestroyRequest (PianoRequest_t *req) { * @param search for this * @return the first station structure matching the given id */ -PianoStation_t *PianoFindStationById (PianoStation_t *stations, - const char *searchStation) { - while (stations != NULL) { - if (strcmp (stations->id, searchStation) == 0) { - return stations; +PianoStation_t *PianoFindStationById (PianoStation_t * const stations, + const char * const searchStation) { + assert (searchStation != NULL); + + PianoStation_t *currStation = stations; + PianoListForeachP (currStation) { + if (strcmp (currStation->id, searchStation) == 0) { + return currStation; } - stations = stations->next; } + return NULL; } diff --git a/src/libpiano/piano.h b/src/libpiano/piano.h index 04f33b5..ce66171 100644 --- a/src/libpiano/piano.h +++ b/src/libpiano/piano.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2008-2011 +Copyright (c) 2008-2013 Lars-Dominik Braun <lars@6xq.net> Permission is hereby granted, free of charge, to any person obtaining a copy @@ -42,19 +42,23 @@ THE SOFTWARE. #define PIANO_RPC_HOST "tuner.pandora.com" #define PIANO_RPC_PATH "/services/json/?" +typedef struct PianoListHead { + struct PianoListHead *next; +} PianoListHead_t; + typedef struct PianoUserInfo { char *listenerId; char *authToken; } PianoUserInfo_t; typedef struct PianoStation { + PianoListHead_t head; char isCreator; char isQuickMix; char useQuickMix; /* station will be included in quickmix */ char *name; char *id; char *seedId; - struct PianoStation *next; } PianoStation_t; typedef enum { @@ -78,6 +82,7 @@ typedef enum { } PianoAudioQuality_t; typedef struct PianoSong { + PianoListHead_t head; char *artist; char *stationId; char *album; @@ -92,28 +97,27 @@ typedef struct PianoSong { float fileGain; PianoSongRating_t rating; PianoAudioFormat_t audioFormat; - struct PianoSong *next; } PianoSong_t; /* currently only used for search results */ typedef struct PianoArtist { + PianoListHead_t head; char *name; char *musicId; char *seedId; int score; - struct PianoArtist *next; } PianoArtist_t; typedef struct PianoGenre { + PianoListHead_t head; char *name; char *musicId; - struct PianoGenre *next; } PianoGenre_t; typedef struct PianoGenreCategory { + PianoListHead_t head; char *name; PianoGenre_t *genres; - struct PianoGenreCategory *next; } PianoGenreCategory_t; typedef struct PianoPartner { @@ -298,6 +302,27 @@ typedef enum { PIANO_RET_P_RATE_LIMIT = PIANO_RET_OFFSET+1039, } PianoReturn_t; +/* list stuff */ +#ifndef __GNUC__ +# define __attribute__(x) +#endif +size_t PianoListCount (const PianoListHead_t * const l); +#define PianoListCountP(l) PianoListCount(&(l)->head) +void *PianoListAppend (PianoListHead_t * const l, PianoListHead_t * const e) + __attribute__ ((warn_unused_result)); +#define PianoListAppendP(l,e) PianoListAppend(&(l)->head, &(e)->head) +void *PianoListDelete (PianoListHead_t * const l, PianoListHead_t * const e) + __attribute__ ((warn_unused_result)); +#define PianoListDeleteP(l,e) PianoListDelete(&(l)->head, &(e)->head) +#define PianoListNextP(e) ((void *) (e)->head.next) +void *PianoListPrepend (PianoListHead_t * const l, PianoListHead_t * const e) + __attribute__ ((warn_unused_result)); +#define PianoListPrependP(l,e) PianoListPrepend (&(l)->head, &(e)->head) +void *PianoListGet (PianoListHead_t * const l, const size_t n); +#define PianoListGetP(l,n) PianoListGet (&(l)->head, n) +#define PianoListForeachP(l) for (; (l) != NULL; (l) = (void *) (l)->head.next) + +/* memory management */ PianoReturn_t PianoInit (PianoHandle_t *, const char *, const char *, const char *, const char *, const char *); @@ -306,12 +331,15 @@ void PianoDestroyPlaylist (PianoSong_t *); void PianoDestroySearchResult (PianoSearchResult_t *); void PianoDestroyStationInfo (PianoStationInfo_t *); +/* pandora rpc */ PianoReturn_t PianoRequest (PianoHandle_t *, PianoRequest_t *, PianoRequestType_t); PianoReturn_t PianoResponse (PianoHandle_t *, PianoRequest_t *); void PianoDestroyRequest (PianoRequest_t *); -PianoStation_t *PianoFindStationById (PianoStation_t *, const char *); +/* misc */ +PianoStation_t *PianoFindStationById (PianoStation_t * const, + const char * const); const char *PianoErrorToStr (PianoReturn_t); #endif /* _PIANO_H */ diff --git a/src/libpiano/request.c b/src/libpiano/request.c index 85d6286..82bf350 100644 --- a/src/libpiano/request.c +++ b/src/libpiano/request.c @@ -1,5 +1,5 @@ /* -Copyright (c) 2008-2012 +Copyright (c) 2008-2013 Lars-Dominik Braun <lars@6xq.net> Permission is hereby granted, free of charge, to any person obtaining a copy @@ -272,14 +272,12 @@ PianoReturn_t PianoRequest (PianoHandle_t *ph, PianoRequest_t *req, PianoStation_t *curStation = ph->stations; json_object *a = json_object_new_array (); - while (curStation != NULL) { + PianoListForeachP (curStation) { /* quick mix can't contain itself */ if (curStation->useQuickMix && !curStation->isQuickMix) { json_object_array_add (a, json_object_new_string (curStation->id)); } - - curStation = curStation->next; } json_object_object_add (j, "quickMixStationIds", a); diff --git a/src/libpiano/response.c b/src/libpiano/response.c index ae7b140..41bbfd3 100644 --- a/src/libpiano/response.c +++ b/src/libpiano/response.c @@ -1,5 +1,5 @@ /* -Copyright (c) 2008-2012 +Copyright (c) 2008-2013 Lars-Dominik Braun <lars@6xq.net> Permission is hereby granted, free of charge, to any person obtaining a copy @@ -193,21 +193,13 @@ PianoReturn_t PianoResponse (PianoHandle_t *ph, PianoRequest_t *req) { } /* start new linked list or append */ - if (ph->stations == NULL) { - ph->stations = tmpStation; - } else { - PianoStation_t *curStation = ph->stations; - while (curStation->next != NULL) { - curStation = curStation->next; - } - curStation->next = tmpStation; - } + ph->stations = PianoListAppendP (ph->stations, tmpStation); } /* fix quickmix flags */ if (mix != NULL) { PianoStation_t *curStation = ph->stations; - while (curStation != NULL) { + PianoListForeachP (curStation) { for (size_t 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), @@ -215,7 +207,6 @@ PianoReturn_t PianoResponse (PianoHandle_t *ph, PianoRequest_t *req) { curStation->useQuickMix = true; } } - curStation = curStation->next; } } break; @@ -293,16 +284,7 @@ PianoReturn_t PianoResponse (PianoHandle_t *ph, PianoRequest_t *req) { break; } - /* begin linked list or append */ - if (playlist == NULL) { - playlist = song; - } else { - PianoSong_t *curSong = playlist; - while (curSong->next != NULL) { - curSong = curSong->next; - } - curSong->next = song; - } + playlist = PianoListAppendP (playlist, song); } reqData->retPlaylist = playlist; @@ -340,23 +322,9 @@ PianoReturn_t PianoResponse (PianoHandle_t *ph, PianoRequest_t *req) { assert (station != NULL); - /* delete station from local station list */ - PianoStation_t *curStation = ph->stations, *lastStation = NULL; - while (curStation != NULL) { - if (curStation == station) { - if (lastStation != NULL) { - lastStation->next = curStation->next; - } else { - /* first station in list */ - ph->stations = curStation->next; - } - PianoDestroyStation (curStation); - free (curStation); - break; - } - lastStation = curStation; - curStation = curStation->next; - } + ph->stations = PianoListDeleteP (ph->stations, station); + PianoDestroyStation (station); + free (station); break; } @@ -385,16 +353,8 @@ PianoReturn_t PianoResponse (PianoHandle_t *ph, PianoRequest_t *req) { artist->name = PianoJsonStrdup (a, "artistName"); artist->musicId = PianoJsonStrdup (a, "musicToken"); - /* add result to linked list */ - if (searchResult->artists == NULL) { - searchResult->artists = artist; - } else { - PianoArtist_t *curArtist = searchResult->artists; - while (curArtist->next != NULL) { - curArtist = curArtist->next; - } - curArtist->next = artist; - } + searchResult->artists = + PianoListAppendP (searchResult->artists, artist); } } @@ -413,16 +373,8 @@ PianoReturn_t PianoResponse (PianoHandle_t *ph, PianoRequest_t *req) { song->artist = PianoJsonStrdup (s, "artistName"); song->musicId = PianoJsonStrdup (s, "musicToken"); - /* add result to linked list */ - if (searchResult->songs == NULL) { - searchResult->songs = song; - } else { - PianoSong_t *curSong = searchResult->songs; - while (curSong->next != NULL) { - curSong = curSong->next; - } - curSong->next = song; - } + searchResult->songs = + PianoListAppendP (searchResult->songs, song); } } break; @@ -438,32 +390,14 @@ PianoReturn_t PianoResponse (PianoHandle_t *ph, PianoRequest_t *req) { PianoJsonParseStation (result, tmpStation); - if (ph->stations == NULL) { - ph->stations = tmpStation; - } else { - PianoStation_t *curStation = ph->stations, *prevStation = NULL; - while (curStation->next != NULL) { - /* replace if station with same id exists already */ - if (strcmp (curStation->id, tmpStation->id) == 0) { - if (prevStation == NULL) { - ph->stations = tmpStation; - } else { - prevStation->next = tmpStation; - } - tmpStation->next = curStation->next; - - PianoDestroyStation (curStation); - free (curStation); - break; - } - prevStation = curStation; - curStation = curStation->next; - } - /* append otherwise */ - if (tmpStation->next == NULL) { - curStation->next = tmpStation; - } + PianoStation_t *search = PianoFindStationById (ph->stations, + tmpStation->id); + if (search != NULL) { + ph->stations = PianoListDeleteP (ph->stations, search); + PianoDestroyStation (search); + free (search); } + ph->stations = PianoListAppendP (ph->stations, tmpStation); break; } @@ -514,29 +448,14 @@ PianoReturn_t PianoResponse (PianoHandle_t *ph, PianoRequest_t *req) { tmpGenre->musicId = PianoJsonStrdup (s, "stationToken"); - /* append station */ - if (tmpGenreCategory->genres == NULL) { - tmpGenreCategory->genres = tmpGenre; - } else { - PianoGenre_t *curGenre = - tmpGenreCategory->genres; - while (curGenre->next != NULL) { - curGenre = curGenre->next; - } - curGenre->next = tmpGenre; - } - } - } - /* append category */ - if (ph->genreStations == NULL) { - ph->genreStations = tmpGenreCategory; - } else { - PianoGenreCategory_t *curCat = ph->genreStations; - while (curCat->next != NULL) { - curCat = curCat->next; + tmpGenreCategory->genres = + PianoListAppendP (tmpGenreCategory->genres, + tmpGenre); } - curCat->next = tmpGenreCategory; } + + ph->genreStations = PianoListAppendP (ph->genreStations, + tmpGenreCategory); } } break; @@ -615,15 +534,8 @@ PianoReturn_t PianoResponse (PianoHandle_t *ph, PianoRequest_t *req) { seedSong->artist = PianoJsonStrdup (s, "artistName"); seedSong->seedId = PianoJsonStrdup (s, "seedId"); - if (info->songSeeds == NULL) { - info->songSeeds = seedSong; - } else { - PianoSong_t *curSong = info->songSeeds; - while (curSong->next != NULL) { - curSong = curSong->next; - } - curSong->next = seedSong; - } + info->songSeeds = PianoListAppendP (info->songSeeds, + seedSong); } } @@ -643,15 +555,8 @@ PianoReturn_t PianoResponse (PianoHandle_t *ph, PianoRequest_t *req) { seedArtist->name = PianoJsonStrdup (a, "artistName"); seedArtist->seedId = PianoJsonStrdup (a, "seedId"); - if (info->artistSeeds == NULL) { - info->artistSeeds = seedArtist; - } else { - PianoArtist_t *curArtist = info->artistSeeds; - while (curArtist->next != NULL) { - curArtist = curArtist->next; - } - curArtist->next = seedArtist; - } + info->artistSeeds = + PianoListAppendP (info->artistSeeds, seedArtist); } } } @@ -679,16 +584,8 @@ PianoReturn_t PianoResponse (PianoHandle_t *ph, PianoRequest_t *req) { json_object_object_get (s, "isPositive")) ? PIANO_RATE_LOVE : PIANO_RATE_BAN; - - if (info->feedback == NULL) { - info->feedback = feedbackSong; - } else { - PianoSong_t *curSong = info->feedback; - while (curSong->next != NULL) { - curSong = curSong->next; - } - curSong->next = feedbackSong; - } + info->feedback = PianoListAppendP (info->feedback, + feedbackSong); } } } @@ -1,5 +1,5 @@ /* -Copyright (c) 2008-2012 +Copyright (c) 2008-2013 Lars-Dominik Braun <lars@6xq.net> Permission is hereby granted, free of charge, to any person obtaining a copy @@ -372,8 +372,8 @@ static void BarMainLoop (BarApp_t *app) { /* what's next? */ if (app->playlist != NULL) { PianoSong_t *histsong = app->playlist; - app->playlist = app->playlist->next; - histsong->next = NULL; + app->playlist = PianoListNextP (app->playlist); + histsong->head.next = NULL; BarUiHistoryPrepend (app, histsong); } if (app->playlist == NULL) { @@ -1,5 +1,5 @@ /* -Copyright (c) 2008-2011 +Copyright (c) 2008-2013 Lars-Dominik Braun <lars@6xq.net> Permission is hereby granted, free of charge, to any person obtaining a copy @@ -305,20 +305,14 @@ static PianoStation_t **BarSortedStations (PianoStation_t *unsortedStations, assert (order < sizeof (orderMapping)/sizeof(*orderMapping)); - /* get size */ - currStation = unsortedStations; - while (currStation != NULL) { - ++stationCount; - currStation = currStation->next; - } + stationCount = PianoListCountP (unsortedStations); stationArray = calloc (stationCount, sizeof (*stationArray)); /* copy station pointers */ - currStation = unsortedStations; i = 0; - while (currStation != NULL) { + currStation = unsortedStations; + PianoListForeachP (currStation) { stationArray[i] = currStation; - currStation = currStation->next; ++i; } @@ -422,11 +416,7 @@ PianoSong_t *BarUiSelectSong (const BarSettings_t *settings, if (isnumeric (buf)) { unsigned long i = strtoul (buf, NULL, 0); - tmpSong = startSong; - while (tmpSong != NULL && i > 0) { - tmpSong = tmpSong->next; - i--; - } + tmpSong = PianoListGetP (startSong, i); } } while (tmpSong == NULL); @@ -449,12 +439,12 @@ PianoArtist_t *BarUiSelectArtist (BarApp_t *app, PianoArtist_t *startArtist) { /* print all artists */ i = 0; tmpArtist = startArtist; - while (tmpArtist != NULL) { + PianoListForeachP (tmpArtist) { if (BarStrCaseStr (tmpArtist->name, buf) != NULL) { - BarUiMsg (&app->settings, MSG_LIST, "%2u) %s\n", i, tmpArtist->name); + BarUiMsg (&app->settings, MSG_LIST, "%2u) %s\n", i, + tmpArtist->name); } i++; - tmpArtist = tmpArtist->next; } BarUiMsg (&app->settings, MSG_QUESTION, "Select artist: "); @@ -465,11 +455,7 @@ PianoArtist_t *BarUiSelectArtist (BarApp_t *app, PianoArtist_t *startArtist) { if (isnumeric (buf)) { i = strtoul (buf, NULL, 0); - tmpArtist = startArtist; - while (tmpArtist != NULL && i > 0) { - tmpArtist = tmpArtist->next; - i--; - } + tmpArtist = PianoListGetP (startArtist, i); } } while (tmpArtist == NULL); @@ -667,7 +653,7 @@ size_t BarUiListSongs (const BarSettings_t *settings, size_t i = 0; char digits[8]; - while (song != NULL) { + PianoListForeachP (song) { if (filter == NULL || (filter != NULL && (BarStrCaseStr (song->artist, filter) != NULL || BarStrCaseStr (song->title, filter) != NULL))) { @@ -683,7 +669,6 @@ size_t BarUiListSongs (const BarSettings_t *settings, BarUiMsg (settings, MSG_LIST, "%s", outstr); } i++; - song = song->next; } return i; @@ -798,32 +783,26 @@ void BarUiStartEventCmd (const BarSettings_t *settings, const char *type, } } -/* prepend song to history, must not be a list of songs as ->next is modified! +/* prepend song to history */ void BarUiHistoryPrepend (BarApp_t *app, PianoSong_t *song) { + assert (app != NULL); + assert (song != NULL); + /* make sure it's a single song */ + assert (PianoListNextP (song) == NULL); + if (app->settings.history != 0) { - PianoSong_t *tmpSong; - - song->next = app->songHistory; - app->songHistory = song; - - /* 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 = app->songHistory; - while (i < app->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); + app->songHistory = PianoListPrependP (app->songHistory, song); + PianoSong_t *del; + do { + del = PianoListGetP (app->songHistory, app->settings.history); + if (del != NULL) { + app->songHistory = PianoListDeleteP (app->songHistory, del); + PianoDestroyPlaylist (del); + } else { + break; } - } + } while (true); } else { PianoDestroyPlaylist (song); } diff --git a/src/ui_act.c b/src/ui_act.c index 270c1f5..8cf6c2b 100644 --- a/src/ui_act.c +++ b/src/ui_act.c @@ -232,7 +232,8 @@ BarUiActCallback(BarUiActDeleteStation) { if (BarUiActDefaultPianoCall (PIANO_REQUEST_DELETE_STATION, selStation) && selStation == app->curStation) { BarUiDoSkipSong (&app->player); - PianoDestroyPlaylist (app->playlist->next); + PianoDestroyPlaylist (PianoListNextP (app->playlist)); + app->playlist->head.next = NULL; BarUiHistoryPrepend (app, app->playlist); app->playlist = NULL; app->curStation = NULL; @@ -283,10 +284,9 @@ BarUiActCallback(BarUiActStationFromGenre) { /* print all available categories */ curCat = app->ph.genreStations; i = 0; - while (curCat != NULL) { + PianoListForeachP (curCat) { BarUiMsg (&app->settings, MSG_LIST, "%2i) %s\n", i, curCat->name); i++; - curCat = curCat->next; } do { @@ -295,20 +295,15 @@ BarUiActCallback(BarUiActStationFromGenre) { if (BarReadlineInt (&i, &app->input) == 0) { return; } - curCat = app->ph.genreStations; - while (curCat != NULL && i > 0) { - curCat = curCat->next; - i--; - } + curCat = PianoListGetP (app->ph.genreStations, i); } while (curCat == NULL); /* print all available stations */ - curGenre = curCat->genres; i = 0; - while (curGenre != NULL) { + curGenre = curCat->genres; + PianoListForeachP (curGenre) { BarUiMsg (&app->settings, MSG_LIST, "%2i) %s\n", i, curGenre->name); i++; - curGenre = curGenre->next; } do { @@ -316,11 +311,7 @@ BarUiActCallback(BarUiActStationFromGenre) { if (BarReadlineInt (&i, &app->input) == 0) { return; } - curGenre = curCat->genres; - while (curGenre != NULL && i > 0) { - curGenre = curGenre->next; - i--; - } + curGenre = PianoListGetP (curCat->genres, i); } while (curGenre == NULL); /* create station */ @@ -477,7 +468,8 @@ BarUiActCallback(BarUiActSelectStation) { BarUiPrintStation (&app->settings, app->curStation); BarUiDoSkipSong (&app->player); if (app->playlist != NULL) { - PianoDestroyPlaylist (app->playlist->next); + PianoDestroyPlaylist (PianoListNextP (app->playlist)); + app->playlist->head.next = NULL; BarUiHistoryPrepend (app, app->playlist); app->playlist = NULL; } @@ -505,7 +497,7 @@ BarUiActCallback(BarUiActTempBanSong) { BarUiActCallback(BarUiActPrintUpcoming) { assert (selSong != NULL); - PianoSong_t *nextSong = selSong->next; + PianoSong_t *nextSong = PianoListNextP (selSong); if (nextSong != NULL) { BarUiListSongs (&app->settings, nextSong, NULL); } else { @@ -527,27 +519,24 @@ static void BarUiActQuickmixCallback (BarApp_t *app, char *buf) { switch (*buf) { case 't': /* toggle */ - while (curStation != NULL) { + PianoListForeachP (curStation) { curStation->useQuickMix = !curStation->useQuickMix; - curStation = curStation->next; } *buf = '\0'; break; case 'a': /* enable all */ - while (curStation != NULL) { + PianoListForeachP (curStation) { curStation->useQuickMix = true; - curStation = curStation->next; } *buf = '\0'; break; case 'n': /* enable none */ - while (curStation != NULL) { + PianoListForeachP (curStation) { curStation->useQuickMix = false; - curStation = curStation->next; } *buf = '\0'; break; |