summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars-Dominik Braun <PromyLOPh@gmail.com>2008-06-12 13:11:41 +0200
committerLars-Dominik Braun <PromyLOPh@gmail.com>2008-06-12 13:11:41 +0200
commite721307fa51241247e73ae2096b6b160671dbeb4 (patch)
tree0e4637062e464f0e05eecb070a8b35d3ba80b3b1
parent31ff2f7dfd0b6eb98cb90d44d87044321def0f7a (diff)
downloadpianobar-e721307fa51241247e73ae2096b6b160671dbeb4.tar.gz
pianobar-e721307fa51241247e73ae2096b6b160671dbeb4.tar.bz2
pianobar-e721307fa51241247e73ae2096b6b160671dbeb4.zip
lib: Initial music search implementation
-rw-r--r--libpiano/main.c71
-rw-r--r--libpiano/piano.h21
-rw-r--r--libpiano/xml.c114
3 files changed, 206 insertions, 0 deletions
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), "<?xml version=\"1.0\"?>"
+ "<methodCall><methodName>music.search</methodName>"
+ "<params><param><value><int>%li</int></value></param>"
+ "<param><value><string>%s</string></value></param>"
+ "<param><value><string>%s</string></value></param>"
+ "</params></methodCall>", 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 <boolean> or <string>, 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 <value><array><data> */
+ 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