summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars-Dominik Braun <lars@6xq.net>2013-08-04 18:53:43 +0200
committerLars-Dominik Braun <lars@6xq.net>2013-08-07 17:37:33 +0200
commitee2e73cd7b5a1de68c8316e916c4ef3a88302bed (patch)
treee952d75d075598123d5ecbe92f14838ce75f6db5
parent36ea2f13f87b9310219790c3cee498201d54f8e0 (diff)
downloadpianobar-windows-ee2e73cd7b5a1de68c8316e916c4ef3a88302bed.tar.gz
pianobar-windows-ee2e73cd7b5a1de68c8316e916c4ef3a88302bed.tar.bz2
pianobar-windows-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--Makefile4
-rw-r--r--src/libpiano/list.c112
-rw-r--r--src/libpiano/piano.c27
-rw-r--r--src/libpiano/piano.h42
-rw-r--r--src/libpiano/request.c6
-rw-r--r--src/libpiano/response.c163
-rw-r--r--src/main.c6
-rw-r--r--src/ui.c73
-rw-r--r--src/ui_act.c37
9 files changed, 239 insertions, 231 deletions
diff --git a/Makefile b/Makefile
index 2289b3a..e9362f6 100644
--- a/Makefile
+++ b/Makefile
@@ -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);
}
}
}
diff --git a/src/main.c b/src/main.c
index 9232f9e..4cca654 100644
--- a/src/main.c
+++ b/src/main.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
@@ -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) {
diff --git a/src/ui.c b/src/ui.c
index 12a64b4..167b3c2 100644
--- a/src/ui.c
+++ b/src/ui.c
@@ -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;