diff options
| -rw-r--r-- | libpiano/main.c | 71 | ||||
| -rw-r--r-- | libpiano/piano.h | 21 | ||||
| -rw-r--r-- | libpiano/xml.c | 114 | 
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  | 
