From 7c96aa41979b1c1b0b4c582c8ac31b7ff779b737 Mon Sep 17 00:00:00 2001 From: Lars-Dominik Braun Date: Thu, 17 Jul 2008 15:53:01 +0200 Subject: 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. --- libpiano/src/http.c | 28 +++++++++++++++++ libpiano/src/http.h | 1 + libpiano/src/main.c | 38 +++++++++++++++++++---- libpiano/src/piano.h | 13 ++++++-- libpiano/src/xml.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++ libpiano/src/xml.h | 2 ++ 6 files changed, 160 insertions(+), 7 deletions(-) (limited to 'libpiano/src') 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 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); -- cgit v1.2.3