summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libpiano/src/http.c28
-rw-r--r--libpiano/src/http.h1
-rw-r--r--libpiano/src/main.c38
-rw-r--r--libpiano/src/piano.h13
-rw-r--r--libpiano/src/xml.c85
-rw-r--r--libpiano/src/xml.h2
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);