/* 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; }
/* prepare piano request (initializes request type, urlpath and postData) * @param piano handle * @param request structure * @param request type */ PianoReturn_t PianoRequest (PianoHandle_t *ph, PianoRequest_t *req, PianoRequestType_t type) { char xmlSendBuf[PIANO_SEND_BUFFER_SIZE]; /* corrected timestamp */ time_t timestamp = time (NULL) - ph->timeOffset; assert (ph != NULL); assert (req != NULL); req->type = type; switch (req->type) { case PIANO_REQUEST_LOGIN: { /* authenticate user */ PianoRequestDataLogin_t *logindata = req->data; assert (logindata != NULL); switch (logindata->step) { case 0: snprintf (xmlSendBuf, sizeof (xmlSendBuf), "<?xml version=\"1.0\"?><methodCall>" "<methodName>misc.sync</methodName>" "<params></params></methodCall>"); snprintf (req->urlPath, sizeof (req->urlPath), PIANO_RPC_PATH "rid=%s&method=sync", ph->routeId); break; case 1: { char *xmlencodedPassword = NULL; /* username == email address does not contain &,<,>," */ if ((xmlencodedPassword = PianoXmlEncodeString (logindata->password)) == NULL) { return PIANO_RET_OUT_OF_MEMORY; } snprintf (xmlSendBuf, sizeof (xmlSendBuf), "<?xml version=\"1.0\"?><methodCall>" "<methodName>listener.authenticateListener</methodName>" "<params><param><value><int>%lu</int></value></param>" /* user */ "<param><value><string>%s</string></value></param>" /* password */ "<param><value><string>%s</string></value></param>" /* vendor */ "<param><value><string>html5tuner</string></value></param>" "<param><value><string/></value></param>" "<param><value><string/></value></param>" "<param><value><string>HTML5</string></value></param>" "<param><value><boolean>1</boolean></value></param>" "</params></methodCall>", (unsigned long) timestamp, logindata->user, xmlencodedPassword); snprintf (req->urlPath, sizeof (req->urlPath), PIANO_RPC_PATH "rid=%s&method=authenticateListener", ph->routeId); free (xmlencodedPassword); break; } } break; } case PIANO_REQUEST_GET_STATIONS: /* get stations, user must be authenticated */ assert (ph->user.listenerId != NULL); snprintf (xmlSendBuf, sizeof (xmlSendBuf), "<?xml version=\"1.0\"?>" "<methodCall><methodName>station.getStations</methodName>" "<params><param><value><int>%lu</int></value></param>" "<param><value><string>%s</string></value></param>" "</params></methodCall>", (unsigned long) timestamp, ph->user.authToken); snprintf (req->urlPath, sizeof (req->urlPath), PIANO_RPC_PATH "rid=%s&lid=%s&method=getStations", ph->routeId, ph->user.listenerId); break; case PIANO_REQUEST_GET_PLAYLIST: { /* get playlist for specified station */ PianoRequestDataGetPlaylist_t *reqData = req->data; assert (reqData != NULL); assert (reqData->station != NULL); assert (reqData->station->id != NULL); assert (reqData->format != PIANO_AF_UNKNOWN); snprintf (xmlSendBuf, sizeof (xmlSendBuf), "<?xml version=\"1.0\"?>" "<methodCall><methodName>playlist.getFragment</methodName>" "<params><param><value><int>%lu</int></value></param>" /* auth token */ "<param><value><string>%s</string></value></param>" /* station id */ "<param><value><string>%s</string></value></param>" /* total listening time */ "<param><value><string>0</string></value></param>" /* time since last session */ "<param><value><string></string></value></param>" /* tracking code */ "<param><value><string></string></value></param>" /* audio format */ "<param><value><string>%s</string></value></param>" /* delta listening time */ "<param><value><string>0</string></value></param>" /* listening timestamp */ "<param><value><string>0</string></value></param>" "</params></methodCall>", (unsigned long) timestamp, ph->user.authToken, reqData->station->id, PianoAudioFormatToString (reqData->format)); snprintf (req->urlPath, sizeof (req->urlPath), 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, reqData->station->id, PianoAudioFormatToString (reqData->format)); break; } case PIANO_REQUEST_ADD_FEEDBACK: { /* low-level, don't use directly (see _RATE_SONG and _MOVE_SONG) */ PianoRequestDataAddFeedback_t *reqData = req->data; assert (reqData != NULL); assert (reqData->stationId != NULL); assert (reqData->rating != PIANO_RATE_NONE); snprintf (xmlSendBuf, sizeof (xmlSendBuf), "<?xml version=\"1.0\"?>" "<methodCall><methodName>station.addFeedback</methodName>" "<params><param><value><int>%lu</int></value></param>" /* auth token */ "<param><value><string>%s</string></value></param>" /* station id */ "<param><value><string>%s</string></value></param>" /* track token */ "<param><value><string>%s</string></value></param>" /* positive */ "<param><value><boolean>%i</boolean></value></param>" "</params></methodCall>", (unsigned long) timestamp, ph->user.authToken, reqData->stationId, reqData->trackToken, (reqData->rating == PIANO_RATE_LOVE) ? 1 : 0); snprintf (req->urlPath, sizeof (req->urlPath), PIANO_RPC_PATH "rid=%s&lid=%s&method=addFeedback&arg1=%s&arg2=%s" "&arg3=%s", ph->routeId, ph->user.listenerId, reqData->stationId, reqData->trackToken, (reqData->rating == PIANO_RATE_LOVE) ? "true" : "false"); break; } case PIANO_REQUEST_RENAME_STATION: { /* rename stations */ PianoRequestDataRenameStation_t *reqData = req->data; char *urlencodedNewName, *xmlencodedNewName; assert (reqData != NULL); assert (reqData->station != NULL); assert (reqData->newName != NULL); if ((xmlencodedNewName = PianoXmlEncodeString (reqData->newName)) == NULL) { return PIANO_RET_OUT_OF_MEMORY; } urlencodedNewName = WaitressUrlEncode (reqData->newName); snprintf (xmlSendBuf, sizeof (xmlSendBuf), "<?xml version=\"1.0\"?>" "<methodCall><methodName>station.setStationName</methodName>" "<params><param><value><int>%lu</int></value></param>" /* auth token */ "<param><value><string>%s</string></value></param>" /* station id */ "<param><value><string>%s</string></value></param>" /* new name */ "<param><value><string>%s</string></value></param>" "</params></methodCall>", (unsigned long) timestamp, ph->user.authToken, reqData->station->id, xmlencodedNewName); snprintf (req->urlPath, sizeof (req->urlPath), PIANO_RPC_PATH "rid=%s&lid=%s&method=setStationName&arg1=%s&arg2=%s", ph->routeId, ph->user.listenerId, reqData->station->id, urlencodedNewName); free (urlencodedNewName); free (xmlencodedNewName); break; } case PIANO_REQUEST_DELETE_STATION: { /* delete station */ PianoStation_t *station = req->data; assert (station != NULL); snprintf (xmlSendBuf, sizeof (xmlSendBuf), "<?xml version=\"1.0\"?>" "<methodCall><methodName>station.removeStation</methodName>" "<params><param><value><int>%lu</int></value></param>" /* auth token */ "<param><value><string>%s</string></value></param>" /* station id */ "<param><value><string>%s</string></value></param>" "</params></methodCall>", (unsigned long) timestamp, ph->user.authToken, station->id); snprintf (req->urlPath, sizeof (req->urlPath), PIANO_RPC_PATH "rid=%s&lid=%s&method=removeStation&arg1=%s", ph->routeId, ph->user.listenerId, station->id); break; } case PIANO_REQUEST_SEARCH: { /* search for artist/song title */ PianoRequestDataSearch_t *reqData = req->data; char *xmlencodedSearchStr, *urlencodedSearchStr; assert (reqData != NULL); assert (reqData->searchStr != NULL); if ((xmlencodedSearchStr = PianoXmlEncodeString (reqData->searchStr)) == NULL) { return PIANO_RET_OUT_OF_MEMORY; } urlencodedSearchStr = WaitressUrlEncode (reqData->searchStr); snprintf (xmlSendBuf, sizeof (xmlSendBuf), "<?xml version=\"1.0\"?>" "<methodCall><methodName>music.search</methodName>" "<params><param><value><int>%lu</int></value></param>" /* auth token */ "<param><value><string>%s</string></value></param>" /* search string */ "<param><value><string>%s</string></value></param>" "</params></methodCall>", (unsigned long) timestamp, ph->user.authToken, xmlencodedSearchStr); snprintf (req->urlPath, sizeof (req->urlPath), PIANO_RPC_PATH "rid=%s&lid=%s&method=search&arg1=%s", ph->routeId, ph->user.listenerId, urlencodedSearchStr); free (urlencodedSearchStr); free (xmlencodedSearchStr); break; } case PIANO_REQUEST_CREATE_STATION: { /* create new station from specified musicid (type=mi, get one by * performing a search) or shared station id (type=sh) */ PianoRequestDataCreateStation_t *reqData = req->data; assert (reqData != NULL); assert (reqData->id != NULL); assert (reqData->type != NULL); snprintf (xmlSendBuf, sizeof (xmlSendBuf), "<?xml version=\"1.0\"?>" "<methodCall><methodName>station.createStation</methodName>" "<params><param><value><int>%lu</int></value></param>" /* auth token */ "<param><value><string>%s</string></value></param>" /* music id */ "<param><value><string>%s%s</string></value></param>" /* empty */ "<param><value><string></string></value></param>" "</params></methodCall>", (unsigned long) timestamp, ph->user.authToken, reqData->type, reqData->id); snprintf (req->urlPath, sizeof (req->urlPath), PIANO_RPC_PATH "rid=%s&lid=%s&method=createStation&arg1=%s%s&arg2=", ph->routeId, ph->user.listenerId, reqData->type, reqData->id); break; } case PIANO_REQUEST_ADD_SEED: { /* add another seed to specified station */ PianoRequestDataAddSeed_t *reqData = req->data; assert (reqData != NULL); assert (reqData->station != NULL); assert (reqData->musicId != NULL); snprintf (xmlSendBuf, sizeof (xmlSendBuf), "<?xml version=\"1.0\"?>" "<methodCall><methodName>station.addSeed</methodName><params>" "<param><value><int>%lu</int></value></param>" /* auth token */ "<param><value><string>%s</string></value></param>" /* station id */ "<param><value><string>%s</string></value></param>" /* music id */ "<param><value><string>%s</string></value></param>" "</params></methodCall>", (unsigned long) timestamp, ph->user.authToken, reqData->station->id, reqData->musicId); snprintf (req->urlPath, sizeof (req->urlPath), PIANO_RPC_PATH "rid=%s&lid=%s&method=addSeed&arg1=%s&arg2=%s", ph->routeId, ph->user.listenerId, reqData->station->id, reqData->musicId); break; } case PIANO_REQUEST_ADD_TIRED_SONG: { /* ban song for a month from all stations */ PianoSong_t *song = req->data; assert (song != NULL); snprintf (xmlSendBuf, sizeof (xmlSendBuf), "<?xml version=\"1.0\"?>" "<methodCall><methodName>listener.addTiredSong</methodName><params>" "<param><value><int>%lu</int></value></param>" "<param><value><string>%s</string></value></param>" /* key */ "<param><value><string>%s</string></value></param>" /* user seed */ "<param><value><string>%s</string></value></param>" /* station id */ "<param><value><string>%s</string></value></param>" "</params></methodCall>", (unsigned long) timestamp, ph->user.authToken, (song->musicId == NULL) ? "" : song->musicId, (song->userSeed == NULL) ? "" : song->userSeed, song->stationId); snprintf (req->urlPath, sizeof (req->urlPath), PIANO_RPC_PATH "rid=%s&lid=%s&method=addTiredSong&arg1=%s&arg2=%s&arg3=%s", ph->routeId, ph->user.listenerId, (song->musicId == NULL) ? "" : song->musicId, (song->userSeed == NULL) ? "" : song->userSeed, song->stationId); break; } case PIANO_REQUEST_SET_QUICKMIX: { /* select stations included in quickmix (see useQuickMix flag of * PianoStation_t) */ char valueBuf[1000], urlArgBuf[1000]; 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>%lu</int></value></param>" "<param><value><string>%s</string></value></param>" /* quick mix type */ "<param><value><string>RANDOM</string></value></param>" "<param><value><array><data>", (unsigned long) timestamp, 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>" /* empty */ "<param><value><string></string></value></param>" /* empty */ "<param><value><string></string></value></param>" "</params></methodCall>", sizeof (xmlSendBuf) - strlen (xmlSendBuf) - 1); snprintf (req->urlPath, sizeof (req->urlPath), PIANO_RPC_PATH "rid=%s&lid=%s&method=setQuickMix&arg1=RANDOM&arg2=%s&arg3=&arg4=", ph->routeId, ph->user.listenerId, urlArgBuf); break; } case PIANO_REQUEST_GET_GENRE_STATIONS: /* receive list of pandora's genre stations */ xmlSendBuf[0] = '\0'; snprintf (req->urlPath, sizeof (req->urlPath), "/xml/genre?r=%lu", (unsigned long) timestamp); break; case PIANO_REQUEST_TRANSFORM_STATION: { /* transform shared station into private */ PianoStation_t *station = req->data; assert (station != NULL); snprintf (xmlSendBuf, sizeof (xmlSendBuf), "<?xml version=\"1.0\"?>" "<methodCall><methodName>station.transformShared</methodName>" "<params><param><value><int>%lu</int></value></param>" /* auth token */ "<param><value><string>%s</string></value></param>" /* station id */ "<param><value><string>%s</string></value></param>" "</params></methodCall>", (unsigned long) timestamp, ph->user.authToken, station->id); snprintf (req->urlPath, sizeof (req->urlPath), PIANO_RPC_PATH "rid=%s&lid=%s&method=transformShared&arg1=%s", ph->routeId, ph->user.listenerId, station->id); break; } case PIANO_REQUEST_EXPLAIN: { /* explain why particular song was played */ PianoRequestDataExplain_t *reqData = req->data; assert (reqData != NULL); assert (reqData->song != NULL); snprintf (xmlSendBuf, sizeof (xmlSendBuf), "<?xml version=\"1.0\"?>" "<methodCall><methodName>playlist.narrative</methodName>" "<params><param><value><int>%lu</int></value></param>" /* auth token */ "<param><value><string>%s</string></value></param>" /* station id */ "<param><value><string>%s</string></value></param>" /* music id */ "<param><value><string>%s</string></value></param>" "</params></methodCall>", (unsigned long) timestamp, ph->user.authToken, reqData->song->stationId, reqData->song->musicId); snprintf (req->urlPath, sizeof (req->urlPath), PIANO_RPC_PATH "rid=%s&lid=%s&method=narrative&arg1=%s&arg2=%s", ph->routeId, ph->user.listenerId, reqData->song->stationId, reqData->song->musicId); break; } case PIANO_REQUEST_GET_SEED_SUGGESTIONS: { /* find similar artists */ PianoRequestDataGetSeedSuggestions_t *reqData = req->data; assert (reqData != NULL); assert (reqData->musicId != NULL); assert (reqData->max != 0); snprintf (xmlSendBuf, sizeof (xmlSendBuf), "<?xml version=\"1.0\"?>" "<methodCall><methodName>music.getSeedSuggestions</methodName>" "<params><param><value><int>%lu</int></value></param>" /* auth token */ "<param><value><string>%s</string></value></param>" /* station id */ "<param><value><string>%s</string></value></param>" /* seed music id */ "<param><value><string>%s</string></value></param>" /* max */ "<param><value><int>%u</int></value></param>" "</params></methodCall>", (unsigned long) timestamp, ph->user.authToken, reqData->station->id, reqData->musicId, reqData->max); snprintf (req->urlPath, sizeof (req->urlPath), PIANO_RPC_PATH "rid=%s&lid=%s&method=getSeedSuggestions&arg1=%s&arg2=%u", ph->routeId, ph->user.listenerId, reqData->musicId, reqData->max); break; } case PIANO_REQUEST_BOOKMARK_SONG: { /* bookmark song */ PianoSong_t *song = req->data; assert (song != NULL); snprintf (xmlSendBuf, sizeof (xmlSendBuf), "<?xml version=\"1.0\"?>" "<methodCall><methodName>station.createBookmark</methodName>" "<params><param><value><int>%lu</int></value></param>" /* auth token */ "<param><value><string>%s</string></value></param>" /* station id */ "<param><value><string>%s</string></value></param>" /* music id */ "<param><value><string>%s</string></value></param>" "</params></methodCall>", (unsigned long) timestamp, ph->user.authToken, song->stationId, song->musicId); snprintf (req->urlPath, sizeof (req->urlPath), PIANO_RPC_PATH "rid=%s&lid=%s&method=createBookmark&arg1=%s&arg2=%s", ph->routeId, ph->user.listenerId, song->stationId, song->musicId); break; } case PIANO_REQUEST_BOOKMARK_ARTIST: { /* bookmark artist */ PianoSong_t *song = req->data; assert (song != NULL); snprintf (xmlSendBuf, sizeof (xmlSendBuf), "<?xml version=\"1.0\"?>" "<methodCall><methodName>station.createArtistBookmark</methodName>" "<params><param><value><int>%lu</int></value></param>" /* auth token */ "<param><value><string>%s</string></value></param>" /* music id */ "<param><value><string>%s</string></value></param>" "</params></methodCall>", (unsigned long) timestamp, ph->user.authToken, song->artistMusicId); snprintf (req->urlPath, sizeof (req->urlPath), PIANO_RPC_PATH "rid=%s&lid=%s&method=createArtistBookmark&arg1=%s", ph->routeId, ph->user.listenerId, song->artistMusicId); break; } case PIANO_REQUEST_GET_STATION_INFO: { /* get station information (seeds and feedback) */ PianoRequestDataGetStationInfo_t *reqData = req->data; assert (reqData != NULL); assert (reqData->station != NULL); snprintf (xmlSendBuf, sizeof (xmlSendBuf), "<?xml version=\"1.0\"?>" "<methodCall><methodName>station.getStation</methodName>" "<params><param><value><int>%lu</int></value></param>" /* auth token */ "<param><value><string>%s</string></value></param>" /* station id */ "<param><value><string>%s</string></value></param>" "</params></methodCall>", (unsigned long) timestamp, ph->user.authToken, reqData->station->id); snprintf (req->urlPath, sizeof (req->urlPath), PIANO_RPC_PATH "rid=%s&lid=%s&method=getStation&arg1=%s", ph->routeId, ph->user.listenerId, reqData->station->id); break; } case PIANO_REQUEST_DELETE_FEEDBACK: { PianoSong_t *song = req->data; assert (song != NULL); snprintf (xmlSendBuf, sizeof (xmlSendBuf), "<?xml version=\"1.0\"?>" "<methodCall><methodName>station.deleteFeedback</methodName>" "<params><param><value><int>%lu</int></value></param>" /* auth token */ "<param><value><string>%s</string></value></param>" /* feedback id */ "<param><value><string>%s</string></value></param>" "</params></methodCall>", (unsigned long) timestamp, ph->user.authToken, song->feedbackId); snprintf (req->urlPath, sizeof (req->urlPath), PIANO_RPC_PATH "rid=%s&lid=%s&method=deleteFeedback&arg1=%s", ph->routeId, ph->user.listenerId, song->feedbackId); break; } case PIANO_REQUEST_DELETE_SEED: { PianoRequestDataDeleteSeed_t *reqData = req->data; char *seedId = NULL; assert (reqData != NULL); assert (reqData->song != NULL || reqData->artist != NULL || reqData->station != NULL); if (reqData->song != NULL) { seedId = reqData->song->seedId; } else if (reqData->artist != NULL) { seedId = reqData->artist->seedId; } else if (reqData->station != NULL) { seedId = reqData->station->seedId; } assert (seedId != NULL); snprintf (xmlSendBuf, sizeof (xmlSendBuf), "<?xml version=\"1.0\"?>" "<methodCall><methodName>station.deleteSeed</methodName>" "<params><param><value><int>%lu</int></value></param>" /* auth token */ "<param><value><string>%s</string></value></param>" /* seed id */ "<param><value><string>%s</string></value></param>" "</params></methodCall>", (unsigned long) timestamp, ph->user.authToken, seedId); snprintf (req->urlPath, sizeof (req->urlPath), PIANO_RPC_PATH "rid=%s&lid=%s&method=deleteSeed&arg1=%s", ph->routeId, ph->user.listenerId, seedId); break; } /* "high-level" wrapper */ case PIANO_REQUEST_RATE_SONG: { /* love/ban song */ PianoRequestDataRateSong_t *reqData = req->data; PianoReturn_t pRet; assert (reqData != NULL); assert (reqData->song != NULL); assert (reqData->rating != PIANO_RATE_NONE); PianoRequestDataAddFeedback_t transformedReqData; transformedReqData.stationId = reqData->song->stationId; transformedReqData.trackToken = reqData->song->trackToken; transformedReqData.rating = reqData->rating; req->data = &transformedReqData; /* create request data (url, post data) */ pRet = PianoRequest (ph, req, PIANO_REQUEST_ADD_FEEDBACK); /* and reset request type/data */ req->type = PIANO_REQUEST_RATE_SONG; req->data = reqData; return pRet; break; } case PIANO_REQUEST_MOVE_SONG: { /* move song to a different station, needs two requests */ PianoRequestDataMoveSong_t *reqData = req->data; PianoRequestDataAddFeedback_t transformedReqData; PianoReturn_t pRet; assert (reqData != NULL); assert (reqData->song != NULL); assert (reqData->from != NULL); assert (reqData->to != NULL); assert (reqData->step < 2); transformedReqData.trackToken = reqData->song->trackToken; req->data = &transformedReqData; switch (reqData->step) { case 0: transformedReqData.stationId = reqData->from->id; transformedReqData.rating = PIANO_RATE_BAN; break; case 1: transformedReqData.stationId = reqData->to->id; transformedReqData.rating = PIANO_RATE_LOVE; break; } /* create request data (url, post data) */ pRet = PianoRequest (ph, req, PIANO_REQUEST_ADD_FEEDBACK); /* and reset request type/data */ req->type = PIANO_REQUEST_MOVE_SONG; req->data = reqData; return pRet; break; } } if ((req->postData = PianoEncryptString (xmlSendBuf)) == NULL) { return PIANO_RET_OUT_OF_MEMORY; } return PIANO_RET_OK; }