diff options
| author | Lars-Dominik Braun <PromyLOPh@gmail.com> | 2008-07-17 15:53:01 +0200 | 
|---|---|---|
| committer | Lars-Dominik Braun <PromyLOPh@gmail.com> | 2008-07-17 15:53:01 +0200 | 
| commit | 7c96aa41979b1c1b0b4c582c8ac31b7ff779b737 (patch) | |
| tree | 125ea492c67f2bbf0d3e2b81e935de2c2376dc5d | |
| parent | 6b0824285abab829cf97de770c9051a60255106e (diff) | |
| download | pianobar-7c96aa41979b1c1b0b4c582c8ac31b7ff779b737.tar.gz pianobar-7c96aa41979b1c1b0b4c582c8ac31b7ff779b737.tar.bz2 pianobar-7c96aa41979b1c1b0b4c582c8ac31b7ff779b737.zip | |
piano: Initial global genre stations support
Pandora provides a xml list of genre stations. Read this list and insert its
data into our PianoHandle tree if requested.
| -rw-r--r-- | libpiano/src/http.c | 28 | ||||
| -rw-r--r-- | libpiano/src/http.h | 1 | ||||
| -rw-r--r-- | libpiano/src/main.c | 38 | ||||
| -rw-r--r-- | libpiano/src/piano.h | 13 | ||||
| -rw-r--r-- | libpiano/src/xml.c | 85 | ||||
| -rw-r--r-- | libpiano/src/xml.h | 2 | 
6 files changed, 160 insertions, 7 deletions
| diff --git a/libpiano/src/http.c b/libpiano/src/http.c index c480ff8..c633816 100644 --- a/libpiano/src/http.c +++ b/libpiano/src/http.c @@ -89,3 +89,31 @@ PianoReturn_t PianoHttpPost (CURL *ch, char *url, char *postData,  	return ret;  } + +/*	get data + *	@param initialized curl handle + *	@param call this url + *	@param put received data here, memory is allocated by this function + *	@return nothing yet + */ +PianoReturn_t PianoHttpGet (CURL *ch, char *url, char **retData) { +	/* Let's hope nothing will be bigger than this... */ +	char curlRet[PIANO_HTTP_BUFFER_SIZE]; +	PianoReturn_t ret; + +	curl_easy_setopt (ch, CURLOPT_URL, url); +	curl_easy_setopt (ch, CURLOPT_WRITEFUNCTION, PianoCurlRetToVar); +	memset (curlRet, 0, sizeof (curlRet)); +	curl_easy_setopt (ch, CURLOPT_WRITEDATA, curlRet); + +	if (curl_easy_perform (ch) == CURLE_OK) { +		ret = PIANO_RET_OK; +		*retData = calloc (strlen (curlRet) + 1, sizeof (char)); +		strcpy (*retData, curlRet); +	} else { +		ret = PIANO_RET_NET_ERROR; +		*retData = NULL; +	} + +	return ret; +} diff --git a/libpiano/src/http.h b/libpiano/src/http.h index a62be66..9c13bc9 100644 --- a/libpiano/src/http.h +++ b/libpiano/src/http.h @@ -27,5 +27,6 @@ THE SOFTWARE.  PianoReturn_t PianoHttpPost (CURL *ch, char *url, char *postData,  		char **retData); +PianoReturn_t PianoHttpGet (CURL *ch, char *url, char **retData);  #endif /* _HTTP_H */ diff --git a/libpiano/src/main.c b/libpiano/src/main.c index 4cd3aa3..3a16401 100644 --- a/libpiano/src/main.c +++ b/libpiano/src/main.c @@ -105,7 +105,6 @@ void PianoDestroySearchResult (PianoSearchResult_t *searchResult) {  }  /*	free single station - *	@public yes   *	@param station   */  void PianoDestroyStation (PianoStation_t *station) { @@ -117,17 +116,16 @@ void PianoDestroyStation (PianoStation_t *station) {  /*	free complete station list   *	@param piano handle   */ -void PianoDestroyStations (PianoHandle_t *ph) { +void PianoDestroyStations (PianoStation_t *stations) {  	PianoStation_t *curStation, *lastStation; -	curStation = ph->stations; +	curStation = stations;  	while (curStation != NULL) {  		lastStation = curStation;  		curStation = curStation->next;  		PianoDestroyStation (lastStation);  		PianoFree (lastStation, sizeof (*lastStation));  	} -	ph->stations = NULL;  }  /* FIXME: copy & waste */ @@ -169,7 +167,16 @@ void PianoDestroy (PianoHandle_t *ph) {  	PianoFree (ph->user.authToken, 0);  	PianoFree (ph->user.listenerId, 0); -	PianoDestroyStations (ph); +	PianoDestroyStations (ph->stations); +	/* destroy genre stations */ +	PianoGenreCategory_t *curGenreCat = ph->genreStations, *lastGenreCat; +	while (curGenreCat != NULL) { +		PianoDestroyStations (curGenreCat->stations); +		PianoFree (curGenreCat->name, 0); +		lastGenreCat = curGenreCat; +		curGenreCat = curGenreCat->next; +		PianoFree (lastGenreCat, sizeof (*lastGenreCat)); +	}  	PianoDestroyPlaylist (ph);  	memset (ph, 0, sizeof (*ph));  } @@ -707,3 +714,24 @@ PianoStation_t *PianoFindStationById (PianoStation_t *stations,  	}  	return NULL;  } + +/*	receive genre stations + *	@param piano handle + *	@return _OK or error + */ +PianoReturn_t PianoGetGenreStations (PianoHandle_t *ph) { +	char url[PIANO_URL_BUFFER_SIZE]; +	char *retStr; +	PianoReturn_t ret; + +	snprintf (url, sizeof (url), "http://www.pandora.com/xml/genre?r=%li", +			time (NULL)); +	 +	if ((ret = PianoHttpGet (ph->curlHandle, url, &retStr)) == +			PIANO_RET_OK) { +		ret = PianoXmlParseGenreExplorer (ph, retStr); +		PianoFree (retStr, 0); +	} + +	return ret; +} diff --git a/libpiano/src/piano.h b/libpiano/src/piano.h index 3d909f8..07b9791 100644 --- a/libpiano/src/piano.h +++ b/libpiano/src/piano.h @@ -121,6 +121,15 @@ struct PianoArtist {  typedef struct PianoArtist PianoArtist_t; + +struct PianoGenreCategory { +	char *name; +	PianoStation_t *stations; +	struct PianoGenreCategory *next; +}; + +typedef struct PianoGenreCategory PianoGenreCategory_t; +  struct PianoHandle {  	CURL *curlHandle;  	char routeId[9]; @@ -128,6 +137,7 @@ struct PianoHandle {  	/* linked lists */  	PianoStation_t *stations;  	PianoSong_t *playlist; +	PianoGenreCategory_t *genreStations;  };  typedef struct PianoHandle PianoHandle_t; @@ -149,8 +159,6 @@ void PianoInit (PianoHandle_t *);  void PianoDestroy (PianoHandle_t *);  void PianoDestroyPlaylist (PianoHandle_t *ph);  void PianoDestroySearchResult (PianoSearchResult_t *searchResult); -void PianoDestroyStation (PianoStation_t *station); -void PianoDestroyStations (PianoHandle_t *ph);  PianoReturn_t PianoConnect (PianoHandle_t *ph, char *user, char *password,  		char secureLogin); @@ -174,5 +182,6 @@ PianoReturn_t PianoSongTired (PianoHandle_t *ph, PianoSong_t *song);  PianoReturn_t PianoSetQuickmix (PianoHandle_t *ph);  PianoStation_t *PianoFindStationById (PianoStation_t *stations,  		char *searchStation); +PianoReturn_t PianoGetGenreStations (PianoHandle_t *ph);  #endif /* _PIANO_H */ diff --git a/libpiano/src/xml.c b/libpiano/src/xml.c index a144255..91bb120 100644 --- a/libpiano/src/xml.c +++ b/libpiano/src/xml.c @@ -574,3 +574,88 @@ char *PianoXmlEncodeString (const char *s) {  	}  	return sOut;  } + +PianoReturn_t PianoXmlParseGenreExplorer (PianoHandle_t *ph, +		char *xmlContent) { +	xmlNode *docRoot, *catNode, *genreNode, *attrNodeValue; +	xmlDocPtr doc; +	xmlAttr *attrNode; +	PianoReturn_t ret; +	PianoGenreCategory_t *tmpGenreCategory; +	PianoStation_t *tmpStation; + +    if ((ret = PianoXmlInitDoc (xmlContent, &doc, &docRoot)) != +			PIANO_RET_OK) { +        return ret; +    } + +	/* get all <member> nodes */ +    for (catNode = docRoot->children; catNode; catNode = catNode->next) { +        if (catNode->type == XML_ELEMENT_NODE && +				xmlStrEqual ((xmlChar *) "category", catNode->name)) { +			tmpGenreCategory = calloc (1, sizeof (*tmpGenreCategory)); +			/* get category attributes */ +			for (attrNode = catNode->properties; attrNode; +					attrNode = attrNode->next) { +				for (attrNodeValue = attrNode->children; attrNodeValue; +						attrNodeValue = attrNodeValue->next) { +					if (attrNodeValue->type == XML_TEXT_NODE && +							xmlStrEqual (attrNode->name, +							(xmlChar *) "categoryName")) { +						tmpGenreCategory->name = +								strdup ((char *) attrNodeValue->content); +					} +				} +			} +			/* get genre subnodes */ +			for (genreNode = catNode->children; genreNode; +					genreNode = genreNode->next) { +				if (genreNode->type == XML_ELEMENT_NODE && +						xmlStrEqual ((xmlChar *) "genre", genreNode->name)) { +					tmpStation = calloc (1, sizeof (*tmpStation)); +					/* get genre attributes */ +					for (attrNode = genreNode->properties; attrNode; +							attrNode = attrNode->next) { +						for (attrNodeValue = attrNode->children; attrNodeValue; +								attrNodeValue = attrNodeValue->next) { +							if (attrNodeValue->type == XML_TEXT_NODE) { +								if (xmlStrEqual (attrNode->name, +										(xmlChar *) "name")) { +									tmpStation->name = strdup ((char *) attrNodeValue->content); +								} else if (xmlStrEqual (attrNode->name, +										(xmlChar *) "stationId")) { +									tmpStation->id = strdup ((char *) attrNodeValue->content); +								} +							} +						} +					} +					/* append station */ +					if (tmpGenreCategory->stations == NULL) { +						tmpGenreCategory->stations = tmpStation; +					} else { +						PianoStation_t *curStation = +								tmpGenreCategory->stations; +						while (curStation->next != NULL) { +							curStation = curStation->next; +						} +						curStation->next = tmpStation; +					} +				} +			} +			/* append category */ +			if (ph->genreStations == NULL) { +				ph->genreStations = tmpGenreCategory; +			} else { +				PianoGenreCategory_t *curCat = ph->genreStations; +				while (curCat->next != NULL) { +					curCat = curCat->next; +				} +				curCat->next = tmpGenreCategory; +			} +        } +	} + +	xmlFreeDoc (doc); + +	return PIANO_RET_OK; +} diff --git a/libpiano/src/xml.h b/libpiano/src/xml.h index ebc2df7..8a4e613 100644 --- a/libpiano/src/xml.h +++ b/libpiano/src/xml.h @@ -34,6 +34,8 @@ PianoReturn_t PianoXmlParseSimple (char *xml);  PianoReturn_t PianoXmlParseCreateStation (PianoHandle_t *ph, char *xml);  PianoReturn_t PianoXmlParseAddSeed (PianoHandle_t *ph, char *xml,  		PianoStation_t *station); +PianoReturn_t PianoXmlParseGenreExplorer (PianoHandle_t *ph, +		char *xmlContent);  char *PianoXmlEncodeString (const char *s); | 
