From e721307fa51241247e73ae2096b6b160671dbeb4 Mon Sep 17 00:00:00 2001 From: Lars-Dominik Braun Date: Thu, 12 Jun 2008 13:11:41 +0200 Subject: lib: Initial music search implementation --- libpiano/main.c | 71 ++++++++++++++++++++++++++++++++++ libpiano/piano.h | 21 ++++++++++ libpiano/xml.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 206 insertions(+) (limited to 'libpiano') diff --git a/libpiano/main.c b/libpiano/main.c index 895b01c..52d7a1b 100644 --- a/libpiano/main.c +++ b/libpiano/main.c @@ -52,6 +52,38 @@ void PianoInit (PianoHandle_t *ph) { curl_easy_setopt (ph->curlHandle, CURLOPT_CONNECTTIMEOUT, 60); } +/* free complete search result + * @author PromyLOPh + * @added 2008-06-12 + * @public yes + * @param search result + */ +void PianoDestroySearchResult (PianoSearchResult_t *searchResult) { + PianoArtist_t *curArtist, *lastArtist; + PianoSong_t *curSong, *lastSong; + + curArtist = searchResult->artists; + while (curArtist != NULL) { + free (curArtist->name); + free (curArtist->musicId); + lastArtist = curArtist; + curArtist = curArtist->next; + memset (lastArtist, 0, sizeof (*lastArtist)); + free (lastArtist); + } + + curSong = searchResult->songs; + while (curSong != NULL) { + free (curSong->title); + free (curSong->artist); + free (curSong->musicId); + lastSong = curSong; + curSong = curSong->next; + memset (lastSong, 0, sizeof (*lastSong)); + free (lastSong); + } +} + /* free complete station list * @author PromyLOPh * @added 2008-06-09 @@ -349,3 +381,42 @@ PianoReturn_t PianoDeleteStation (PianoHandle_t *ph, PianoStation_t *station) { return ret; } + +/* search for music (artist or track), needed to create new station, don't + * forget to free the search result + * @author PromyLOPh + * @added 2008-06-11 + * @public yes + * @param piano handle + * @param utf-8 search string + * @param return search result + * @return nothing yet + */ +void PianoSearchMusic (PianoHandle_t *ph, char *searchStr, + PianoSearchResult_t *searchResult) { + char xmlSendBuf[10000], url[PIANO_URL_BUFFER_SIZE]; + char *requestStr, *retStr, *xmlencodedSearchStr, *urlencodedSearchStr; + + xmlencodedSearchStr = PianoXmlEncodeString (searchStr); + snprintf (xmlSendBuf, sizeof (xmlSendBuf), "" + "music.search" + "%li" + "%s" + "%s" + "", time (NULL), ph->user.authToken, + xmlencodedSearchStr); + requestStr = PianoEncryptString (xmlSendBuf); + + urlencodedSearchStr = curl_easy_escape (ph->curlHandle, searchStr, 0); + snprintf (url, sizeof (url), PIANO_RPC_URL "rid=%s&lid=%s&" + "method=search&arg1=%s", ph->routeId, ph->user.listenerId, + urlencodedSearchStr); + + PianoHttpPost (ph->curlHandle, url, requestStr, &retStr); + PianoXmlParseSearch (retStr, searchResult); + + curl_free (urlencodedSearchStr); + free (xmlencodedSearchStr); + free (retStr); + free (requestStr); +} diff --git a/libpiano/piano.h b/libpiano/piano.h index ebb7f55..bbe0a9e 100644 --- a/libpiano/piano.h +++ b/libpiano/piano.h @@ -101,11 +101,24 @@ struct PianoSong { char *title; char *focusTraitId; char *identity; + int score; /* only used for search results */ struct PianoSong *next; }; typedef struct PianoSong PianoSong_t; +/* currently only used for search results */ +struct PianoArtist { + /* disabled: iscomposer */ + /* disabled: likelymatch */ + char *name; + char *musicId; + int score; + struct PianoArtist *next; +}; + +typedef struct PianoArtist PianoArtist_t; + struct PianoHandle { CURL *curlHandle; char routeId[9]; @@ -117,6 +130,13 @@ struct PianoHandle { typedef struct PianoHandle PianoHandle_t; +struct PianoSearchResult { + PianoSong_t *songs; + PianoArtist_t *artists; +}; + +typedef struct PianoSearchResult PianoSearchResult_t; + /* FIXME: more error types (http failed, e.g.) later */ enum PianoReturn {PIANO_RET_OK, PIANO_RET_ERR}; typedef enum PianoReturn PianoReturn_t; @@ -124,6 +144,7 @@ typedef enum PianoReturn PianoReturn_t; void PianoInit (PianoHandle_t *); void PianoDestroy (PianoHandle_t *); void PianoDestroyPlaylist (PianoHandle_t *ph); +void PianoDestroySearchResult (PianoSearchResult_t *searchResult); void PianoConnect (PianoHandle_t *, char *, char *); void PianoGetStations (PianoHandle_t *ph); diff --git a/libpiano/xml.c b/libpiano/xml.c index 7e5346a..f183c7c 100644 --- a/libpiano/xml.c +++ b/libpiano/xml.c @@ -314,6 +314,120 @@ PianoReturn_t PianoXmlParseSimple (char *xml) { return ret; } +/* xml struct parser callback, used in PianoXmlParseSearchCb + * @author PromyLOPh + * @added 2008-06-12 + */ +void PianoXmlParseSearchArtistCb (char *key, xmlNode *value, void *data) { + PianoArtist_t *artist = data; + char *valueStr = NULL; + + /* some values have subnodes like or , just + * ignore them... */ + if (value->content != NULL) { + valueStr = (char *) value->content; + } else if (value->children != NULL && + value->children->content != NULL) { + valueStr = (char *) value->children->content; + } + + if (strcmp ("artistName", key) == 0) { + artist->name = strdup (valueStr); + } else if (strcmp ("musicId", key) == 0) { + artist->musicId = strdup (valueStr); + } +} + +/* callback for xml struct parser used in PianoXmlParseSearch, "switch" for + * PianoXmlParseSearchArtistCb and XXX + * @author PromyLOPh + * @added 2008-06-12 + */ +void PianoXmlParseSearchCb (char *key, xmlNode *value, void *data) { + PianoSearchResult_t *searchResult = data; + + if (strcmp ("artists", key) == 0) { + xmlNode *curNode; + + /* skip */ + for (curNode = value->children->children; curNode; + curNode = curNode->next) { + if (curNode->type == XML_ELEMENT_NODE && + xmlStrEqual ((xmlChar *) "value", curNode->name)) { + + PianoArtist_t *artist = calloc (1, sizeof (*artist)); + memset (artist, 0, sizeof (*artist)); + + PianoXmlStructParser (curNode->children, + PianoXmlParseSearchArtistCb, artist); + + /* 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; + } + } + } + } else if (strcmp ("songs", key) == 0) { + xmlNode *curNode; + + for (curNode = value->children->children; curNode; + curNode = curNode->next) { + if (curNode->type == XML_ELEMENT_NODE && + xmlStrEqual ((xmlChar *) "value", curNode->name)) { + /* FIXME: copy & waste */ + PianoSong_t *tmpSong = calloc (1, sizeof (*tmpSong)); + PianoXmlStructParser (curNode->children, + PianoXmlParsePlaylistCb, tmpSong); + /* begin linked list or append */ + if (searchResult->songs == NULL) { + searchResult->songs = tmpSong; + } else { + PianoSong_t *curSong = searchResult->songs; + while (curSong->next != NULL) { + curSong = curSong->next; + } + curSong->next = tmpSong; + } + } + } + } +} + +/* parse search result + * @author PromyLOPh + * @added 2008-06-12 + * @param xml document + * @param returns search result + * @return nothing yet + */ +void PianoXmlParseSearch (char *searchXml, + PianoSearchResult_t *searchResult) { + /* FIXME: copy & waste */ + xmlNode *docRoot = NULL, *curNode = NULL; + xmlDocPtr doc = xmlReadDoc ((xmlChar *) searchXml, NULL, NULL, 0); + + if (doc == NULL) { + printf ("whoops... xml parser error\n"); + return; + } + + docRoot = xmlDocGetRootElement (doc); + + xmlNode *structRoot = docRoot->children->children->children->children; + /* we need a "clean" search result (with null pointers) */ + memset (searchResult, 0, sizeof (*searchResult)); + PianoXmlStructParser (structRoot, PianoXmlParseSearchCb, searchResult); + + xmlFreeDoc (doc); + xmlCleanupParser(); +} + /* encode reserved chars * @author PromyLOPh * @added 2008-06-10 -- cgit v1.2.3