summaryrefslogtreecommitdiff
path: root/libpiano/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'libpiano/main.c')
-rw-r--r--libpiano/main.c249
1 files changed, 249 insertions, 0 deletions
diff --git a/libpiano/main.c b/libpiano/main.c
new file mode 100644
index 0000000..185d94c
--- /dev/null
+++ b/libpiano/main.c
@@ -0,0 +1,249 @@
+/*
+Copyright (c) 2008 Lars-Dominik Braun
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include <curl/curl.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "const.h"
+#include "main.h"
+#include "piano.h"
+#include "http.h"
+#include "xml.h"
+
+char *PianoEncryptString (char *strInput);
+
+/* initialize piano handle, set up curl handle and settings
+ * @author PromyLOPh
+ * @added 2008-06-05
+ * @param piano handle
+ * @return nothing
+ */
+void PianoInit (PianoHandle_t *ph) {
+ memset (ph, 0, sizeof (*ph));
+ ph->curlHandle = curl_easy_init ();
+ /* FIXME: 64-bit may make this hack useless */
+ snprintf (ph->routeId, sizeof (ph->routeId), "%07liP", time (NULL)>>8);
+ /* at the moment we don't need publicity */
+ curl_easy_setopt (ph->curlHandle, CURLOPT_USERAGENT, PIANO_USERAGENT);
+ /* set tor as control connection proxy */
+ curl_easy_setopt (ph->curlHandle, CURLOPT_PROXY, "localhost:9050");
+ curl_easy_setopt (ph->curlHandle, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4A);
+}
+
+/* free complete station list
+ * @author PromyLOPh
+ * @added 2008-06-09
+ * @param piano handle
+ */
+void PianoDestroyStations (PianoHandle_t *ph) {
+ PianoStation_t *curStation, *lastStation;
+
+ curStation = ph->stations;
+ while (curStation != NULL) {
+ free (curStation->name);
+ free (curStation->id);
+ lastStation = curStation;
+ curStation = curStation->next;
+ memset (lastStation, 0, sizeof (*lastStation));
+ free (lastStation);
+ }
+}
+
+/* FIXME: copy & waste */
+/* free _all_ elements of playlist
+ * @author PromyLOPh
+ * @added 2008-06-09
+ * @param piano handle
+ * @return nothing
+ */
+void PianoDestroyPlaylist (PianoHandle_t *ph) {
+ PianoSong_t *curSong, *lastSong;
+
+ curSong = ph->playlist;
+ while (curSong != NULL) {
+ free (curSong->audioUrl);
+ free (curSong->artist);
+ free (curSong->focusTraitId);
+ free (curSong->matchingSeed);
+ free (curSong->musicId);
+ free (curSong->title);
+ free (curSong->userSeed);
+ lastSong = curSong;
+ curSong = curSong->next;
+ memset (lastSong, 0, sizeof (*lastSong));
+ free (lastSong);
+ }
+}
+
+/* frees the whole piano handle structure
+ * @author PromyLOPh
+ * @added 2008-06-05
+ * @param piano handle
+ * @return nothing
+ */
+void PianoDestroy (PianoHandle_t *ph) {
+ curl_easy_cleanup (ph->curlHandle);
+ /* FIXME: only free if pointer != NULL */
+ free (ph->user.webAuthToken);
+ free (ph->user.authToken);
+ free (ph->user.listenerId);
+
+ PianoDestroyStations (ph);
+ PianoDestroyPlaylist (ph);
+ memset (ph, 0, sizeof (*ph));
+}
+
+/* authenticates user
+ * @author PromyLOPh
+ * @added 2008-06-05
+ * @param piano handle
+ * @param username (utf-8 encoded)
+ * @param password (plaintext, utf-8 encoded)
+ * @return nothing
+ */
+void PianoConnect (PianoHandle_t *ph, char *user, char *password) {
+ /* sync */
+ char url[PIANO_URL_BUFFER_SIZE];
+ char *requestStr = PianoEncryptString ("<?xml version=\"1.0\"?>"
+ "<methodCall><methodName>misc.sync</methodName>"
+ "<params></params></methodCall>");
+ char *retStr, requestStrPlain[10000];
+
+ /* sync (is the return value used by pandora? for now: ignore result) */
+ snprintf (url, sizeof (url), PIANO_RPC_URL "rid=%s&method=sync",
+ ph->routeId);
+ PianoHttpPost (ph->curlHandle, url, requestStr, &retStr);
+ free (requestStr);
+ free (retStr);
+
+ /* authenticate */
+ snprintf (requestStrPlain, sizeof (requestStrPlain),
+ "<?xml version=\"1.0\"?><methodCall>"
+ "<methodName>listener.authenticateListener</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), user, password);
+ requestStr = PianoEncryptString (requestStrPlain);
+ snprintf (url, sizeof (url), PIANO_SECURE_RPC_URL "rid=%s"
+ "&method=authenticateListener", ph->routeId);
+ PianoHttpPost (ph->curlHandle, url, requestStr, &retStr);
+ PianoXmlParseUserinfo (ph, retStr);
+
+ free (requestStr);
+ free (retStr);
+}
+
+/* get all stations for authenticated user (so: PianoConnect needs to
+ * be run before)
+ * @author PromyLOPh
+ * @added 2008-06-05
+ * @param piano handle filled with some authentication data by PianoConnect
+ * @return nothing
+ */
+void PianoGetStations (PianoHandle_t *ph) {
+ char xmlSendBuf[10000], url[PIANO_URL_BUFFER_SIZE];
+ char *requestStr, *retStr;
+
+ snprintf (xmlSendBuf, sizeof (xmlSendBuf), "<?xml version=\"1.0\"?>"
+ "<methodCall><methodName>station.getStations</methodName>"
+ "<params><param><value><int>%li</int></value></param>"
+ "<param><value><string>%s</string></value></param>"
+ "</params></methodCall>", time (NULL), ph->user.authToken);
+ requestStr = PianoEncryptString (xmlSendBuf);
+ snprintf (url, sizeof (url), PIANO_RPC_URL
+ "rid=%s&lid=%s&method=getStations", ph->routeId,
+ ph->user.listenerId);
+ PianoHttpPost (ph->curlHandle, url, requestStr, &retStr);
+ PianoXmlParseStations (ph, retStr);
+ free (retStr);
+ free (requestStr);
+}
+
+/* get next songs for station (usually four tracks)
+ * @author PromyLOPh
+ * @added 2008-06-05
+ * @param piano handle
+ * @param station id
+ * @return nothing yet
+ */
+void PianoGetPlaylist (PianoHandle_t *ph, char *stationId) {
+ char xmlSendBuf[10000], url[PIANO_URL_BUFFER_SIZE];
+ char *requestStr, *retStr;
+
+ /* FIXME: remove static numbers */
+ snprintf (xmlSendBuf, sizeof (xmlSendBuf), "<?xml version=\"1.0\"?>"
+ "<methodCall><methodName>playlist.getFragment</methodName>"
+ "<params><param><value><int>%li</int></value></param>"
+ "<param><value><string>%s</string></value></param>"
+ "<param><value><string>%s</string></value></param>"
+ "<param><value><string>15941546</string></value></param>"
+ "<param><value><string>181840822</string></value></param>"
+ "<param><value><string></string></value></param>"
+ "<param><value><string></string></value></param>"
+ "<param><value><string>aacplus</string></value></param>"
+ "</params></methodCall>", time (NULL), ph->user.authToken,
+ stationId);
+ requestStr = PianoEncryptString (xmlSendBuf);
+ snprintf (url, sizeof (url), PIANO_RPC_URL
+ "rid=%s&lid=%s&method=getFragment&arg1=%s&arg2=15941546"
+ "&arg3=181840822&arg4=&arg5=&arg6=aacplus", ph->routeId,
+ ph->user.listenerId, stationId);
+ PianoHttpPost (ph->curlHandle, url, requestStr, &retStr);
+ PianoXmlParsePlaylist (ph, retStr);
+ free (retStr);
+ free (requestStr);
+}
+
+void PianoRateTrack (PianoHandle_t *ph, PianoStation_t *station,
+ PianoSong_t *song, PianoSongRating_t rating) {
+ char xmlSendBuf[10000], url[PIANO_URL_BUFFER_SIZE];
+ char *requestStr, *retStr;
+
+ snprintf (xmlSendBuf, sizeof (xmlSendBuf), "<?xml version=\"1.0\"?>"
+ "<methodCall><methodName>station.addFeedback</methodName>"
+ "<params><param><value><int>%li</int></value></param>"
+ "<param><value><string>%s</string></value></param>"
+ "<param><value><string>%s</string></value></param>"
+ "<param><value><string>%s</string></value></param>"
+ "<param><value><string>%s</string></value></param>"
+ "<param><value><string>%s</string></value></param>"
+ "<param><value><string>%s</string></value></param>"
+ "<param><value><boolean>%i</boolean></value></param>"
+ "<param><value><boolean>0</boolean></value></param>"
+ "</params></methodCall>", time (NULL), ph->user.authToken,
+ station->id, song->musicId, song->matchingSeed, song->userSeed,
+ song->focusTraitId, (rating == PIANO_RATE_LOVE) ? 1 : 0);
+ requestStr = PianoEncryptString (xmlSendBuf);
+ snprintf (url, sizeof (url), PIANO_RPC_URL
+ "rid=%s&lid=%s&method=addFeedback&arg1=%s&arg2=%s"
+ "&arg3=%s&arg4=%s&arg5=%s&arg6=%s&arg7=false", ph->routeId,
+ ph->user.listenerId, station->id, song->musicId,
+ song->matchingSeed, song->userSeed, song->focusTraitId,
+ (rating == PIANO_RATE_LOVE) ? "true" : "false");
+ PianoHttpPost (ph->curlHandle, url, requestStr, &retStr);
+ /* FIXME: check answer (success = <?xml version="1.0" encoding="UTF-8"?><methodResponse><params><param><value>1</value></param></params></methodResponse> ) */
+ free (requestStr);
+ free (retStr);
+}