diff options
Diffstat (limited to 'src/libpiano')
| -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 | 
5 files changed, 194 insertions, 156 deletions
| 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);  					}  				}  			} | 
