diff options
| -rw-r--r-- | AUTHORS | 2 | ||||
| -rw-r--r-- | BUGS | 6 | ||||
| -rw-r--r-- | COPYING | 19 | ||||
| -rw-r--r-- | ChangeLog | 15 | ||||
| -rw-r--r-- | INSTALL | 25 | ||||
| -rw-r--r-- | Makefile.am | 3 | ||||
| -rw-r--r-- | NEWS | 4 | ||||
| -rw-r--r-- | RoadMap | 18 | ||||
| -rwxr-xr-x | autogen.sh | 7 | ||||
| -rw-r--r-- | configure.in | 37 | ||||
| -rw-r--r-- | libpiano/Makefile.am | 6 | ||||
| -rw-r--r-- | libpiano/const.h | 35 | ||||
| -rw-r--r-- | libpiano/crypt.c | 283 | ||||
| -rw-r--r-- | libpiano/crypt.h | 29 | ||||
| -rw-r--r-- | libpiano/crypt_key_input.h | 1071 | ||||
| -rw-r--r-- | libpiano/crypt_key_output.h | 1076 | ||||
| -rw-r--r-- | libpiano/http.c | 87 | ||||
| -rw-r--r-- | libpiano/http.h | 28 | ||||
| -rw-r--r-- | libpiano/main.c | 249 | ||||
| -rw-r--r-- | libpiano/main.h | 27 | ||||
| -rw-r--r-- | libpiano/piano.h | 132 | ||||
| -rw-r--r-- | libpiano/xml.c | 278 | ||||
| -rw-r--r-- | libpiano/xml.h | 30 | ||||
| -rw-r--r-- | src/Makefile.am | 6 | ||||
| -rw-r--r-- | src/main.c | 339 | 
25 files changed, 3812 insertions, 0 deletions
| @@ -0,0 +1,2 @@ +Reverse engineering, main code: +	Lars-Dominik Braun <PromyLOPh@gmail.com> @@ -0,0 +1,6 @@ +Bugs +==== + +A lot, I think. But none of them are found yet... + +Report them to: PromyLOPh@gmail.com @@ -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 @@ -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 @@ -0,0 +1,4 @@ +News +==== + +Nothing happened yet... @@ -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 <string.h> +#include <stdio.h> +#include <stdlib.h> + +#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 <curl/curl.h> +#include <stdlib.h> +#include <string.h> + +#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 <curl/curl.h> +#include <string.h> +#include <stdlib.h> +#include <time.h> + +#include "const.h" +#include "main.h" +#include "piano.h" +#include "http.h" +#include "xml.h" + +char *PianoEncryptString (char *strInput); + +/*	initialize piano handle, set up curl handle and settings + *	@author PromyLOPh + *	@added 2008-06-05 + *	@param piano handle + *	@return nothing + */ +void PianoInit (PianoHandle_t *ph) { +	memset (ph, 0, sizeof (*ph)); +	ph->curlHandle = curl_easy_init (); +	/* FIXME: 64-bit may make this hack useless */ +	snprintf (ph->routeId, sizeof (ph->routeId), "%07liP", time (NULL)>>8); +	/* at the moment we don't need publicity */ +	curl_easy_setopt (ph->curlHandle, CURLOPT_USERAGENT, PIANO_USERAGENT); +	/* set tor as control connection proxy */ +	curl_easy_setopt (ph->curlHandle, CURLOPT_PROXY, "localhost:9050"); +	curl_easy_setopt (ph->curlHandle, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4A); +} + +/*	free complete station list + *	@author PromyLOPh + *	@added 2008-06-09 + *	@param piano handle + */ +void PianoDestroyStations (PianoHandle_t *ph) { +	PianoStation_t *curStation, *lastStation; + +	curStation = ph->stations; +	while (curStation != NULL) { +		free (curStation->name); +		free (curStation->id); +		lastStation = curStation; +		curStation = curStation->next; +		memset (lastStation, 0, sizeof (*lastStation)); +		free (lastStation); +	} +} + +/* FIXME: copy & waste */ +/*	free _all_ elements of playlist + *	@author PromyLOPh + *	@added 2008-06-09 + *	@param piano handle + *	@return nothing + */ +void PianoDestroyPlaylist (PianoHandle_t *ph) { +	PianoSong_t *curSong, *lastSong; + +	curSong = ph->playlist; +	while (curSong != NULL) { +		free (curSong->audioUrl); +		free (curSong->artist); +		free (curSong->focusTraitId); +		free (curSong->matchingSeed); +		free (curSong->musicId); +		free (curSong->title); +		free (curSong->userSeed); +		lastSong = curSong; +		curSong = curSong->next; +		memset (lastSong, 0, sizeof (*lastSong)); +		free (lastSong); +	} +} + +/*	frees the whole piano handle structure + *	@author PromyLOPh + *	@added 2008-06-05 + *	@param piano handle + *	@return nothing + */ +void PianoDestroy (PianoHandle_t *ph) { +	curl_easy_cleanup (ph->curlHandle); +	/* FIXME: only free if pointer != NULL */ +	free (ph->user.webAuthToken); +	free (ph->user.authToken); +	free (ph->user.listenerId); + +	PianoDestroyStations (ph); +	PianoDestroyPlaylist (ph); +	memset (ph, 0, sizeof (*ph)); +} + +/*	authenticates user + *	@author PromyLOPh + *	@added 2008-06-05 + *	@param piano handle + *	@param username (utf-8 encoded) + *	@param password (plaintext, utf-8 encoded) + *	@return nothing + */ +void PianoConnect (PianoHandle_t *ph, char *user, char *password) { +	/* sync */ +	char url[PIANO_URL_BUFFER_SIZE]; +	char *requestStr = PianoEncryptString ("<?xml version=\"1.0\"?>" +			"<methodCall><methodName>misc.sync</methodName>" +			"<params></params></methodCall>"); +	char *retStr, requestStrPlain[10000]; + +	/* sync (is the return value used by pandora? for now: ignore result) */ +	snprintf (url, sizeof (url), PIANO_RPC_URL "rid=%s&method=sync", +			ph->routeId); +	PianoHttpPost (ph->curlHandle, url, requestStr, &retStr); +	free (requestStr); +	free (retStr); + +	/* authenticate */ +	snprintf (requestStrPlain, sizeof (requestStrPlain),  +			"<?xml version=\"1.0\"?><methodCall>" +			"<methodName>listener.authenticateListener</methodName>" +			"<params><param><value><int>%li</int></value></param>" +			"<param><value><string>%s</string></value></param>" +			"<param><value><string>%s</string></value></param>" +			"</params></methodCall>", time (NULL), user, password); +	requestStr = PianoEncryptString (requestStrPlain); +	snprintf (url, sizeof (url), PIANO_SECURE_RPC_URL "rid=%s" +			"&method=authenticateListener", ph->routeId); +	PianoHttpPost (ph->curlHandle, url, requestStr, &retStr); +	PianoXmlParseUserinfo (ph, retStr); + +	free (requestStr); +	free (retStr); +} + +/*	get all stations for authenticated user (so: PianoConnect needs to + *	be run before) + *	@author PromyLOPh + *	@added 2008-06-05 + *	@param piano handle filled with some authentication data by PianoConnect + *	@return nothing + */ +void PianoGetStations (PianoHandle_t *ph) { +	char xmlSendBuf[10000], url[PIANO_URL_BUFFER_SIZE]; +	char *requestStr, *retStr; + +	snprintf (xmlSendBuf, sizeof (xmlSendBuf), "<?xml version=\"1.0\"?>" +			"<methodCall><methodName>station.getStations</methodName>" +			"<params><param><value><int>%li</int></value></param>" +			"<param><value><string>%s</string></value></param>" +			"</params></methodCall>", time (NULL), ph->user.authToken); +	requestStr = PianoEncryptString (xmlSendBuf); +	snprintf (url, sizeof (url), PIANO_RPC_URL +			"rid=%s&lid=%s&method=getStations", ph->routeId, +			ph->user.listenerId); +	PianoHttpPost (ph->curlHandle, url, requestStr, &retStr); +	PianoXmlParseStations (ph, retStr); +	free (retStr); +	free (requestStr); +} + +/*	get next songs for station (usually four tracks) + *	@author PromyLOPh + *	@added 2008-06-05 + *	@param piano handle + *	@param station id + *	@return nothing yet + */ +void PianoGetPlaylist (PianoHandle_t *ph, char *stationId) { +	char xmlSendBuf[10000], url[PIANO_URL_BUFFER_SIZE]; +	char *requestStr, *retStr; + +	/* FIXME: remove static numbers */ +	snprintf (xmlSendBuf, sizeof (xmlSendBuf), "<?xml version=\"1.0\"?>" +			"<methodCall><methodName>playlist.getFragment</methodName>" +			"<params><param><value><int>%li</int></value></param>" +			"<param><value><string>%s</string></value></param>" +			"<param><value><string>%s</string></value></param>" +			"<param><value><string>15941546</string></value></param>" +			"<param><value><string>181840822</string></value></param>" +			"<param><value><string></string></value></param>" +			"<param><value><string></string></value></param>" +			"<param><value><string>aacplus</string></value></param>" +			"</params></methodCall>", time (NULL), ph->user.authToken, +			stationId); +	requestStr = PianoEncryptString (xmlSendBuf); +	snprintf (url, sizeof (url), PIANO_RPC_URL +			"rid=%s&lid=%s&method=getFragment&arg1=%s&arg2=15941546" +			"&arg3=181840822&arg4=&arg5=&arg6=aacplus", ph->routeId, +			ph->user.listenerId, stationId); +	PianoHttpPost (ph->curlHandle, url, requestStr, &retStr); +	PianoXmlParsePlaylist (ph, retStr); +	free (retStr); +	free (requestStr); +} + +void PianoRateTrack (PianoHandle_t *ph, PianoStation_t *station, +		PianoSong_t *song, PianoSongRating_t rating) { +	char xmlSendBuf[10000], url[PIANO_URL_BUFFER_SIZE]; +	char *requestStr, *retStr; + +	snprintf (xmlSendBuf, sizeof (xmlSendBuf), "<?xml version=\"1.0\"?>" +			"<methodCall><methodName>station.addFeedback</methodName>" +			"<params><param><value><int>%li</int></value></param>" +			"<param><value><string>%s</string></value></param>" +			"<param><value><string>%s</string></value></param>" +			"<param><value><string>%s</string></value></param>" +			"<param><value><string>%s</string></value></param>" +			"<param><value><string>%s</string></value></param>" +			"<param><value><string>%s</string></value></param>" +			"<param><value><boolean>%i</boolean></value></param>" +			"<param><value><boolean>0</boolean></value></param>" +			"</params></methodCall>", time (NULL), ph->user.authToken, +			station->id, song->musicId, song->matchingSeed, song->userSeed, +			song->focusTraitId, (rating == PIANO_RATE_LOVE) ? 1 : 0); +	requestStr = PianoEncryptString (xmlSendBuf); +	snprintf (url, sizeof (url), PIANO_RPC_URL +			"rid=%s&lid=%s&method=addFeedback&arg1=%s&arg2=%s" +			"&arg3=%s&arg4=%s&arg5=%s&arg6=%s&arg7=false", ph->routeId, +			ph->user.listenerId, station->id, song->musicId, +			song->matchingSeed, song->userSeed, song->focusTraitId, +			(rating == PIANO_RATE_LOVE) ? "true" : "false"); +	PianoHttpPost (ph->curlHandle, url, requestStr, &retStr); +	/* FIXME: check answer (success = <?xml version="1.0" encoding="UTF-8"?><methodResponse><params><param><value>1</value></param></params></methodResponse> ) */ +	free (requestStr); +	free (retStr); +} 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 <curl/curl.h> + +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 <libxml/parser.h> +#include <libxml/tree.h> +#include <stdio.h> +#include <string.h> + +#include "piano.h" +#include "crypt.h" + +/*	parses things like this: + *	<struct> + *		<member> + *			<name /> + *			<value /> + *		</member> + *		<!-- ... --> + *	</struct> + *	@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 <name> as + *			string, content of <value> as xmlNode (may contain other nodes + *			or text), additional data used by callback(); don't forget + *			to *copy* data taken from <name> or <value> 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 <member> 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 <name> or <value> */ +			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 <value /> 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 <boolean> or <string>, just +	 * ignore them... */ +	if (value->content != NULL) { +		valueStr = (char *) value->content; +	} else if (value->children != NULL && +			value->children->content != NULL) { +		 valueStr = (char *) value->children->content; +	} +	/* 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 <boolean> or <string>, just +	 * ignore them... */ +	if (value->content != NULL) { +		valueStr = (char *) value->content; +	} else if (value->children != NULL && +			value->children->content != NULL) { +		 valueStr = (char *) value->children->content; +	} +	if (strcmp ("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 <boolean> or <string>, just +	 * ignore them... */ +	if (value->content != NULL) { +		valueStr = (char *) value->content; +	} else if (value->children != NULL && +			value->children->content != NULL) { +		 valueStr = (char *) value->children->content; +	} +	if (strcmp ("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); + +	/* <methodResponse> <params> <param> <value> <struct> */ +	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); + +	/* <methodResponse> <params> <param> <value> <array> <data> */ +	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); + +	/* <methodResponse> <params> <param> <value> <array> <data> */ +	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 <piano.h> +#include <curl/curl.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <ao/ao.h> +#include <neaacdec.h> +#include <pthread.h> +#include <unistd.h> +#include <termios.h> +#include <poll.h> + +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; +} | 
