From 112528c8abaf712e2db0f8aef6b7d64b52281127 Mon Sep 17 00:00:00 2001 From: Lars-Dominik Braun Date: Tue, 10 Jun 2008 09:26:12 +0200 Subject: Added missing files to repo --- AUTHORS | 2 + BUGS | 6 + COPYING | 19 + ChangeLog | 15 + INSTALL | 25 + Makefile.am | 3 + NEWS | 4 + RoadMap | 18 + autogen.sh | 7 + configure.in | 37 ++ libpiano/Makefile.am | 6 + libpiano/const.h | 35 ++ libpiano/crypt.c | 283 ++++++++++++ libpiano/crypt.h | 29 ++ libpiano/crypt_key_input.h | 1071 ++++++++++++++++++++++++++++++++++++++++++ libpiano/crypt_key_output.h | 1076 +++++++++++++++++++++++++++++++++++++++++++ libpiano/http.c | 87 ++++ libpiano/http.h | 28 ++ libpiano/main.c | 249 ++++++++++ libpiano/main.h | 27 ++ libpiano/piano.h | 132 ++++++ libpiano/xml.c | 278 +++++++++++ libpiano/xml.h | 30 ++ src/Makefile.am | 6 + src/main.c | 339 ++++++++++++++ 25 files changed, 3812 insertions(+) create mode 100644 AUTHORS create mode 100644 BUGS create mode 100644 COPYING create mode 100644 ChangeLog create mode 100644 INSTALL create mode 100644 Makefile.am create mode 100644 NEWS create mode 100644 RoadMap create mode 100755 autogen.sh create mode 100644 configure.in create mode 100644 libpiano/Makefile.am create mode 100644 libpiano/const.h create mode 100644 libpiano/crypt.c create mode 100644 libpiano/crypt.h create mode 100644 libpiano/crypt_key_input.h create mode 100644 libpiano/crypt_key_output.h create mode 100644 libpiano/http.c create mode 100644 libpiano/http.h create mode 100644 libpiano/main.c create mode 100644 libpiano/main.h create mode 100644 libpiano/piano.h create mode 100644 libpiano/xml.c create mode 100644 libpiano/xml.h create mode 100644 src/Makefile.am create mode 100644 src/main.c diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..84f6677 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,2 @@ +Reverse engineering, main code: + Lars-Dominik Braun diff --git a/BUGS b/BUGS new file mode 100644 index 0000000..20034c6 --- /dev/null +++ b/BUGS @@ -0,0 +1,6 @@ +Bugs +==== + +A lot, I think. But none of them are found yet... + +Report them to: PromyLOPh@gmail.com diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..ce56cec --- /dev/null +++ b/COPYING @@ -0,0 +1,19 @@ +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. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..beca2c0 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,15 @@ +2008-06-09 + * replaced calloc & strcpy by strdup in xml.c + * rating implemented + * skip, change station, quit implemented + * now using thread for audio playback + +2008-06-07 + * updated readme + * documented some more functions + * fixed autotools + * added primitive playback of first song using libao and faad2 + +2008-06-05 + * url creation now uses less buffers + * first public release diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..d6458ab --- /dev/null +++ b/INSTALL @@ -0,0 +1,25 @@ +Install +======= + +Do not install this application yet! + +Dependencies +------------ + +Versions may vary :) Just get the newest one: + +libao http://www.xiph.org/ao/ (pianobar) +libcurl http://curl.haxx.se/ (libpiano, pianobar) +libfaad2 http://www.audiocoding.com/downloads.html (pianobar) +libxml2 http://xmlsoft.org/ (libpiano) + +Build +----- + +./autogen.sh +./configure +make + +Just run the client from this source directory + +./src/pianobar diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..b0a409e --- /dev/null +++ b/Makefile.am @@ -0,0 +1,3 @@ +SUBDIRS = libpiano src + +EXTRA_DIST = autogen.sh RoadMap BUGS diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..c8aa439 --- /dev/null +++ b/NEWS @@ -0,0 +1,4 @@ +News +==== + +Nothing happened yet... diff --git a/RoadMap b/RoadMap new file mode 100644 index 0000000..6b83d8c --- /dev/null +++ b/RoadMap @@ -0,0 +1,18 @@ +Roadmap +======= + +Ordered by importance: + +Must-have: +---------- + +* implement all pandora commands like ban/love/... +* buffer songs (works without too, but would be a huge improvement) +* fixes, fixes, fixes (look for memory leaks or implement error handling, e.g.) + +Wishes: +------- + +* replaygain +* cache for authtoken (how long are they valid?) and other userdata +* last.fm scrobbling diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..12d2f9b --- /dev/null +++ b/autogen.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +libtoolize --force \ +&& aclocal \ +&& automake --add-missing \ +&& autoconf \ +&& ./configure diff --git a/configure.in b/configure.in new file mode 100644 index 0000000..2206af2 --- /dev/null +++ b/configure.in @@ -0,0 +1,37 @@ +AC_INIT([pianobar], [20080609], [PromyLOPh@gmail.com]) +AC_CONFIG_SRCDIR([src/main.c]) +AM_INIT_AUTOMAKE([-Wall]) + +AC_PROG_CC +AM_PROG_CC_C_O +AM_SANITY_CHECK +AM_PROG_LIBTOOL + +PKG_PROG_PKG_CONFIG + +PKG_CHECK_MODULES(LIBCURL, libcurl >= 7.18.0) +AC_SUBST(LIBCURL_CFLAGS) +AC_SUBST(LIBCURL_LIBS) + +PKG_CHECK_MODULES(LIBXML, libxml-2.0 >= 2.6.31) +AC_SUBST(LIBXML_CFLAGS) +AC_SUBST(LIBXML_LIBS) + +PKG_CHECK_MODULES(LIBAO, ao >= 0.8.8) +AC_SUBST(LIBAO_CFLAGS) +AC_SUBST(LIBAO_LIBS) + +AC_CHECK_LIB([faad], [NeAACDecOpen], [LIBFAAD_LIBS=-lfaad], AC_MSG_ERROR([libfaad2 is required. See INSTALL])) +AC_SUBST(LIBFAAD_LIBS) + +# FIXME: check for pthread + +AC_CHECK_HEADERS([stdlib.h string.h]) + +AC_CHECK_FUNCS([memset]) + +AC_TYPE_SIZE_T + +AC_CONFIG_FILES(Makefile src/Makefile libpiano/Makefile) + +AC_OUTPUT diff --git a/libpiano/Makefile.am b/libpiano/Makefile.am new file mode 100644 index 0000000..e74d442 --- /dev/null +++ b/libpiano/Makefile.am @@ -0,0 +1,6 @@ +lib_LTLIBRARIES = libpiano.la + +libpiano_la_SOURCES = crypt.c http.c main.c xml.c const.h crypt.h crypt_key_input.h crypt_key_output.h http.h main.h xml.h +include_HEADERS = piano.h +libpiano_la_CPPFLAGS = ${LIBCURL_CFLAGS} ${LIBXML_CFLAGS} +libpiano_la_LIBADD = ${LIBCURL_LIBS} ${LIBXML_LIBS} diff --git a/libpiano/const.h b/libpiano/const.h new file mode 100644 index 0000000..dfaca1f --- /dev/null +++ b/libpiano/const.h @@ -0,0 +1,35 @@ +/* +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. +*/ + +#ifndef _CONST_H +#define _CONST_H + +/* constants */ + + +#define PIANO_USERAGENT "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9pre) Gecko/2008051115 Firefox/3.0pre" +#define PIANO_RPC_URL "http://www.pandora.com/radio/xmlrpc/v19?" +#define PIANO_SECURE_RPC_URL "https://www.pandora.com/radio/xmlrpc/v19?" +#define PIANO_URL_BUFFER_SIZE 1024 +#define PIANO_HTTP_BUFFER_SIZE 100000 + +#endif /* _CONST_H */ diff --git a/libpiano/crypt.c b/libpiano/crypt.c new file mode 100644 index 0000000..396f61d --- /dev/null +++ b/libpiano/crypt.c @@ -0,0 +1,283 @@ +/* +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 +#include +#include + +#include "crypt_key_output.h" +#include "crypt_key_input.h" + +/* hex string to array of unsigned int values + * @author PromyLOPh + * @added 2008-06-01 + * @param hex string + * @param return array + * @param return size of array + * @return nothing, yet + */ +void PianoHexToInts (char *strHex, unsigned int **retInts, size_t *retIntsN) { + size_t i; + char hexInt[9]; + unsigned int *arrInts = calloc (strlen (strHex) / 8, sizeof (*arrInts)); + + /* FIXME: error handling: string too short, e.g. */ + /* unsigned int = 4 bytes, 8 chars in hex */ + for (i = 0; i < strlen (strHex); i += 8) { + memset (hexInt, 0, sizeof (hexInt)); + memcpy (hexInt, strHex+i, sizeof (hexInt)-1); + sscanf (hexInt, "%x", &arrInts[i/8]); + } + *retInts = arrInts; + /* FIXME: copy & waste */ + *retIntsN = strlen (strHex) / 8, sizeof (*arrInts); +} + +/* decipher int array; reverse engineered from pandora source + * @author PromyLOPh + * @author probably pandora? + * @added 2008-06-01 + * @param decrypt-me + * @param decrypt-me-length + * @param return plain ints array + * @return nothing, yet + */ +void PianoDecipherInts (unsigned int *cipherInts, size_t cipherIntsN, + unsigned int **retPlainInts) { + unsigned int *plainInts = calloc (cipherIntsN, sizeof (*plainInts)); + + size_t i; + + for (i = 0; i < cipherIntsN; i += 2) { + unsigned int _loc2 = cipherInts [i]; + unsigned int _loc3 = cipherInts [i+1]; + unsigned int _loc6; + size_t n_count; + + for (n_count = in_key_n + 1; n_count > 1; --n_count) { + _loc2 = _loc2 ^ in_key_p [n_count]; + + unsigned int _loc4 = _loc2; + #if 0 + unsigned short _loc8 = _loc4 & 0xff; + _loc4 = _loc4 >> 8; + unsigned short _loc9 = _loc4 & 0xff; + _loc4 = _loc4 >> 8; + unsigned short _loc10 = _loc4 & 0xff; + _loc4 = _loc4 >> 8; + unsigned short _loc11 = _loc4 & 0xff; + #endif + unsigned short _loc8 = _loc4 & 0xff; + unsigned short _loc9 = (_loc4 >> 8) & 0xff; + unsigned short _loc10 = (_loc4 >> 16) & 0xff; + unsigned short _loc11 = (_loc4 >> 24) & 0xff; + unsigned int _loc5 = in_key_s [0][_loc11] + + in_key_s [1][_loc10]; + _loc5 = _loc5 ^ in_key_s [2][_loc9]; + _loc5 = _loc5 + in_key_s [3][_loc8]; + _loc3 = _loc3 ^ _loc5; + _loc6 = _loc2; + _loc2 = _loc3; + _loc3 = _loc6; + } + _loc6 = _loc2; + _loc2 = _loc3; + _loc3 = _loc6; + _loc3 = _loc3 ^ in_key_p [1]; + _loc2 = _loc2 ^ in_key_p [0]; + plainInts [i] = _loc2; + plainInts [i+1] = _loc3; + } + *retPlainInts = plainInts; +} + +/* int array to string + * @author PromyLOPh + * @added 2008-06-01 + * @param int array + * @param length of array + * @return the string + */ +char *PianoIntsToString (unsigned int *arrInts, size_t arrIntsN) { + char *strDecoded = calloc (arrIntsN * 4 + 1, sizeof (*strDecoded)); + size_t i; + + for (i = 0; i < arrIntsN; i++) { + snprintf (&strDecoded[i*4], arrIntsN * 4, "%c%c%c%c", ((arrInts[i] >> 24) & 0xff), ((arrInts[i] >> 16) & 0xff), ((arrInts[i] >> 8) & 0xff), ((arrInts[i] >> 0) & 0xff)); + } + return strDecoded; +} + +/* decrypt hex-encoded string + * @author PromyLOPh + * @added 2008-06-01 + * @param hex string + * @return decrypted string + */ +char *PianoDecryptString (char *strInput) { + unsigned int *cipherInts, *plainInts; + size_t cipherIntsN; + char *strDecrypted; + + PianoHexToInts (strInput, &cipherInts, &cipherIntsN); + PianoDecipherInts (cipherInts, cipherIntsN, &plainInts); + strDecrypted = PianoIntsToString (plainInts, cipherIntsN); + + free (cipherInts); + free (plainInts); + + return strDecrypted; +} + +/* string to int array + * @author PromyLOPh + * @added 2008-06-02 + * @param the string, length % 8 needs to be 0 + * @param returns int array + * @param returns size of int array + * @return nothing + */ +void PianoBytesToInts (char *strInput, unsigned int **retArrInts, + size_t *retArrIntsN) { + size_t i, j, neededStrLen = strlen (strInput); + unsigned int *arrInts; + char shift; + + /* blowfish encrypts two 4 byte blocks */ + neededStrLen = strlen (strInput); + if (neededStrLen % 8 != 0) { + /* substract overhead and add full 8 byte block */ + neededStrLen = neededStrLen - (neededStrLen % 8) + 8; + } + arrInts = calloc (neededStrLen / 4, sizeof (*arrInts)); + + /* we must not read beyond the end of the string, so be a bit + * paranoid */ + shift = 24; + i = 0; + j = 0; + while (i < strlen (strInput)) { + shift = 24; + while (shift >= 0 && i < strlen (strInput)) { + arrInts[i/4] |= strInput[i] << shift; + shift -= 8; + i++; + } + } + *retArrInts = arrInts; + *retArrIntsN = neededStrLen / 4; +} + +/* decipher ints; reverse engineered from pandora flash client + * @author PromyLOPh + * @author probably pandora? + * @added 2008-06-07 + * @param encipher this + * @param how many ints + * @param returns crypted ints; memory is allocated by this function + * @return nothing yet + */ +void PianoEncipherInts (unsigned int *plainInts, size_t plainIntsN, + unsigned int **retCipherInts) { + unsigned int *cipherInts = calloc (plainIntsN, sizeof (*cipherInts)); + size_t i, _loc7; + + for (i = 0; i < plainIntsN; i+=2) { + /* ++ encipher */ + unsigned int _loc2 = plainInts [i]; + unsigned int _loc3 = plainInts [i+1]; + unsigned int _loc6; + + for (_loc7 = 0; _loc7 < out_key_n; _loc7++) { + _loc2 = _loc2 ^ out_key_p[_loc7]; + unsigned int _loc4 = _loc2; + #if 0 + unsigned int _loc8 = _loc4 & 0xff; + _loc4 >>= 8; + unsigned int _loc9 = _loc4 & 0xff; + _loc4 >>= 8; + unsigned int _loc10 = _loc4 & 0xff; + _loc4 >>= 8; + unsigned _loc11 = _loc4 & 0xff; + #endif + unsigned int _loc8 = _loc4 & 0xff; + unsigned int _loc9 = (_loc4 >> 8) & 0xff; + unsigned int _loc10 = (_loc4 >> 16) & 0xff; + unsigned _loc11 = (_loc4 >> 24) & 0xff; + unsigned int _loc5 = out_key_s[0][_loc11] + + out_key_s [1][_loc10]; + _loc5 ^= out_key_s [2][_loc9]; + _loc5 += out_key_s [3][_loc8]; + _loc3 ^= _loc5; + _loc6 = _loc2; + _loc2 = _loc3; + _loc3 = _loc6; + } + _loc6 = _loc2; + _loc2 = _loc3; + _loc3 = _loc6; + _loc3 ^= out_key_p [out_key_n]; + _loc2 ^= out_key_p [out_key_n+1]; + cipherInts [i] = _loc2; + cipherInts [i+1] = _loc3; + } + *retCipherInts = cipherInts; +} + +/* int array to hex-encoded string + * @author PromyLOPh + * @added 2008-06-07 + * @param int array + * @param size of array + * @return string; memory is allocated here, don't forget to free it + */ +char *PianoIntsToHexString (unsigned int *arrInts, size_t arrIntsN) { + /* 4 bytes as hex (= 8 chars) */ + char *hexStr = calloc (arrIntsN * 4 * 2 + 1, sizeof (*hexStr)); + size_t i; + + for (i = 0; i < arrIntsN; i++) { + snprintf (hexStr+i*4*2, arrIntsN * 4 * 2 + 1, "%08x", arrInts[i]); + } + return hexStr; +} + +/* blowfish-encrypt string; used before sending xml to server + * @author PromyLOPh + * @added 2008-06-07 + * @param encrypt this + * @return encrypted, hex-encoded string + */ +char *PianoEncryptString (char *strInput) { + unsigned int *plainInts, *cipherInts; + size_t plainIntsN; + char *strHex; + + PianoBytesToInts (strInput, &plainInts, &plainIntsN); + PianoEncipherInts (plainInts, plainIntsN, &cipherInts); + strHex = PianoIntsToHexString (cipherInts, plainIntsN); + + free (plainInts); + free (cipherInts); + + return strHex; +} diff --git a/libpiano/crypt.h b/libpiano/crypt.h new file mode 100644 index 0000000..5b097f1 --- /dev/null +++ b/libpiano/crypt.h @@ -0,0 +1,29 @@ +/* +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. +*/ + +#ifndef _CRYPH_H +#define _CRYPT_H + +char *PianoDecryptString (char *strInput); +char *PianoEncryptString (char *strInput); + +#endif /* _CRYPT_H */ diff --git a/libpiano/crypt_key_input.h b/libpiano/crypt_key_input.h new file mode 100644 index 0000000..101d382 --- /dev/null +++ b/libpiano/crypt_key_input.h @@ -0,0 +1,1071 @@ +/* +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. +*/ + +/* decryption key for audio urls; maybe a bit (is) wrong? */ + +const unsigned int in_key_n = 16; + +static const unsigned long in_key_p [16 + 2] = { +2296512344, +484947285, +143549968, +244631162, +2837862836, +4220619567, +3243088304, +3951650136, +2299087613, +1520074566, +158025345, +411178977, +2673524149, +2453762392, +3332626847, +495515519, +3311155458, +682696847}; + +static const unsigned long in_key_s [4][256] = {{ +2128658832, +3697692759, +569211301, +3742887157, +3467885802, +2147119513, +4192337968, +3437898897, +4016418030, +2157619138, +583117442, +401727980, +3072617582, +4077876221, +3671778389, +2649329515, +2640655243, +2071373660, +4085571303, +3553863527, +1133039616, +3437126533, +2490500932, +3370401494, +1573762703, +2175142928, +2392296103, +3236551751, +5067846, +165858937, +3228665328, +743820206, +3002649133, +59643220, +2417792365, +3142818654, +3427635772, +933884315, +3613996694, +3618979812, +2360591210, +1682801625, +1453625472, +3456164020, +879269100, +328554126, +2275316178, +1272030676, +2500712587, +749073271, +3896454727, +4088023553, +687999959, +2469782053, +3766986318, +3451556060, +1754326800, +2344570827, +1225379552, +2644890178, +4208616430, +27004362, +2596728114, +3890571680, +2829628313, +2146575973, +2604179370, +875685754, +3789988084, +3710311422, +429817720, +2489171178, +2417320237, +2057030818, +513667518, +2609637543, +3883646020, +812728312, +2465864861, +3479050491, +3739187534, +702439720, +1035737271, +4260354581, +3936608854, +4227404962, +3051622786, +2736574401, +3016354133, +2400405798, +2156979612, +3314004968, +2051685990, +19000029, +2263979164, +3289285288, +2054307889, +3734311294, +491634325, +2190156983, +2148046895, +3704963939, +3127900644, +2980448167, +1614044505, +3660721912, +980501804, +3968515521, +3295860462, +148000610, +243717540, +1863084385, +1451686518, +1937128161, +1288731877, +2328067692, +2439034247, +4197306741, +1938401619, +2555038861, +15219513, +3628919040, +3510915315, +1489139789, +1991410177, +4187354845, +225137599, +2062447135, +2501882488, +2480492692, +567737617, +1036415794, +3981376799, +913768078, +3065006006, +1820394782, +254348814, +1325117948, +2909116826, +2511990395, +1715211232, +3189554177, +3567373216, +3556507372, +2262599526, +693598649, +1099914476, +3672117902, +2638339847, +3299432663, +1538274707, +1268479177, +201923410, +3061278922, +592173100, +3679063927, +1977344805, +213188203, +1473160814, +655738293, +2307755395, +1102800598, +1224966405, +2974183441, +2587452770, +3896724147, +2477674660, +3932777844, +2839523899, +2303064094, +2319028970, +3994938371, +2531716662, +1149932666, +2122231008, +3430946183, +1123953689, +3918797176, +3113636643, +569397975, +873251573, +1006744943, +2358488303, +1706139356, +3748979395, +2868106633, +3327350140, +965732034, +4203817156, +1154349457, +4176400058, +2506261162, +3522349991, +2825760889, +2975958252, +3380371122, +4191046999, +3067498012, +2000197545, +1596105051, +43102264, +3960878063, +2991269966, +2651508977, +503441229, +3370966567, +4126958357, +3479998414, +1663772473, +4055833092, +3058057733, +1519395627, +4081731088, +3498430713, +4087687311, +1900626065, +1479961327, +754122244, +2327746245, +22675233, +927443873, +2073499140, +1474870579, +2638639189, +1805139553, +953981772, +3390679038, +1167912887, +95410946, +648812050, +3545853366, +4257643329, +3476212461, +4247642195, +1702876451, +2551474845, +4015716228, +2857099433, +731476059, +1034709055, +189485318, +706939940, +2448745741, +3738990808, +2158196067, +272411170, +2036216135, +3989855351, +849465627, +2117968867, +4237903689, +1146595723, +4164488914, +3196930194, +3197964737, +931629632}, +{3548148628, +2211365680, +2089986676, +1655452034, +2053784589, +1508902489, +1547502091, +444611061, +1464377684, +1323694999, +2081672378, +2096063287, +1954615531, +2547897755, +51446746, +3545549320, +3792454069, +2011748624, +603352473, +4082037335, +3248566449, +1996054105, +367955388, +45294088, +4191310435, +3560573315, +2208097136, +317000604, +973063857, +1901052476, +3594901368, +2372855512, +3754787831, +1249648311, +1236196835, +1003906284, +1584089589, +1911913406, +4148522202, +4117131048, +464855281, +57312436, +4033903816, +3327693898, +328640972, +2473759010, +656272857, +3330556738, +1461007611, +4149032611, +389760877, +167691223, +465324772, +3366565279, +1394746618, +3064354168, +587646460, +1027350944, +1109309161, +1888507858, +2555943894, +1275409665, +3956869818, +2047644060, +3068621980, +2124508377, +1890051703, +78829997, +531871861, +864999736, +3976110411, +550237492, +3644799421, +963672361, +2733945391, +2843027788, +3240585992, +329717593, +2367858037, +520750960, +4141805924, +918099938, +3102520697, +2717021903, +600629173, +2513538841, +2432383934, +1222912227, +2250136015, +1948713135, +3303451350, +4045419046, +3737856603, +1818504227, +1009479111, +3646248578, +3257619203, +1147482990, +4107385262, +2863997375, +339020927, +1396395445, +122111967, +1785723989, +1749970671, +35631032, +229501423, +1725806672, +3827732449, +2328758187, +1666770172, +2201735539, +2116234489, +2696008844, +2750826860, +2456856093, +2196939312, +3967735672, +3306243803, +1276372623, +2299710358, +2465827193, +267327425, +4294932395, +578153752, +2087579097, +848263718, +1627539853, +366252371, +4134377219, +2567776591, +1116309489, +1592683734, +1135214447, +4078309104, +883503540, +1924140744, +688979784, +825732389, +3771827534, +181267738, +3001917334, +3164692624, +3534114336, +774568626, +1184890620, +1267945932, +437602121, +3742699662, +2050213757, +1614127546, +163079514, +1753969382, +119415495, +1663983235, +1291217790, +1366095958, +1281385911, +534413482, +2423430219, +766473010, +1036107689, +3882538353, +4072983665, +2120880908, +2578509329, +3528269059, +3019425823, +2507098354, +2754316745, +1302297579, +3471472873, +3481343609, +1110986617, +3582075135, +3938075187, +1835529863, +114194332, +780559136, +1585511111, +2709377510, +4663784, +1983420553, +1741851203, +3571748766, +4159418382, +2298273138, +3444544863, +1646590981, +4150277106, +2922217812, +1591569840, +2501244910, +2307277202, +2486747582, +4137585745, +3264322649, +617810905, +592289569, +2957603935, +1720250393, +1282606586, +3978699383, +3209807216, +3518166905, +1471743803, +3699500250, +3010910150, +1141653188, +3125105165, +1708028061, +91863804, +3079950642, +1336661688, +585800731, +1074729853, +3353177727, +2984823139, +3539233959, +2168918504, +3793136000, +2920883668, +963999784, +859512981, +1285863374, +1626228743, +1196896976, +3246829424, +2086049373, +1817626830, +1917959116, +1920789886, +256350158, +780762582, +213624274, +3580963146, +1783941209, +3588539293, +4013209723, +1482977330, +74981631, +559033976, +2469748467, +2880298757, +1099765558, +981518101, +3991034119, +758521765, +2537136421, +2024757999, +1200463233, +1909122492, +1302732640, +1250260811, +1659083864, +1287777740}, +{3554236288, +810416052, +158802161, +131289115, +2593446892, +990921853, +88040369, +3223991913, +3314506608, +978106573, +164800071, +1122917831, +3948723682, +884979134, +954240927, +1937491233, +3177479616, +3510454307, +2556095171, +2095156345, +2078654475, +2247021842, +3261581243, +3126392505, +2156995676, +3163839338, +2870938297, +793620229, +1688422899, +512503459, +2068937319, +1069519665, +2140042310, +3631453050, +4119336486, +3936344495, +1966578659, +3270436351, +1287213770, +2499138104, +1312726036, +821755190, +2864942520, +2022246070, +1346794584, +3958680043, +2898351670, +2292291399, +440681239, +1464442920, +2295074635, +2252760328, +490755791, +301606609, +1139180458, +2816955463, +1563942872, +36955748, +3471174646, +4103015072, +2739976564, +1133336123, +824381589, +315115904, +3583285615, +1598273833, +2548883769, +618878114, +4030191589, +925875053, +4125012162, +1453444251, +3684935211, +4170815349, +4112292800, +3897892094, +3514815579, +3146810609, +693096477, +1806637049, +1659631547, +2330028127, +4286685584, +4168728225, +3735359230, +1236064845, +1245391878, +2346463708, +609365761, +253579419, +3740453275, +3206055112, +1763220332, +1154782396, +1635249739, +106454628, +1237878011, +3960679739, +1259117609, +1325699946, +390092277, +2014447649, +1310659372, +2776516651, +2445505501, +1354818074, +1167516370, +2429917704, +3779915141, +1893127422, +2330145579, +1193157505, +1509056626, +3153125681, +1404909737, +4176954964, +2943369187, +3147767230, +3349110054, +943888967, +2421425468, +865909068, +3907763794, +1570630418, +1473683708, +1023355763, +725783349, +3425397802, +2607056779, +2248801744, +739959172, +1925660432, +3214198318, +1841031619, +4141680013, +4210070222, +3152438583, +3667048743, +4281076589, +3634719715, +945809397, +2561946849, +1225545006, +3306764442, +3409589233, +1598008340, +3831187310, +1733352819, +932119442, +3082624907, +1422551176, +2766356888, +819609813, +3288351621, +1230545957, +680725051, +977757332, +2721303922, +440647377, +3207512234, +1130262272, +2587644460, +2563067841, +681411150, +4115404362, +1110175982, +3158946095, +643581087, +110203798, +2836680784, +1488118585, +4070154931, +2991733788, +4119545618, +948002949, +3109157700, +897958133, +169664173, +733813972, +1982075210, +1205004562, +375168004, +2810680328, +2246661195, +2809488804, +1054033161, +3346180847, +3943569363, +2728441744, +844689912, +2821295363, +907982464, +2715150073, +3800824232, +1719926814, +2155188792, +2709493441, +1938625885, +2114268368, +466087366, +2409883443, +2025557853, +1344441334, +3617674189, +817973227, +1955080900, +2845524782, +3745246674, +2632253171, +1257730466, +2040723666, +2708337140, +543947183, +1488485060, +292373701, +491952464, +2057755552, +3400090358, +1900715831, +3612192944, +1987004224, +3567497054, +878496315, +1604053755, +1176518849, +2279327360, +1748284085, +303657754, +2782089490, +506128051, +1614889427, +2801053043, +1202125863, +1360990060, +3802296025, +879327051, +2871259251, +2348346866, +3233806136, +3311161207, +1838180420, +544662648, +1972132486, +3765637101, +3464671957, +2834850978, +4022703989, +3719086717, +3051662122, +1658462487, +3404201395, +2558383819, +401622436, +4158099338, +3191926275, +3900648207}, +{2906980109, +3244040462, +3842009756, +4177586565, +3128780359, +389257510, +1433826605, +3239482476, +2804682224, +1095312530, +4264552109, +500527977, +320084931, +3448532078, +87643447, +1233852435, +3799263706, +849541286, +3654913140, +1720613777, +1204288368, +3558012178, +1852713204, +2991301237, +712827210, +512347544, +2209552811, +2380728472, +2061298391, +1187415824, +4154911301, +4057990159, +2349469378, +2545159130, +1775747174, +2591410713, +2229519704, +4057763051, +34983877, +2018348659, +3051995695, +2099457161, +122176200, +3614959731, +1011099307, +2707461689, +2710657949, +1519288114, +297037952, +350201262, +511044781, +1108019973, +3101610154, +3969643310, +997019662, +1683546324, +1465743109, +358651173, +4222805613, +268914497, +652780242, +3508590503, +414591203, +3313257121, +2605462681, +1291711251, +2142143497, +2733700582, +3268848903, +1669040160, +3061666233, +2897555767, +3277977602, +218193538, +551879950, +2651413813, +1304346475, +1672107670, +1251053219, +57431126, +1608803694, +1191480742, +904537817, +645123498, +3097150410, +2924217906, +611983353, +2293480932, +2034270664, +986691666, +741722320, +3726624549, +1403284782, +616727866, +3292944289, +1733282574, +3943960954, +892568249, +1602920243, +2055039837, +1121174416, +1554530122, +1969210884, +1627002077, +255323245, +659290392, +413679961, +3355601324, +853401555, +1923886853, +1911568009, +275978186, +4110789833, +3785826431, +1880789664, +1834557896, +3185455839, +4112428490, +1909962454, +901840141, +1702581561, +930703993, +544235727, +1917462098, +3576405067, +2313599093, +3209909484, +1078722592, +2300716722, +488195978, +843151466, +1885259855, +2660301574, +2493041758, +3885484332, +3596373427, +4091285124, +18165664, +2851846839, +2066994388, +3779380391, +1638886162, +1203036700, +3207436785, +3839055612, +992380467, +1617890949, +3271283843, +1985171789, +1589586926, +59295131, +2201447571, +1802886001, +1524685393, +1619130887, +4277411271, +1632946657, +916420718, +1988186984, +1087584352, +328546419, +699568195, +752262087, +2593455512, +2054325461, +224511444, +1937218889, +4177808215, +3674484078, +2202083318, +1662921402, +431990019, +3263118914, +1513147185, +3599292635, +1667827679, +4194190277, +2902980642, +1527280030, +2323092096, +3686881320, +1844238265, +234981319, +3601863066, +3591054018, +1245988708, +1982786555, +3217502413, +2338410264, +1184032842, +686321676, +2833157096, +3648900116, +3352580660, +2473019798, +2877120488, +4117315385, +105188436, +3682865154, +923331766, +858955270, +2848822230, +1157150450, +2597825900, +3704699325, +1687529016, +2601511833, +3714180651, +788566728, +3803114264, +2289638900, +931304621, +2478429664, +942053111, +2072299200, +1527540710, +1639028869, +4075126463, +2520412384, +2832409251, +2538838994, +523574607, +99984740, +1238458557, +566420211, +1326154395, +3447105210, +4266037523, +2847987284, +3693440980, +1764601394, +4086197753, +3561101407, +1750462971, +3195538424, +962192249, +232305254, +4054331716, +2477415058, +3576429591, +2979101766, +2766793053, +3112000711, +3423119961, +357902640, +1320412483, +2720212787, +1427733989, +99871163, +1794019431, +1332239274, +653929270, +3402307422, +1010543326, +3438754380, +3221207255}}; diff --git a/libpiano/crypt_key_output.h b/libpiano/crypt_key_output.h new file mode 100644 index 0000000..5bafaf5 --- /dev/null +++ b/libpiano/crypt_key_output.h @@ -0,0 +1,1076 @@ +/* +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. +*/ + +/* encryption key for xmlrpc */ + +#ifndef _CRYPT_H +#define _CRYPT_H + +const unsigned int out_key_n = 16; + +static const unsigned long out_key_p [16 + 2] = { +1655854977, +919004318, +2043595880, +23762164, +-1305147675, +-215967440, +835493487, /* ! */ +261889135, /* ! */ +987405585, +-122581809, +8882411, +875817828, /* ! */ +466417059, +-544099275, +-1525766406, +-1945723444, +536361814, +-1487225158}; + +static const unsigned long out_key_s [4][256] = {{ +-513813079, +-765782257, +183159219, +-1365669178, +1047088991, +222171688, +-2090853737, +-765179426, +997050138, +-2057228390, +-1628206499, +-1408898308, /* ! */ +-588637121, +1846207300, +2065654413, +-412282565, /* ! */ +-1421690766, +1839083055, +1892832522, +-1919151611, +-1767698857, +1341672799, +-255927541, +726598137, +1990634699, +464663677, +-904351607, /* ! */ +1970163162, +-792713214, +-475806450, /* 47 */ +1950400144, +-262078895, +-761022537, +-667642993, +312735385, +-34426203, +1832569587, +-1684213010, /* ! */ +634837297, +-1948396026, +-604405134, +-691056861, +988289742, +-1839385794, +2062571691, +297518815, +-888607360, +-511051809, +701070684, +-1998977035, /* ! */ +1553720912, +-1604313120, +-1754421883, +1603596992, /* ! */ +1928276512, +-943968281, +1944528438, +589172448, +1447396119, +694763397, /* ! */ +2082830654, /* ! */ +553534140, +1553843344, /* ! */ +-1667538856, +-2018018024, +1501396120, +1234751004, +1067889147, +-1123200064, /* ! */ +-2044106955, +2086877862, +1976886420, +38662426, +-104788291, +-2117573866, +663013564, +-996232851, /* ! */ +1102290631, /* 95 */ +-740244768, +-1151084003, /* ! */ +1942342365, +-21446148, +593950808, /* ! */ +-704678316, +882519192, +-1705861753, +1535663280, +-955682427, +490241188, +-2045390075, +-1740044623, /* ! */ +-560660930, /* ! */ +-397891080, +-646170301, /* ! */ +486316357, +1043377519, +-1352836022, /* ! */ +963270259, +1208484782, +-1946438033, +-1672860695, +-2047609127, +-2066653853, +882790375, +-1651671083, +-1390467297, +947685781, +943582655, /* ! */ +993804347, +-669445900, /* ! */ +1033242534, +1947027902, +2123227639, +-1374249331, /* ! */ +559160429, +802992266, +-443557517, +-1689158322, +1902902596, +1955321636, +75631, +-1420670840, +-2016287362, +-1445425632, +-420570310, /* ! */ +-354654912, /* 143 */ +-1972668301, +653997721, /* ! */ +452795541, +-66510820, +-1862128475, +-1327921414, +1708518909, +15711562, /* ! */ +1721321276, +-1394169533, +373602900, +2099511181, /* ! */ +2078960031, /* ! */ +-1504406862, +-1849228115, /* ! */ +-1767469541, +-1599186379, +772444871, +918597368, /* ! */ +-937045004, +-712386722, +-904126536, +-1318252653, +-450264842, /* ! */ +1826831532, /* ! */ +-958506776, +2050742404, +2050686251, +-154637178, +481081149, +1114171521, +-1904274054, +1419437721, +693681474, +1890059780, +-1575700716, +-656873177, +490233525, +-526894138, +1682076343, +-781336395, +816523260, +2048253734, +1527924261, +-1254019825, +-1450610880, +1819678767, +1741799953, /* 191 */ +812933538, /* ! */ +250020223, +-588621470, +-586042668, /* ! */ +303595274, +-736731322, +-1042514938, +2056265092, +590811071, +-2076239761, +1536040004, +526821270, +-809199490, +826044521, +-639982281, +575323029, +-370506263, /* ! */ +-749572018, +2087094581, +587374721, +552065397, /* ! */ +149358673, +786310855, +-167069507, +-1875132152, +1022462681, +129236467, +-1087026086, +1856839244, /* ! */ +1328124015, +1731045631, /* ! */ +-1648761702, +-2049695288, +-701165592, +-329506427, /* ! */ +-925003291, +-721052514, +1651606994, /* ! */ +-1211116030, +1210824470, /* ! */ +1625998108, /* ! */ +173453468, +-558787357, /* ! */ +-1398935598, +1207642912, +-1044964430, +1054695311, +-532066592, /* 239 */ +-261141564, +-1493815133, /* ! */ +-161866707, +-1721246338, +-477625609, +133205312, +1987497710, +-1339095630, +1043463425, +-1843491306, /* ! */ +543431533, +-257519406, /* ! */ +1302076883, +127797200, +-1975436180, +1034932095, /* ! */ +-1868206592, /* ! */ +-1696244482, +1998241908, +1099342102, +900741619, /* ! */ +1370202513, /* ! */ +-627586602, +1075779902, +-800694166, +2047880971, /* ! */ +757977382, +-737442507, +763877853, +837154760, /* ! */ +-1361839879, +1697214753, +-1169239768, +-2088855814}, +{1629020117, +922095353, +504197536, /* ! */ +954775243, +120145635, /* ! */ +-579060756, +-519454323, +73872886, +-557968095, +410158880, +-67682390, /* ! */ +2136179483, +113474032, +936282950, /* 287 */ +1835643417, /* ! */ +-425487382, +2010519404, +-837248632, +-1592374918, +-1308567382, +-768768095, +-935042502, +-1467653241, +101884394, +1185880783, +-2128586097, +2058885475, +-296250734, +2137323390, +1125638684, +1529361514, +-1107789882, +-782194686, +1311102644, +-19347165, /* ! */ +1295250024, +627682341, +1409475839, +1718747575, +1534390947, +1253718782, /* ! */ +1169937313, +1521291895, +1265721067, +563973947, +-1270523181, +1493641800, +422652537, +153943244, +491686725, +53879678, /* ! */ +-403818722, +-501153969, +411423572, +964839170, +-798731292, +191704494, /* ! */ +-1942882791, /* ! */ +247351225, +-1147871801, +991063408, +2078916385, /* 335 */ +-409571302, /* ! */ +-1940714758, +-1635967463, +380126381, +-1480405811, +-111862091, +798808002, +1846690607, +1161223894, +-840749709, +1757844636, +1919227953, +1396721207, +-841099775, /* ! */ +1457173961, +269317440, /* ! */ +2076729104, +1669595361, +-406583178, +1213054918, +2137223591, +-408202097, +-1602785642, +-1642508502, +2059883563, +963377666, +-1730998307, +990959345, /* ! */ +-1662041039, +1184415790, +-1800589468, /* ! */ +1191574841, +2066827079, +1565744467, /* ! */ +-1982705060, +1003114192, +431969651, +2118380916, +1762711765, /* ! */ +-1288938317, +-1853007890, /* ! */ +1365304189, +-1249405781, +-843409397, +-2121756142, /* ! */ +1763447208, +1707589958, +2025386815, /* 383 */ +1264619878, +1975513356, +-506432955, +-339393069, +-715206660, +-1014927581, +-2017612850, +1645137307, +1335624819, /* ! */ +-1383696066, +-216010255, +-937606920, +1953828927, /* ! */ +1100215538, +-1844619416, +975828407, +1987251605, +1299855611, +755596177, /* ! */ +-926025603, /* ! */ +307698060, +-819390822, +138444246, /* ! */ +-1330460178, /* ! */ +-295935330, +-668410217, +216808357, +-192442834, /* ! */ +1944707886, +683076481, +-1879751421, +1560771135, +886165615, +-971369067, +-179874281, +-1780972412, /* ! */ +1551477128, +124161839, +638318309, +-793030002, +-303257131, /* ! */ +913110130, +-1563131354, +-1152927828, +58544864, +-666588206, /* ! */ +-2025777247, +1410656413, /* 431 */ +1133449775, +1776814160, +-1202000308, +-1587468692, +764233611, +-404082071, +1418515926, +-250996474, +1606154972, +-1042368908, +-960300962, +163193207, +2109826396, +310314579, /* ! */ +-656998654, +-2120731499, +398720860, +1102716052, +-1232677915, +513056809, /* ! */ +-1517523318, +-1907107147, +5008204, +-388009951, /* ! */ +145362986, +2001293342, +-313996635, +1696291650, +-468561025, +-620682907, +-487614562, +185707581, +542653640, +1843380185, +1071686700, +-278346004, +-1874035140, +1769296035, /* ! */ +823654751, +-1141322049, +770471852, +-1174632118, +-1380529665, +-356118263, +369984285, +-993721262, +2078447917, +-1905514517, /* 479 */ +438882915, +-1866080467, +-1965418802, +785895483, +856543611, +2115038375, +1562771728, +158744776, +740212411, /* ! */ +-1753064584, +-347114853, +-679343665, +-1677363466, +-776711069, +146507865, +1433561752, +1484718853, /* ! */ +2068007340, +1673669650, +2034888177, +-1427667267, +1725314550, +-745227351, +-510153416, +1812096408, +-769448952, +724796919, +-1641705060, /* ! */ +-187715871, +-1993150269, +-1951578846, +-1566737172, /* ! */ +-695189052, +-1557626854, +278291124, +-207619058, +892260834, +-217735893, +1437921610, /* ! */ +-1331483695, +1629715297, +1609637755, +-1299672728, /* ! */ +2024824922, +1141063060, /* ! */ +-1593362831, +-406554816, +-2065662630, /* 527 */ +-224474689, +1957733334}, +{530839846, +-1871368488, +722209002, /* ! */ +-1494427347, +283456798, +-1991074430, +-1437368661, /* ! */ +1393643393, +1884233053, /* ! */ +316592593, /* ! */ +-1633634175, +67711552, +-1532028936, /* ! */ +-28150029, +204892734, +-626897753, +-1702641288, +1473684453, /* ! */ +847362557, +-1079059160, +-19386413, +-1492891500, +-1231328909, +-1172519719, +733310353, +1030660013, +562154443, +1484588979, +413427779, +-1254045512, +1581815858, +1647037953, /* ! */ +-1864688004, /* ! */ +-594840704, +1714355138, +1910977695, /* ! */ +-869823320, +-1594092636, +-949905272, +1872451812, +1724295091, +1473849446, +-467809334, +-872003011, +957920643, +-1658925668, /* ! */ /* 575 */ +-1014830365, +2041534498, +-1289170570, +-314708652, +-14928717, /* ! */ +594597886, +606588791, +-294691293, +-1652089121, /* ! */ +1353100923, +-376999554, /* ! */ +-1606083711, +1964831987, /* ! */ +1284324098, +946571071, +-236835181, /* ! */ +1826868670, /* ! */ +-628576385, +353949044, +-1383415207, +-442241461, +1210088326, +-1861213995, +2026802836, +-775203988, +213100962, +1303937343, +1886697286, +-853503936, +22916867, +347578369, +458151896, /* ! */ +893076939, +752142338, +-51154144, +698477494, +2085285200, +-1415936037, +-1477954736, +238866470, /* ! */ +364867055, /* ! */ +1969690005, +1464856701, +-221777765, /* ! */ +1766279956, +926079829, +-2128722228, +1464323667, /* 623 */ +-468389908, +-1102371895, +-626360488, +1493866378, +1382411426, +1373259629, /* ! */ +-1516263679, +-2036634017, /* ! */ +-454735742, +-461817920, +1678767014, +682280596, +-1933839848, +1867889900, /* ! */ +1536263691, +1512429242, +1233608153, +1055317390, +1481821303, +-1545547500, +-474961387, +-1325240485, +727223122, /* ! */ +666049219, +1466147771, +-978190400, +-984951028, +137279631, +828970652, +1470706108, +1240031461, +339800793, /* ! */ +-1772684179, +1005013651, /* ! */ +-893710369, +2713655, +-831673471, /* ! */ +560401867, +1193286576, +2012625949, +-1385481301, +690693520, +450434938, /* ! */ +6859662, +-1695312035, +-470768530, +-1735583840, +1551947458, /* 671 */ +-23903826, /* ! */ +-272927289, +1457836440, +-549340909, +340129861, +1448426993, /* ! */ +1720095155, /* ! */ +289970191, +609452121, +-1134964683, /* ! */ +2130731381, +661512363, +1034545082, +1645695279, /* ! */ +-592416413, +1464654292, +314520845, +-1293877797, +-943133768, +2135092525, +-339166461, +-1468607841, +2119446364, +-1873255440, +-372270913, +287916301, +-55366124, +-1194267973, +1116182918, +1905595606, /* ! */ +-1948425343, +-1664638428, +-818329511, +469058705, +-2055526656, /* ! */ +-251951159, +463740098, +-1736727888, /* ! */ +893359773, /* ! */ +-932042121, +342343504, +-29499057, +1590216069, +1274735907, +-1960711099, +-1127741069, +122033645, +2128542502, /* 719 */ +-81160273, +519927763, /* ! */ +-1307524253, +-482965142, +-1875812682, +-288813376, +1790354532, +-1951270944, +-524755692, /* ! */ +1014821076, +-786978547, +-1503715841, +-2119099811, +-178066143, +-328007828, +-1411219934, +1027907211, +1561637548, +-1472328906, +110611707, +1896384984, +-1646981054, /* ! */ +-1588084855, +-2134248380, +-905796293, +-56029556, +-2117775674, +-1582683057, +615719466, +384957578, +1188945602, +-1184220203, +-6033762, +2003966672, +1510414055, /* ! */ +-2049998746, +386408271, +1961250254, +1424350579, +-858634167, +213880883, +-1007779050, +2026561215, +259490021, +-797084108, +1460692963, +1525331451, +1370262182, /* ! */ /* 767 */ +293318673, +544808302, +920263177, +103655446, /* ! */ +-1431460277, +-1803600980, /* ! */ +-1505376616, +257291575, +1208290601, +1859852686, +69613997, +-1234549782, +-1423238393, /* ! */ +711158442, +218702758, +48671031, +1561531785, +549682762}, +{1722841024, /* ! */ +1678073353, +-614334879, +-1261051299, +778307565, +1683919416, +-606372214, +890910445, +-1519602957, +422817018, +-985731497, +-399348512, /* ! */ +-1730647324, +-1099955160, +-1930459907, +-2018277684, +-1196489861, +1513840148, +1886456409, +838084158, +1913826009, +-142146436, /* ! */ +-413218814, +565709772, +204821326, +-1548350062, +1881270649, +-1176661609, +655405327, +1449467372, /* ! */ /* 815 */ +1721788626, +-854013850, +-899192508, +-360793273, +867045638, +-1591438706, +-1195082927, +2094926826, +1928537063, /* ! */ +792539387, /* ! */ +1767255387, +1983283598, +-358435631, +-779393177, +-1086267881, +-1549436626, +-1582534409, +1051799914, +-245143042, +-1918223607, +-11193281, +1001934263, /* ! */ +-73506240, /* ! */ +1279486962, +-937898593, +265050536, +-2052831146, +-2116298214, +676055329, +1320971350, +60112790, /* ! */ +-1111508310, /* ! */ +691496339, +-1289734630, +1672957635, +1828477688, +2055454618, +-497831808, +-1032041626, +1974291279, +146836556, +-367217667, +-719016930, +-894795368, +400656073, +-551206802, +71329459, /* ! */ +955057240, /* ! */ /* 863 */ +-842425766, +-938155869, +-461082201, +-89628848, +-719614551, /* ! */ +851389605, +1710650519, +1929871027, +2138521733, +1395635780, +1378055652, /* ! */ +234386875, +230019956, +-2105283931, +-418953863, +556294611, +1790257504, +-11582813, +-795597470, +907791823, /* ! */ +-36926894, +-1078349178, +1632571284, +1085203308, /* ! */ +-2102060924, +-353799919, /* ! */ +-511810872, +1217595593, +315762222, +664567993, +-620935514, +1760697749, +-150531764, +-906315733, /* ! */ +966756585, +2143511316, +829751318, +-645111024, +-750227043, +914171901, /* ! */ +-326094853, +-4718658, +176409364, /* ! */ +-453628962, +1015428453, +-950961455, /* ! */ +-1929004703, +-1979218629, /* 911 */ +-386687514, +-809528953, +-1315642451, +519041810, +1296778479, +-1396513598, +338706908, +1972031445, +-479710299, /* ! */ +-514326614, +-95378821, +1012441438, +-1770114023, +1966997515, +-431195712, +-195630652, +-1805137610, +-878196189, +1305117064, +-201378838, +45814250, +1582855393, /* ! */ +1051694644, +-118080464, +842639867, /* ! */ +964643756, /* ! */ +-810650327, +2103445589, +-1435798060, +1611948935, +-2013661703, +1773966623, +1264748971, +-53913554, +-1910238305, +59625376, /* ! */ +129956518, +1806897494, +1746354391, +765642861, +945168608, +-1084123694, +470467004, +-285404973, +-273067374, +-379320221, +469476951, +891590085, /* 959 */ +484100235, +-1507959076, /* ! */ +1604199464, +423268838, +488586602, +930867807, +-242676590, /* ! */ +-54340460, +1075848084, +-1939665362, +589512753, +205813722, +-46146582, /* ! */ +-797260050, /* ! */ +224571541, +-1212320744, +1738238306, +-444589, +2005858805, +2003218491, +638371325, +256246972, +1793131025, /* ! */ +-707291882, +-1151592902, +363764911, /* ! */ +1777326955, +-757008613, +-2006058918, /* ! */ +-946044045, +-1781443141, +-1007568595, +-661476356, +203874992, +663304469, +-563792643, +1058896789, +-1700207594, +-1838678505, +816281610, +783051130, +244431728, +26999557, +-400433464, +2036402176, /* ! */ +1461934271, +1431750752, /* ! */ +557152328, /* 1007 */ +336682025, +-188192101, /* ! */ +-1029579530, +1537018210, /* ! */ +355741330, +-913772271, +-573111973, +1332856894, /* ! */ +-463998480, +1095506380, +-1372153732, +-1070918314, +1176314092, +-1513258489, +2134865852, +-1080957377, +-1538012438, +-238348645, +730779314, +1576034869, +638655973, +-1293620774, +-1041456218, +-1532623621, +-360700565, +2018940370, +-706509096, +-1761858993, /* ! */ +566171489, /* ! */ +-2101362137, +548160877, +1587887228, /* ! */ +1708148227, +-928571626}}; + +#endif /* _CRYPT_H */ diff --git a/libpiano/http.c b/libpiano/http.c new file mode 100644 index 0000000..31c93cf --- /dev/null +++ b/libpiano/http.c @@ -0,0 +1,87 @@ +/* +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 +#include +#include + +#include "const.h" +#include "http.h" + + +/* FIXME: curl has a receive limit, use it! */ +/* callback for curl, writes data to buffer + * @author PromyLOPh + * @added 2008-06-05 + * @param received data + * @param block size + * @param blocks received + * @param write data into this buffer + * @return written bytes + */ +size_t PianoCurlRetToVar (void *ptr, size_t size, size_t nmemb, void *stream) { + char *charPtr = ptr; + char *streamPtr = stream; + + if (strlen (streamPtr) + nmemb > PIANO_HTTP_BUFFER_SIZE) { + printf ("buffer overflow...\n"); + return 0; + } else { + memcpy (streamPtr+strlen(streamPtr), charPtr, size*nmemb); + return size*nmemb; + } +} + +/* FIXME: we may use a callback given by the library client here. would be + * more flexible... */ +/* post data to url and receive answer as string + * @author PromyLOPh + * @added 2008-06-05 + * @param initialized curl handle + * @param call this url + * @param post this data + * @param put received data here, memory is allocated by this function + * @return nothing yet + */ +void PianoHttpPost (CURL *ch, char *url, char *postData, char **retData) { + struct curl_slist *headers = NULL; + /* Let's hope nothing will be bigger than this... */ + char curlRet[PIANO_HTTP_BUFFER_SIZE]; + + headers = curl_slist_append (headers, "Content-Type: text/xml"); + + curl_easy_setopt (ch, CURLOPT_URL, url); + curl_easy_setopt (ch, CURLOPT_POSTFIELDS, postData); + curl_easy_setopt (ch, CURLOPT_HTTPHEADER, headers); + curl_easy_setopt (ch, CURLOPT_WRITEFUNCTION, PianoCurlRetToVar); + /* don't verify certificate for now, it's easier ;) */ + curl_easy_setopt (ch, CURLOPT_SSL_VERIFYPEER, 0); + memset (curlRet, 0, sizeof (curlRet)); + curl_easy_setopt (ch, CURLOPT_WRITEDATA, curlRet); + + curl_easy_perform (ch); + + curl_slist_free_all (headers); + + *retData = calloc (strlen (curlRet) + 1, sizeof (char)); + strcpy (*retData, curlRet); +} diff --git a/libpiano/http.h b/libpiano/http.h new file mode 100644 index 0000000..87dc49c --- /dev/null +++ b/libpiano/http.h @@ -0,0 +1,28 @@ +/* +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. +*/ + +#ifndef _HTTP_H +#define _HTTP_H + +void PianoHttpPost (CURL *ch, char *url, char *postData, char **retData); + +#endif /* _HTTP_H */ 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 +#include +#include +#include + +#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 ("" + "misc.sync" + ""); + 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), + "" + "listener.authenticateListener" + "%li" + "%s" + "%s" + "", 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), "" + "station.getStations" + "%li" + "%s" + "", 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), "" + "playlist.getFragment" + "%li" + "%s" + "%s" + "15941546" + "181840822" + "" + "" + "aacplus" + "", 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), "" + "station.addFeedback" + "%li" + "%s" + "%s" + "%s" + "%s" + "%s" + "%s" + "%i" + "0" + "", 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 = 1 ) */ + free (requestStr); + free (retStr); +} diff --git a/libpiano/main.h b/libpiano/main.h new file mode 100644 index 0000000..1746e53 --- /dev/null +++ b/libpiano/main.h @@ -0,0 +1,27 @@ +/* +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. +*/ + +#ifndef _MAIN_H +#define _MAIN_H + + +#endif /* _MAIN_H */ diff --git a/libpiano/piano.h b/libpiano/piano.h new file mode 100644 index 0000000..ac64cd1 --- /dev/null +++ b/libpiano/piano.h @@ -0,0 +1,132 @@ +/* +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. +*/ + +#ifndef _PIANO_H +#define _PIANO_H + +/* this is our public API + * all strings _must_ be utf-8 encoded. i won't care, but pandora does. so + * be nice and check the encoding of your strings. thanks :) */ + +#include + +struct PianoUserInfo { + unsigned int zipcode; + /* disabled: billingFrequency */ + signed hasExplicitContentFilter; + char *webAuthToken; + /* disabled: alertCode */ + /* disabled: seenQuickMixPanel */ + unsigned short birthYear; + char *bookmarkUrl; + char *listenerState; /* FIXME: use enum? */ + /* disabled: adCookieValue */ + /* disabled: gender */ + /* disabled: emailOptIn */ + /* disabled: autoRenew */ + char *username; + char *listenerId; + char *authToken; + char *webName; +}; + +typedef struct PianoUserInfo PianoUserInfo_t; + +struct PianoStation { + signed isCreator; + /* disabled: originalStationId */ + char **genre; + unsigned int originalCreatorId; + /* disabled: initialSeed */ + /* disabled: isNew */ + /* disabled: transformType */ + char *idToken; + signed isQuickMix; + char *name; + char *id; + struct PianoStation *next; +}; + +typedef struct PianoStation PianoStation_t; + +struct PianoSong { + char *artist; + char **genre; + char *matchingSeed; + /* disabled: composerName */ + /* disabled: isSeed */ + /* disabled: artistFansURL */ + /* disabled: songExplorerUrl */ + float fileGain; + /* disabled: songDetailURL */ + /* disabled: albumDetailURL */ + char *webId; + /* disabled: musicComUrl */ + /* disabled: fanExplorerUrl */ + int rating; + /* disabled: artistExplorerUrl */ + /* disabled: artRadio */ + char *audioEncoding; /* FIXME: should be enum: mp3 or aacplus */ + char *stationId; + char *album; + char *artistMusicId; + char *userSeed; + /* disabled: albumExplorerUrl */ + /* disabled: amazonUrl */ + char *audioUrl; + signed onTour; + /* disabled: itunesUrl */ + char *musicId; + char *title; + char *focusTraitId; + char *identity; + struct PianoSong *next; +}; + +typedef struct PianoSong PianoSong_t; + +struct PianoHandle { + CURL *curlHandle; + char routeId[9]; + PianoUserInfo_t user; + /* linked lists */ + PianoStation_t *stations; + PianoSong_t *playlist; +}; + +typedef struct PianoHandle PianoHandle_t; + +enum PianoSongRating {PIANO_RATE_BAN, PIANO_RATE_LOVE}; +typedef enum PianoSongRating PianoSongRating_t; + +void PianoInit (PianoHandle_t *); +void PianoDestroy (PianoHandle_t *); +void PianoDestroyPlaylist (PianoHandle_t *ph); +void PianoConnect (PianoHandle_t *, char *, char *); + +void PianoGetStations (PianoHandle_t *ph); +void PianoGetPlaylist (PianoHandle_t *ph, char *stationId); + +void PianoRateTrack (PianoHandle_t *ph, PianoStation_t *station, + PianoSong_t *song, PianoSongRating_t rating); + +#endif /* _PIANO_H */ diff --git a/libpiano/xml.c b/libpiano/xml.c new file mode 100644 index 0000000..370d236 --- /dev/null +++ b/libpiano/xml.c @@ -0,0 +1,278 @@ +/* +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 +#include +#include +#include + +#include "piano.h" +#include "crypt.h" + +/* parses things like this: + * + * + * + * + * + * + * + * @author PromyLOPh + * @added 2008-06-03 + * @param xml node named "struct" (or containing a similar structure) + * @param who wants to use this data? callback: content of as + * string, content of as xmlNode (may contain other nodes + * or text), additional data used by callback(); don't forget + * to *copy* data taken from or as they will be + * freed soon + * @param + */ +void PianoXmlStructParser (xmlNode *structRoot, + void (*callback) (char *, xmlNode *, void *), void *data) { + + xmlNode *curNode, *memberNode, *valueNode; + xmlChar *key; + + /* get all nodes */ + for (curNode = structRoot->children; curNode; curNode = curNode->next) { + if (curNode->type == XML_ELEMENT_NODE && + xmlStrEqual ((xmlChar *) "member", curNode->name)) { + key = NULL; + valueNode = NULL; + /* check children for or */ + for (memberNode = curNode->children; memberNode; + memberNode = memberNode->next) { + if (memberNode->type == XML_ELEMENT_NODE) { + if (xmlStrEqual ((xmlChar *) "name", memberNode->name)) { + key = memberNode->children->content; + } else if (xmlStrEqual ((xmlChar *) "value", + memberNode->name)) { + valueNode = memberNode->children; + } + } + } + /* this will ignore empty nodes, but well... */ + if (key != NULL && valueNode != NULL) { + (*callback) ((char *) key, valueNode, data); + } + } + } +} + +/* structParser callback; writes userinfo to PianoUserInfo structure + * @author PromyLOPh + * @added 2008-06-03 + * @param value identifier + * @param value node + * @param pointer to userinfo structure + * @return nothing + */ +void PianoXmlParseUserinfoCb (char *key, xmlNode *value, void *data) { + char *valueStr = NULL; + PianoUserInfo_t *user = data; + + /* some values have subnodes like or , 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; + } + /* FIXME: should be continued later */ + if (strcmp ("webAuthToken", key) == 0) { + user->webAuthToken = strdup (valueStr); + } else if (strcmp ("authToken", key) == 0) { + user->authToken = strdup (valueStr); + } else if (strcmp ("listenerId", key) == 0) { + user->listenerId = strdup (valueStr); + } +} + +void PianoXmlParseStationsCb (char *key, xmlNode *value, void *data) { + PianoStation_t *station = data; + char *valueStr = NULL; + + /* FIXME: copy & waste */ + /* some values have subnodes like or , 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 ("stationName", key) == 0) { + station->name = strdup (valueStr); + } else if (strcmp ("stationId", key) == 0) { + station->id = strdup (valueStr); + } +} + +/* FIXME: copy & waste */ +void PianoXmlParsePlaylistCb (char *key, xmlNode *value, void *data) { + PianoSong_t *song = data; + char *valueStr = NULL; + + /* some values have subnodes like or , 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 ("audioURL", key) == 0) { + /* last 48 chars of audioUrl are encrypted, but they put the key + * into the door's lock; dumb pandora... */ + const char urlTailN = 48; + char *urlTail, *urlTailCrypted = valueStr + (strlen (valueStr) - urlTailN); + urlTail = PianoDecryptString (urlTailCrypted); + //printf ("tail is:\t%s\nwas:\t\t%s (%i)\nurl was:\t %s (%i)\n", urlTail, urlTailCrypted, strlen (urlTailCrypted), valueStr, strlen (valueStr)); + song->audioUrl = calloc (strlen (valueStr) + 1, sizeof (char)); + strncpy (song->audioUrl, valueStr, strlen (valueStr) - urlTailN); + /* FIXME: the key seems to be broken... so ignore 8 x 0x08 postfix; + * urlTailN/2 because the encrypted hex string is now decoded */ + strncat (song->audioUrl, urlTail, (urlTailN/2)-8); + free (urlTail); + + } else if (strcmp ("artistSummary", key) == 0) { + song->artist = strdup (valueStr); + } else if (strcmp ("musicId", key) == 0) { + song->musicId = strdup (valueStr); + } else if (strcmp ("matchingSeed", key) == 0) { + song->matchingSeed = strdup (valueStr); + } else if (strcmp ("userSeed", key) == 0) { + song->userSeed = strdup (valueStr); + } else if (strcmp ("focusTraitId", key) == 0) { + song->focusTraitId = strdup (valueStr); + } else if (strcmp ("songTitle", key) == 0) { + song->title = strdup (valueStr); + } +} + +/* parses server response and updates handle + * @author PromyLOPh + * @added 2008-06-03 + * @param piano handle + * @param utf-8 string + * @return nothing + */ +void PianoXmlParseUserinfo (PianoHandle_t *ph, char *xml) { + xmlNode *docRoot = NULL; + xmlDocPtr doc = xmlReadDoc ((xmlChar *) xml, NULL, NULL, 0); + + if (doc == NULL) { + printf ("whoops... xml parser error\n"); + return; + } + + docRoot = xmlDocGetRootElement (doc); + + /* */ + xmlNode *structRoot = docRoot->children->children->children->children; + PianoXmlStructParser (structRoot, PianoXmlParseUserinfoCb, &ph->user); + + xmlFreeDoc (doc); + xmlCleanupParser(); +} + +/* parse stations returned by pandora + * @author PromyLOPh + * @added 2008-06-04 + * @param piano handle + * @param xml returned by pandora + * @return nothing + */ +void PianoXmlParseStations (PianoHandle_t *ph, char *xml) { + /* FIXME: copy & waste */ + xmlNode *docRoot = NULL, *curNode = NULL; + xmlDocPtr doc = xmlReadDoc ((xmlChar *) xml, NULL, NULL, 0); + + if (doc == NULL) { + printf ("whoops... xml parser error\n"); + return; + } + + docRoot = xmlDocGetRootElement (doc); + + /* */ + xmlNode *dataRoot = docRoot->children->children->children->children->children; + for (curNode = dataRoot->children; curNode; curNode = curNode->next) { + if (curNode->type == XML_ELEMENT_NODE && + xmlStrEqual ((xmlChar *) "value", curNode->name)) { + PianoStation_t *tmpStation = calloc (1, sizeof (*tmpStation)); + PianoXmlStructParser (curNode->children, + PianoXmlParseStationsCb, tmpStation); + /* start new linked list or append */ + if (ph->stations == NULL) { + ph->stations = tmpStation; + } else { + PianoStation_t *curStation = ph->stations; + while (curStation->next != NULL) { + curStation = curStation->next; + } + curStation->next = tmpStation; + } + } + } + + xmlFreeDoc (doc); + xmlCleanupParser(); +} + +void PianoXmlParsePlaylist (PianoHandle_t *ph, char *xml) { + /* FIXME: copy & waste */ + xmlNode *docRoot = NULL, *curNode = NULL; + xmlDocPtr doc = xmlReadDoc ((xmlChar *) xml, NULL, NULL, 0); + + if (doc == NULL) { + printf ("whoops... xml parser error\n"); + return; + } + + docRoot = xmlDocGetRootElement (doc); + + /* */ + xmlNode *dataRoot = docRoot->children->children->children->children->children; + for (curNode = dataRoot->children; curNode; curNode = curNode->next) { + if (curNode->type == XML_ELEMENT_NODE && + xmlStrEqual ((xmlChar *) "value", curNode->name)) { + PianoSong_t *tmpSong = calloc (1, sizeof (*tmpSong)); + PianoXmlStructParser (curNode->children, + PianoXmlParsePlaylistCb, tmpSong); + /* begin linked list or append */ + if (ph->playlist == NULL) { + ph->playlist = tmpSong; + } else { + PianoSong_t *curSong = ph->playlist; + while (curSong->next != NULL) { + curSong = curSong->next; + } + curSong->next = tmpSong; + } + } + } + + xmlFreeDoc (doc); + xmlCleanupParser(); +} diff --git a/libpiano/xml.h b/libpiano/xml.h new file mode 100644 index 0000000..c4eede8 --- /dev/null +++ b/libpiano/xml.h @@ -0,0 +1,30 @@ +/* +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. +*/ + +#ifndef _XML_H +#define _XML_H + +void PianoXmlParseUserinfo (PianoHandle_t *ph, char *xml); +void PianoXmlParseStations (PianoHandle_t *ph, char *xml); +void PianoXmlParsePlaylist (PianoHandle_t *ph, char *xml); + +#endif /* _XML_H */ diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..8f88440 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,6 @@ +bin_PROGRAMS = pianobar + +pianobar_SOURCES = main.c +pianobar_CPPFLAGS = ${LIBCURL_CFLAGS} ${LIBAO_CFLAGS} -I../libpiano +pianobar_LDADD = ${LIBCURL_LIBS} ${LIBAO_LIBS} ${LIBFAAD_LIBS} -lpthread ../libpiano/libpiano.la + diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..d125122 --- /dev/null +++ b/src/main.c @@ -0,0 +1,339 @@ +/* +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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct aacPlayer { + /* buffer */ + char *buffer; + size_t bufferFilled; + char lastBytes[4]; + /* got mdat atom */ + char dataMode; + char foundEsdsAtom; + char audioInitialized; + /* aac */ + NeAACDecHandle aacHandle; + unsigned long samplerate; + unsigned char channels; + /* audio out */ + ao_device *audioOutDevice; + char *url; + char finishedPlayback; + char doQuit; +}; + +void dumpBuffer (char *buf, size_t len) { + int i; + for (i = 0; i < len; i++) { + printf ("%02x ", buf[i] & 0xff); + } + printf ("\n"); +} + +/* FIXME: this is a huge block of _bad_ and buggy code */ +int playCurlCb (void *ptr, size_t size, size_t nmemb, void *stream) { + char *data = ptr; + struct aacPlayer *player = stream; + + if (player->doQuit) { + return -1; + } + + if (player->dataMode == 1) { + size_t bufferOffset = 0, aacBufferN; + char *aacDecoded, *aacBuffer; + NeAACDecFrameInfo frameInfo; + + aacBufferN = player->bufferFilled + nmemb; + aacBuffer = calloc (aacBufferN, sizeof (char)); + memcpy (aacBuffer, player->buffer, player->bufferFilled); + memcpy (aacBuffer + player->bufferFilled, data, nmemb * size); + + free (player->buffer); + + /* keep some bytes in buffer */ + while (bufferOffset < aacBufferN-500) { + //printf ("play buffer at %i/%i: ", bufferOffset, aacBufferN); + //dumpBuffer (aacBuffer+bufferOffset, 50); + /* FIXME: well, i think we need this block length table */ + aacDecoded = NeAACDecDecode(player->aacHandle, &frameInfo, + (unsigned char *) aacBuffer+bufferOffset, + aacBufferN-bufferOffset); + //printf ("bytesconsumed: %li\nerror: %i\nsamples: %lu\nsamplerate: %lu\n\n", frameInfo.bytesconsumed, frameInfo.error, frameInfo.samples, frameInfo.samplerate); + if (frameInfo.error != 0) { + printf ("error: %s\n\n", NeAACDecGetErrorMessage (frameInfo.error)); + break; + } + ao_play (player->audioOutDevice, aacDecoded, + frameInfo.samples*frameInfo.channels); + bufferOffset += frameInfo.bytesconsumed; + } + /* copy remaining bytes */ + player->buffer = calloc (aacBufferN - bufferOffset, sizeof (char)); + memcpy (player->buffer, aacBuffer+bufferOffset, + aacBufferN - bufferOffset); + player->bufferFilled = aacBufferN - bufferOffset; + //printf ("player->buffer (%i) = ", aacBufferN - bufferOffset); + //dumpBuffer (player->buffer, 50); + free (aacBuffer); + } else { + player->buffer = calloc (nmemb + sizeof (player->lastBytes), size); + /* we are going to find a 4-byte string, but curl sends fragments and + * if the identifier is cut into two pieces, we will get into big + * trouble... */ + memcpy (player->buffer, player->lastBytes, sizeof (player->lastBytes)); + memcpy (player->buffer+sizeof (player->lastBytes), data, size*nmemb); + + char *searchBegin = player->buffer; + + if (!player->foundEsdsAtom) { + while (searchBegin < player->buffer + nmemb) { + if (memcmp (searchBegin, "esds", 4) == 0) { + player->foundEsdsAtom = 1; + break; + } + searchBegin++; + } + } + if (player->foundEsdsAtom && !player->audioInitialized) { + /* FIXME: is this the correct way? */ + while (searchBegin < player->buffer + nmemb) { + if (memcmp (searchBegin, "\x05\x80\x80\x80", 4) == 0) { + ao_sample_format format; + int audioOutDriver; + + char err = NeAACDecInit2 (player->aacHandle, + (unsigned char *) searchBegin+1+4, 5, + &player->samplerate, &player->channels); + if (err != 0) { + printf ("whoops... %i\n", err); + return 1; + } + //printf ("samplerate: %li\nchannels: %i\n\n", + // player->samplerate, player->channels); + audioOutDriver = ao_default_driver_id(); + format.bits = 16; + format.channels = player->channels; + format.rate = player->samplerate; + format.byte_format = AO_FMT_LITTLE; + player->audioOutDevice = ao_open_live (audioOutDriver, &format, NULL); + player->audioInitialized = 1; + break; + } + searchBegin++; + } + } + if (player->audioInitialized) { + while (searchBegin < player->buffer + nmemb) { + if (memcmp (searchBegin, "mdat", 4) == 0) { + player->dataMode = 1; + memmove (player->buffer, searchBegin+4, nmemb - (searchBegin-player->buffer)); + player->bufferFilled = nmemb - (searchBegin-player->buffer); + //printf ("copied %i bytes: ", nmemb - (searchBegin-player->buffer)); + //dumpBuffer (player->buffer, 50); + break; + } + searchBegin++; + } + } + if (!player->dataMode) { + memcpy (player->lastBytes, data + (size * nmemb - sizeof (player->lastBytes)), + sizeof (player->lastBytes)); + //printf ("last bytes: "); + //dumpBuffer (player->lastBytes, 4); + free (player->buffer); + } + } + + return size*nmemb; +} + +void *threadPlayUrl (void *data) { + struct aacPlayer *player = data; + NeAACDecConfigurationPtr conf; + CURL *audioFd; + + audioFd = curl_easy_init (); + player->aacHandle = NeAACDecOpen(); + + conf = NeAACDecGetCurrentConfiguration(player->aacHandle); + conf->outputFormat = FAAD_FMT_16BIT; + conf->downMatrix = 1; + NeAACDecSetConfiguration(player->aacHandle, conf); + + curl_easy_setopt (audioFd, CURLOPT_URL, player->url); + curl_easy_setopt (audioFd, CURLOPT_WRITEFUNCTION, playCurlCb); + curl_easy_setopt (audioFd, CURLOPT_WRITEDATA, player); + /* at the moment we don't need publicity */ + curl_easy_setopt (audioFd, CURLOPT_USERAGENT, "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9pre) Gecko/2008051115 Firefox/3.0pre"); + curl_easy_perform (audioFd); + + free (player->buffer); + NeAACDecClose(player->aacHandle); + ao_close(player->audioOutDevice); + curl_easy_cleanup (audioFd); + + player->finishedPlayback = 1; + + return NULL; +} + +PianoStation_t *selectStation (PianoHandle_t *ph) { + PianoStation_t *curStation; + size_t i; + + printf ("which station do you want to listen to?\n"); + i = 0; + curStation = ph->stations; + while (curStation != NULL) { + printf ("%2i) %s\n", i, curStation->name); + curStation = curStation->next; + i++; + } + scanf ("%i", &i); + curStation = ph->stations; + while (curStation != NULL && i > 0) { + curStation = curStation->next; + i--; + } + return curStation; +} + +int main (int argc, char **argv) { + PianoHandle_t ph; + struct aacPlayer player; + char doQuit = 0; + PianoSong_t *curSong = NULL; + PianoStation_t *curStation; + struct termios termopts; + + /* init some things */ + curl_global_init (CURL_GLOBAL_SSL); + ao_initialize(); + PianoInit (&ph); + + /* no buffering for stdin */ + tcgetattr (fileno (stdin), &termopts); + termopts.c_lflag &= ~ICANON; + tcsetattr(fileno (stdin), TCSANOW, &termopts); + setvbuf (stdin, NULL, _IONBF, 1); + + PianoConnect (&ph, argv[1], argv[2]); + PianoGetStations (&ph); + printf ("webAuthToken: %s\nauthToken: %s\nlistenerId: %s\n", ph.user.webAuthToken, ph.user.authToken, ph.user.listenerId); + + /* select station */ + curStation = selectStation (&ph); + printf ("playing station %s\n", curStation->name); + PianoGetPlaylist (&ph, curStation->id); + + curSong = ph.playlist; + /* play first track */ + while (!doQuit) { + PianoSong_t *lastSong = NULL; + pthread_t playerThread; + printf ("%s by %s\n", curSong->title, curSong->artist); + memset (&player, 0, sizeof (player)); + player.url = strdup (curSong->audioUrl); + + /* start player */ + pthread_create (&playerThread, NULL, threadPlayUrl, &player); + + /* in the meantime: wait for user actions */ + while (!player.finishedPlayback) { + struct pollfd polls = {fileno (stdin), POLLIN, POLLIN}; + char buf; + + if (poll (&polls, 1, 1000) > 0) { + read (fileno (stdin), &buf, sizeof (buf)); + switch (buf) { + case '?': + printf ("n\tnext track\nq\tquit\ns\tchange station\n"); + break; + + case 'b': + player.doQuit = 1; + PianoRateTrack (&ph, curStation, curSong, + PIANO_RATE_BAN); + PianoDestroyPlaylist (&ph); + break; + + case 'l': + PianoRateTrack (&ph, curStation, curSong, + PIANO_RATE_LOVE); + break; + + case 'n': + player.doQuit = 1; + break; + + case 'q': + doQuit = 1; + player.doQuit = 1; + break; + + case 's': + /* FIXME: does not work, segfault... */ + player.doQuit = 1; + PianoDestroyPlaylist (&ph); + curStation = selectStation (&ph); + printf ("changed station to %s\n", curStation->name); + break; + + } + } + } + pthread_join (playerThread, NULL); + + free (player.url); + /* what's next? */ + lastSong = curSong; + curSong = lastSong->next; + if (curSong == NULL && !doQuit) { + printf ("receiving new playlist\n"); + PianoGetPlaylist (&ph, curStation->id); + curSong = lastSong->next; + if (curSong == NULL) { + /* no tracks left */ + doQuit = 1; + } + } + } + + /* destroy everything (including the world...) */ + PianoDestroy (&ph); + curl_global_cleanup (); + ao_shutdown(); + + return 0; +} -- cgit v1.2.3