diff options
author | Lars-Dominik Braun <PromyLOPh@lavabit.com> | 2009-12-15 20:44:40 +0100 |
---|---|---|
committer | Lars-Dominik Braun <PromyLOPh@lavabit.com> | 2009-12-15 20:44:40 +0100 |
commit | d57bf656fd35eff82034dea5072014bffdc92f82 (patch) | |
tree | 502dfbaad544f608fce71d8ba4b122118eee3ea3 /libpiano/src/main.c | |
parent | fac7d0d211ab56d8a1357d7837dae789aa3cbf64 (diff) | |
download | pianobar-windows-d57bf656fd35eff82034dea5072014bffdc92f82.tar.gz pianobar-windows-d57bf656fd35eff82034dea5072014bffdc92f82.tar.bz2 pianobar-windows-d57bf656fd35eff82034dea5072014bffdc92f82.zip |
Rename libraries' main.c files
Diffstat (limited to 'libpiano/src/main.c')
-rw-r--r-- | libpiano/src/main.c | 908 |
1 files changed, 0 insertions, 908 deletions
diff --git a/libpiano/src/main.c b/libpiano/src/main.c deleted file mode 100644 index 2bf8426..0000000 --- a/libpiano/src/main.c +++ /dev/null @@ -1,908 +0,0 @@ -/* -Copyright (c) 2008-2009 - Lars-Dominik Braun <PromyLOPh@lavabit.com> - -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. -*/ - -#define _BSD_SOURCE /* required by strdup() */ - -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <time.h> - -#include "main.h" -#include "piano.h" -#include "http.h" -#include "xml.h" -#include "crypt.h" -#include "config.h" - -#define PIANO_PROTOCOL_VERSION "25" -#define PIANO_RPC_HOST "www.pandora.com" -#define PIANO_RPC_PORT "80" -#define PIANO_RPC_PATH "/radio/xmlrpc/v" PIANO_PROTOCOL_VERSION "?" -#define PIANO_SEND_BUFFER_SIZE 10000 - -/* prototypes */ -static PianoReturn_t PianoAddFeedback (PianoHandle_t *, const char *, const char *, - const char *, const char *, const char *, PianoSongRating_t); -const char *PianoAudioFormatToString (PianoAudioFormat_t); - -/* more "secure" free version - * @param free this pointer - * @param zero n bytes; 0 disables zeroing (for strings with unknown size, - * e.g.) - */ -void PianoFree (void *ptr, size_t size) { - if (ptr != NULL) { - if (size > 0) { - /* avoid reuse of freed memory */ - memset ((char *) ptr, 0, size); - } - free (ptr); - } -} - -/* initialize piano handle - * @param piano handle - * @return nothing - */ -void PianoInit (PianoHandle_t *ph) { - memset (ph, 0, sizeof (*ph)); - - WaitressInit (&ph->waith); - strncpy (ph->waith.host, PIANO_RPC_HOST, sizeof (ph->waith.host)-1); - strncpy (ph->waith.port, PIANO_RPC_PORT, sizeof (ph->waith.port)-1); - - /* route-id seems to be random. we're using time anyway... */ - snprintf (ph->routeId, sizeof (ph->routeId), "%07liP", time (NULL) % 10000000); -} - -/* free complete search result - * @public yes - * @param search result - */ -void PianoDestroySearchResult (PianoSearchResult_t *searchResult) { - PianoArtist_t *curArtist, *lastArtist; - PianoSong_t *curSong, *lastSong; - - curArtist = searchResult->artists; - while (curArtist != NULL) { - PianoFree (curArtist->name, 0); - PianoFree (curArtist->musicId, 0); - lastArtist = curArtist; - curArtist = curArtist->next; - PianoFree (lastArtist, sizeof (*lastArtist)); - } - - curSong = searchResult->songs; - while (curSong != NULL) { - PianoFree (curSong->title, 0); - PianoFree (curSong->artist, 0); - PianoFree (curSong->musicId, 0); - lastSong = curSong; - curSong = curSong->next; - PianoFree (lastSong, sizeof (*lastSong)); - } -} - -/* free single station - * @param station - */ -void PianoDestroyStation (PianoStation_t *station) { - PianoFree (station->name, 0); - PianoFree (station->id, 0); - memset (station, 0, sizeof (station)); -} - -/* free complete station list - * @param piano handle - */ -void PianoDestroyStations (PianoStation_t *stations) { - PianoStation_t *curStation, *lastStation; - - curStation = stations; - while (curStation != NULL) { - lastStation = curStation; - curStation = curStation->next; - PianoDestroyStation (lastStation); - PianoFree (lastStation, sizeof (*lastStation)); - } -} - -/* FIXME: copy & waste */ -/* free _all_ elements of playlist - * @param piano handle - * @return nothing - */ -void PianoDestroyPlaylist (PianoSong_t *playlist) { - PianoSong_t *curSong, *lastSong; - - curSong = playlist; - while (curSong != NULL) { - PianoFree (curSong->audioUrl, 0); - PianoFree (curSong->artist, 0); - PianoFree (curSong->focusTraitId, 0); - PianoFree (curSong->matchingSeed, 0); - PianoFree (curSong->musicId, 0); - PianoFree (curSong->title, 0); - PianoFree (curSong->userSeed, 0); - PianoFree (curSong->identity, 0); - PianoFree (curSong->stationId, 0); - PianoFree (curSong->album, 0); - lastSong = curSong; - curSong = curSong->next; - PianoFree (lastSong, sizeof (*lastSong)); - } -} - -/* frees the whole piano handle structure - * @param piano handle - * @return nothing - */ -void PianoDestroy (PianoHandle_t *ph) { - WaitressFree (&ph->waith); - - PianoFree (ph->user.webAuthToken, 0); - PianoFree (ph->user.authToken, 0); - PianoFree (ph->user.listenerId, 0); - - 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)); - } - memset (ph, 0, sizeof (*ph)); -} - -/* authenticates user - * @param piano handle - * @param username (utf-8 encoded) - * @param password (plaintext, utf-8 encoded) - * @param use ssl when logging in (1 = on, 0 = off), note that the password - * is not hashed and will be sent as plain-text! - */ -PianoReturn_t PianoConnect (PianoHandle_t *ph, const char *user, - const char *password) { - char *retStr, xmlSendBuf[PIANO_SEND_BUFFER_SIZE]; - PianoReturn_t ret; - - /* sync and throw away result (it's an encrypted timestamp, decrypt with - * PianoDecryptString) */ - snprintf (xmlSendBuf, sizeof (xmlSendBuf), "<?xml version=\"1.0\"?>" - "<methodCall><methodName>misc.sync</methodName>" - "<params></params></methodCall>"); - snprintf (ph->waith.path, sizeof (ph->waith.path), PIANO_RPC_PATH - "rid=%s&method=sync", ph->routeId); - ret = PianoHttpPost (&ph->waith, xmlSendBuf, &retStr); - PianoFree (retStr, 0); - - if (ret != PIANO_RET_OK) { - return ret; - } - - /* authenticate */ - snprintf (xmlSendBuf, sizeof (xmlSendBuf), - "<?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); - snprintf (ph->waith.path, sizeof (ph->waith.path), PIANO_RPC_PATH - "rid=%s&method=authenticateListener", ph->routeId); - - if ((ret = PianoHttpPost (&ph->waith, xmlSendBuf, &retStr)) == - PIANO_RET_OK) { - ret = PianoXmlParseUserinfo (ph, retStr); - PianoFree (retStr, 0); - } - - return ret; -} - -/* get all stations for authenticated user (so: PianoConnect needs to - * be run before) - * @param piano handle filled with some authentication data by PianoConnect - */ -PianoReturn_t PianoGetStations (PianoHandle_t *ph) { - char xmlSendBuf[PIANO_SEND_BUFFER_SIZE], *retStr; - PianoReturn_t ret; - - 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); - snprintf (ph->waith.path, sizeof (ph->waith.path), PIANO_RPC_PATH - "rid=%s&lid=%s&method=getStations", ph->routeId, - ph->user.listenerId); - - if ((ret = PianoHttpPost (&ph->waith, xmlSendBuf, &retStr)) == - PIANO_RET_OK) { - ret = PianoXmlParseStations (ph, retStr); - PianoFree (retStr, 0); - } - - return ret; -} - -/* get next songs for station (usually four tracks) - * @param piano handle - * @param station id - * @param audio format - * @param return value: playlist - */ -PianoReturn_t PianoGetPlaylist (PianoHandle_t *ph, const char *stationId, - PianoAudioFormat_t format, PianoSong_t **retPlaylist) { - char xmlSendBuf[PIANO_SEND_BUFFER_SIZE], *retStr; - PianoReturn_t ret; - - /* FIXME: remove static, "magic" 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>0</string></value></param>" - "<param><value><string></string></value></param>" - "<param><value><string></string></value></param>" - "<param><value><string>%s</string></value></param>" - "<param><value><string>0</string></value></param>" - "<param><value><string>0</string></value></param>" - "</params></methodCall>", time (NULL), ph->user.authToken, - stationId, PianoAudioFormatToString (format)); - snprintf (ph->waith.path, sizeof (ph->waith.path), PIANO_RPC_PATH - "rid=%s&lid=%s&method=getFragment&arg1=%s&arg2=0" - "&arg3=&arg4=&arg5=%s&arg6=0&arg7=0", ph->routeId, - ph->user.listenerId, stationId, - PianoAudioFormatToString (format)); - - if ((ret = PianoHttpPost (&ph->waith, xmlSendBuf, &retStr)) == - PIANO_RET_OK) { - ret = PianoXmlParsePlaylist (ph, retStr, retPlaylist); - PianoFree (retStr, 0); - } - - return ret; -} - -/* love or ban track (you cannot remove your rating, so PIANO_RATE_NONE is - * not allowed) - * @public yes - * @param piano handle - * @param rate this track - * @param your rating - */ -PianoReturn_t PianoRateTrack (PianoHandle_t *ph, PianoSong_t *song, - PianoSongRating_t rating) { - PianoReturn_t ret; - - ret = PianoAddFeedback (ph, song->stationId, song->musicId, - song->matchingSeed, song->userSeed, song->focusTraitId, rating); - - if (ret == PIANO_RET_OK) { - song->rating = rating; - } - - return ret; -} - -/* move song to another station - * @param piano handle - * @param move from - * @param move here - * @param song to move - */ -PianoReturn_t PianoMoveSong (PianoHandle_t *ph, - const PianoStation_t *stationFrom, const PianoStation_t *stationTo, - const PianoSong_t *song) { - PianoReturn_t ret; - - /* ban from current station */ - if ((ret = PianoAddFeedback (ph, stationFrom->id, song->musicId, "", "", - "", PIANO_RATE_BAN)) == PIANO_RET_OK) { - /* love at new station */ - return PianoAddFeedback (ph, stationTo->id, song->musicId, "", - "", "", PIANO_RATE_LOVE); - } - return ret; -} - -/* add feedback - * @param piano handle - * @param station id - * @param song id - * @param song matching seed or NULL - * @param song user seed or NULL - * @param song focus trait id or NULL - * @param rating - */ -static PianoReturn_t PianoAddFeedback (PianoHandle_t *ph, const char *stationId, - const char *songMusicId, const char *songMatchingSeed, - const char *songUserSeed, const char *songFocusTraitId, - PianoSongRating_t rating) { - char xmlSendBuf[PIANO_SEND_BUFFER_SIZE], *retStr; - PianoReturn_t ret = PIANO_RET_ERR; - - 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></value></param>" - "<param><value><boolean>%i</boolean></value></param>" - "<param><value><boolean>0</boolean></value></param>" - "</params></methodCall>", time (NULL), ph->user.authToken, - stationId, songMusicId, - (songMatchingSeed == NULL) ? "" : songMatchingSeed, - (songUserSeed == NULL) ? "" : songUserSeed, - (songFocusTraitId == NULL) ? "" : songFocusTraitId, - (rating == PIANO_RATE_LOVE) ? 1 : 0); - snprintf (ph->waith.path, sizeof (ph->waith.path), PIANO_RPC_PATH - "rid=%s&lid=%s&method=addFeedback&arg1=%s&arg2=%s" - "&arg3=%s&arg4=%s&arg5=%s&arg6=&arg7=%s&arg8=false", ph->routeId, - ph->user.listenerId, stationId, songMusicId, - (songMatchingSeed == NULL) ? "" : songMatchingSeed, - (songUserSeed == NULL) ? "" : songUserSeed, - (songFocusTraitId == NULL) ? "" : songFocusTraitId, - (rating == PIANO_RATE_LOVE) ? "true" : "false"); - - if ((ret = PianoHttpPost (&ph->waith, xmlSendBuf, &retStr)) == - PIANO_RET_OK) { - ret = PianoXmlParseSimple (retStr); - PianoFree (retStr, 0); - } - - return ret; -} - -/* rename station (on the server and local) - * @public yes - * @param piano handle - * @param change this stations name - * @param new name - * @return - */ -PianoReturn_t PianoRenameStation (PianoHandle_t *ph, PianoStation_t *station, - const char *newName) { - char xmlSendBuf[PIANO_SEND_BUFFER_SIZE], *retStr; - char *urlencodedNewName, *xmlencodedNewName; - PianoReturn_t ret = PIANO_RET_ERR; - - if ((xmlencodedNewName = PianoXmlEncodeString (newName)) == NULL) { - return PIANO_RET_OUT_OF_MEMORY; - } - - snprintf (xmlSendBuf, sizeof (xmlSendBuf), "<?xml version=\"1.0\"?>" - "<methodCall><methodName>station.setStationName</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>" - "</params></methodCall>", time (NULL), ph->user.authToken, - station->id, xmlencodedNewName); - - urlencodedNewName = WaitressUrlEncode (newName); - snprintf (ph->waith.path, sizeof (ph->waith.path), PIANO_RPC_PATH - "rid=%s&lid=%s&method=setStationName&arg1=%s&arg2=%s", - ph->routeId, ph->user.listenerId, station->id, urlencodedNewName); - - if ((ret = PianoHttpPost (&ph->waith, xmlSendBuf, &retStr)) == - PIANO_RET_OK) { - if ((ret = PianoXmlParseSimple (retStr)) == PIANO_RET_OK) { - PianoFree (station->name, 0); - station->name = strdup (newName); - } - PianoFree (retStr, 0); - } - - PianoFree (urlencodedNewName, 0); - PianoFree (xmlencodedNewName, 0); - - return ret; -} - -/* delete station - * @public yes - * @param piano handle - * @param station you want to delete - */ -PianoReturn_t PianoDeleteStation (PianoHandle_t *ph, PianoStation_t *station) { - char xmlSendBuf[PIANO_SEND_BUFFER_SIZE], *retStr; - PianoReturn_t ret = PIANO_RET_ERR; - - snprintf (xmlSendBuf, sizeof (xmlSendBuf), "<?xml version=\"1.0\"?>" - "<methodCall><methodName>station.removeStation</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, - station->id); - - snprintf (ph->waith.path, sizeof (ph->waith.path), PIANO_RPC_PATH - "rid=%s&lid=%s&method=removeStation&arg1=%s", ph->routeId, - ph->user.listenerId, station->id); - if ((ret = PianoHttpPost (&ph->waith, xmlSendBuf, &retStr)) == - PIANO_RET_OK) { - if ((ret = PianoXmlParseSimple (retStr)) == PIANO_RET_OK) { - /* delete station from local station list */ - PianoStation_t *curStation = ph->stations, *lastStation = NULL; - while (curStation != NULL) { - if (curStation == station) { - if (lastStation != NULL) { - lastStation->next = curStation->next; - } else { - /* first station in list */ - ph->stations = curStation->next; - } - PianoDestroyStation (curStation); - PianoFree (curStation, sizeof (*curStation)); - break; - } - lastStation = curStation; - curStation = curStation->next; - } - } - } - - return ret; -} - -/* search for music (artist or track), needed to create new station; don't - * forget to free the search result; beware! searchResult will be nulled - * by PianoXmlParseSearch - * @public yes - * @param piano handle - * @param utf-8 search string - * @param return search result - */ -PianoReturn_t PianoSearchMusic (PianoHandle_t *ph, - const char *searchStr, PianoSearchResult_t *searchResult) { - char xmlSendBuf[PIANO_SEND_BUFFER_SIZE], *retStr; - char *xmlencodedSearchStr, *urlencodedSearchStr; - PianoReturn_t ret; - - if ((xmlencodedSearchStr = PianoXmlEncodeString (searchStr)) == NULL) { - return PIANO_RET_OUT_OF_MEMORY; - } - - 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); - - urlencodedSearchStr = WaitressUrlEncode (searchStr); - snprintf (ph->waith.path, sizeof (ph->waith.path), PIANO_RPC_PATH - "rid=%s&lid=%s&method=search&arg1=%s", ph->routeId, - ph->user.listenerId, urlencodedSearchStr); - - if ((ret = PianoHttpPost (&ph->waith, xmlSendBuf, &retStr)) == - PIANO_RET_OK) { - ret = PianoXmlParseSearch (retStr, searchResult); - PianoFree (retStr, 0); - } - - PianoFree (urlencodedSearchStr, 0); - PianoFree (xmlencodedSearchStr, 0); - - return ret; -} - -/* create new station on server - * @public yes - * @param piano handle - * @param type: "mi" for music id (from music search) or "sh" for - * shared station - * @param id - */ -PianoReturn_t PianoCreateStation (PianoHandle_t *ph, const char *type, - const char *id) { - char xmlSendBuf[PIANO_SEND_BUFFER_SIZE], *retStr; - PianoReturn_t ret; - - snprintf (xmlSendBuf, sizeof (xmlSendBuf), "<?xml version=\"1.0\"?>" - "<methodCall><methodName>station.createStation</methodName>" - "<params><param><value><int>%li</int></value></param>" - "<param><value><string>%s</string></value></param>" - "<param><value><string>%s%s</string></value></param>" - "</params></methodCall>", time (NULL), ph->user.authToken, - type, id); - - snprintf (ph->waith.path, sizeof (ph->waith.path), PIANO_RPC_PATH - "rid=%s&lid=%s&method=createStation&arg1=%s%s", ph->routeId, - ph->user.listenerId, type, id); - - if ((ret = PianoHttpPost (&ph->waith, xmlSendBuf, &retStr)) == - PIANO_RET_OK) { - ret = PianoXmlParseCreateStation (ph, retStr); - PianoFree (retStr, 0); - } - - return ret; -} - -/* FIXME: update station data instead of replacing them */ -/* add more music to existing station; multithreaded apps beware! this alters - * station data, don't forget to lock the station pointer you passed to this - * function - * @public yes - * @param piano handle - * @param add music to this station - * @param music id; can be obtained with PianoSearchMusic () - */ -PianoReturn_t PianoStationAddMusic (PianoHandle_t *ph, - PianoStation_t *station, const char *musicId) { - char xmlSendBuf[PIANO_SEND_BUFFER_SIZE], *retStr; - PianoReturn_t ret; - - snprintf (xmlSendBuf, sizeof (xmlSendBuf), "<?xml version=\"1.0\"?>" - "<methodCall><methodName>station.addSeed</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>" - "</params></methodCall>", time (NULL), ph->user.authToken, - station->id, musicId); - - snprintf (ph->waith.path, sizeof (ph->waith.path), PIANO_RPC_PATH - "rid=%s&lid=%s&method=addSeed&arg1=%s&arg2=%s", ph->routeId, - ph->user.listenerId, station->id, musicId); - - if ((ret = PianoHttpPost (&ph->waith, xmlSendBuf, &retStr)) == - PIANO_RET_OK) { - ret = PianoXmlParseAddSeed (ph, retStr, station); - PianoFree (retStr, 0); - } - - return ret; -} - -/* ban a song temporary (for one month) - * @param piano handle - * @param song to be banned - * @return _OK or error - */ -PianoReturn_t PianoSongTired (PianoHandle_t *ph, const PianoSong_t *song) { - char xmlSendBuf[PIANO_SEND_BUFFER_SIZE], *retStr; - PianoReturn_t ret; - - snprintf (xmlSendBuf, sizeof (xmlSendBuf), "<?xml version=\"1.0\"?>" - "<methodCall><methodName>listener.addTiredSong</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, - song->identity); - - snprintf (ph->waith.path, sizeof (ph->waith.path), PIANO_RPC_PATH - "rid=%s&lid=%s&method=addTiredSong&arg1=%s", ph->routeId, - ph->user.listenerId, song->identity); - - if ((ret = PianoHttpPost (&ph->waith, xmlSendBuf, &retStr)) == - PIANO_RET_OK) { - ret = PianoXmlParseSimple (retStr); - PianoFree (retStr, 0); - } - - return ret; -} - -/* set stations use by quickmix - * @param piano handle - * @return _OK or error - */ -PianoReturn_t PianoSetQuickmix (PianoHandle_t *ph) { - char xmlSendBuf[PIANO_SEND_BUFFER_SIZE], valueBuf[1000], urlArgBuf[1000], - *retStr; - PianoReturn_t ret; - PianoStation_t *curStation = ph->stations; - - memset (urlArgBuf, 0, sizeof (urlArgBuf)); - snprintf (xmlSendBuf, sizeof (xmlSendBuf), "<?xml version=\"1.0\"?>" - "<methodCall><methodName>station.setQuickMix</methodName><params>" - "<param><value><int>%li</int></value></param>" - "<param><value><string>%s</string></value></param>" - "<param><value><string>RANDOM</string></value></param>" - "<param><value><array><data>", time (NULL), ph->user.authToken); - while (curStation != NULL) { - /* quick mix can't contain itself */ - if (!curStation->useQuickMix || curStation->isQuickMix) { - curStation = curStation->next; - continue; - } - /* append to xml doc */ - snprintf (valueBuf, sizeof (valueBuf), - "<value><string>%s</string></value>", curStation->id); - strncat (xmlSendBuf, valueBuf, sizeof (xmlSendBuf) - - strlen (xmlSendBuf) - 1); - /* append to url arg */ - strncat (urlArgBuf, curStation->id, sizeof (urlArgBuf) - - strlen (urlArgBuf) - 1); - curStation = curStation->next; - /* if not last item: append "," */ - if (curStation != NULL) { - strncat (urlArgBuf, "%2C", sizeof (urlArgBuf) - - strlen (urlArgBuf) - 1); - } - } - strncat (xmlSendBuf, - "</data></array></value></param></params></methodCall>", - sizeof (xmlSendBuf) - strlen (xmlSendBuf) - 1); - - snprintf (ph->waith.path, sizeof (ph->waith.path), PIANO_RPC_PATH - "rid=%s&lid=%s&method=setQuickMix&arg1=RANDOM&arg2=%s", - ph->routeId, ph->user.listenerId, urlArgBuf); - - if ((ret = PianoHttpPost (&ph->waith, xmlSendBuf, &retStr)) == - PIANO_RET_OK) { - ret = PianoXmlParseSimple (retStr); - PianoFree (retStr, 0); - } - - return ret; -} - -/* get station from list by id - * @param search here - * @param search for this - * @return the first station structure matching the given id - */ -PianoStation_t *PianoFindStationById (PianoStation_t *stations, - const char *searchStation) { - while (stations != NULL) { - if (strcmp (stations->id, searchStation) == 0) { - return stations; - } - stations = stations->next; - } - return NULL; -} - -/* receive genre stations - * @param piano handle - * @return _OK or error - */ -PianoReturn_t PianoGetGenreStations (PianoHandle_t *ph) { - char *retStr; - PianoReturn_t ret; - - snprintf (ph->waith.path, sizeof (ph->waith.path), "/xml/genre?r=%li", - time (NULL)); - - if ((ret = PianoHttpGet (&ph->waith, &retStr)) == - PIANO_RET_OK) { - ret = PianoXmlParseGenreExplorer (ph, retStr); - PianoFree (retStr, 0); - } - - return ret; -} - -/* make shared stations private, needed to rate songs played on shared - * stations - * @param piano handle - * @param station to transform - * @return _OK or error - */ -PianoReturn_t PianoTransformShared (PianoHandle_t *ph, - PianoStation_t *station) { - char xmlSendBuf[PIANO_SEND_BUFFER_SIZE], *retStr; - PianoReturn_t ret; - - snprintf (xmlSendBuf, sizeof (xmlSendBuf), "<?xml version=\"1.0\"?>" - "<methodCall><methodName>station.transformShared</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, - station->id); - - snprintf (ph->waith.path, sizeof (ph->waith.path), PIANO_RPC_PATH - "rid=%s&lid=%s&method=transformShared&arg1=%s", ph->routeId, - ph->user.listenerId, station->id); - - if ((ret = PianoHttpPost (&ph->waith, xmlSendBuf, &retStr)) == - PIANO_RET_OK) { - ret = PianoXmlParseTranformStation (retStr); - /* though this call returns a bunch of "new" data only this one is - * changed and important (at the moment) */ - if (ret == PIANO_RET_OK) { - station->isCreator = 1; - } - PianoFree (retStr, 0); - } - - return ret; -} - -/* "why dit you play this song?" - * @param piano handle - * @param song (from playlist) - * @param return allocated string; you have to free it yourself - * @return _OK or error - */ -PianoReturn_t PianoExplain (PianoHandle_t *ph, const PianoSong_t *song, - char **retExplain) { - char xmlSendBuf[PIANO_SEND_BUFFER_SIZE], *retStr; - PianoReturn_t ret; - - snprintf (xmlSendBuf, sizeof (xmlSendBuf), "<?xml version=\"1.0\"?>" - "<methodCall><methodName>playlist.narrative</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>" - "</params></methodCall>", time (NULL), ph->user.authToken, - song->stationId, song->musicId); - - snprintf (ph->waith.path, sizeof (ph->waith.path), PIANO_RPC_PATH - "rid=%s&lid=%s&method=method=narrative&arg1=%s&arg2=%s", - ph->routeId, ph->user.listenerId, song->stationId, song->musicId); - - if ((ret = PianoHttpPost (&ph->waith, xmlSendBuf, &retStr)) == - PIANO_RET_OK) { - ret = PianoXmlParseNarrative (retStr, retExplain); - PianoFree (retStr, 0); - } - - return ret; -} - -/* Get seed suggestions by music id - * @param piano handle - * @param music id - * @param max results - * @param result buffer - */ -PianoReturn_t PianoSeedSuggestions (PianoHandle_t *ph, const char *musicId, - unsigned int max, PianoSearchResult_t *searchResult) { - char xmlSendBuf[PIANO_SEND_BUFFER_SIZE], *retStr; - PianoReturn_t ret; - - snprintf (xmlSendBuf, sizeof (xmlSendBuf), "<?xml version=\"1.0\"?>" - "<methodCall><methodName>music.getSeedSuggestions</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><int>%u</int></value></param>" - "</params></methodCall>", time (NULL), ph->user.authToken, - musicId, max); - - snprintf (ph->waith.path, sizeof (ph->waith.path), PIANO_RPC_PATH - "rid=%s&lid=%s&method=method=getSeedSuggestions&arg1=%s&arg2=%u", - ph->routeId, ph->user.listenerId, musicId, max); - - if ((ret = PianoHttpPost (&ph->waith, xmlSendBuf, &retStr)) == - PIANO_RET_OK) { - ret = PianoXmlParseSeedSuggestions (retStr, searchResult); - PianoFree (retStr, 0); - } - - return ret; -} - -/* convert return value to human-readable string - * @param enum - * @return error string - */ -const char *PianoErrorToStr (PianoReturn_t ret) { - switch (ret) { - case PIANO_RET_OK: - return "Everything is fine :)"; - break; - - case PIANO_RET_ERR: - return "Unknown."; - break; - - case PIANO_RET_XML_INVALID: - return "Invalid XML."; - break; - - case PIANO_RET_AUTH_TOKEN_INVALID: - return "Invalid auth token."; - break; - - case PIANO_RET_AUTH_USER_PASSWORD_INVALID: - return "Username and/or password not correct."; - break; - - case PIANO_RET_NET_ERROR: - return "Connection failed."; - break; - - case PIANO_RET_NOT_AUTHORIZED: - return "Not authorized."; - break; - - case PIANO_RET_PROTOCOL_INCOMPATIBLE: - return "Protocol incompatible. Please upgrade " PACKAGE "."; - break; - - case PIANO_RET_READONLY_MODE: - return "Request cannot be completed at this time, please try " - "again later."; - break; - - case PIANO_RET_STATION_CODE_INVALID: - return "Station id is invalid."; - break; - - case PIANO_RET_IP_REJECTED: - return "Your ip address was rejected. Please setup a control " - "proxy (see manpage)."; - break; - - case PIANO_RET_STATION_NONEXISTENT: - return "Station does not exist."; - break; - - case PIANO_RET_OUT_OF_MEMORY: - return "Out of memory."; - break; - - case PIANO_RET_OUT_OF_SYNC: - return "Out of sync. Please correct your system's time."; - break; - - default: - return "No error message available."; - break; - } -} - -/* convert audio format id to string that can be used in xml requests - * @param format id - * @return constant string - */ -const char *PianoAudioFormatToString (PianoAudioFormat_t format) { - switch (format) { - case PIANO_AF_AACPLUS: - return "aacplus"; - break; - - case PIANO_AF_MP3: - return "mp3"; - break; - - case PIANO_AF_MP3_HI: - return "mp3-hifi"; - break; - - default: - return NULL; - break; - } -} - |