1
0

iPodSD.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523
  1. #include "iPodSD.h"
  2. #include <math.h>
  3. #include <assert.h>
  4. // get 3 bytes from data (used in iTunesSD1)
  5. static __forceinline unsigned long get3(const uint8_t * data)
  6. {
  7. unsigned long ret = 0;
  8. ret += ((unsigned long) data[0]) << 16;
  9. ret += ((unsigned long) data[1]) << 8;
  10. ret += ((unsigned long) data[2]);
  11. return ret;
  12. }
  13. //write 3 bytes normal (used in iTunesSD1)
  14. static __forceinline void put3(const unsigned long number, uint8_t * data)
  15. {
  16. data[0] = (uint8_t)(number >> 16) & 0xff;
  17. data[1] = (uint8_t)(number >> 8) & 0xff;
  18. data[2] = (uint8_t)number & 0xff;
  19. }
  20. // pass data and ptr, updates ptr automatically (by reference)
  21. static __forceinline void write_uint64_t(uint8_t *data, size_t &offset, uint64_t value)
  22. {
  23. memcpy(&data[offset], &value, 8);
  24. offset+=8;
  25. }
  26. // pass data and ptr, updates ptr automatically (by reference)
  27. static __forceinline void write_uint32_t(uint8_t *data, size_t &offset, uint32_t value)
  28. {
  29. memcpy(&data[offset], &value, 4);
  30. offset+=4;
  31. }
  32. // pass data and ptr, updates ptr automatically (by reference)
  33. static __forceinline void write_uint16_t(uint8_t *data, size_t &offset, uint16_t value)
  34. {
  35. memcpy(&data[offset], &value, 2);
  36. offset+=2;
  37. }
  38. // pass data and ptr, updates ptr automatically (by reference)
  39. static __forceinline void write_uint8_t(uint8_t *data, size_t &offset, uint8_t value)
  40. {
  41. data[offset++] = value;
  42. }
  43. // pass data and ptr, updates ptr automatically (by reference)
  44. static __forceinline void write_header(uint8_t *data, size_t &offset, const char *header)
  45. {
  46. data[offset++] = header[0];
  47. data[offset++] = header[1];
  48. data[offset++] = header[2];
  49. data[offset++] = header[3];
  50. }
  51. // Case insensitive version of wcsstr
  52. static wchar_t *wcsistr (const wchar_t *s1, const wchar_t *s2)
  53. {
  54. wchar_t *cp = (wchar_t*) s1;
  55. wchar_t *s, *t, *endp;
  56. wchar_t l, r;
  57. endp = (wchar_t*)s1 + ( lstrlen(s1) - lstrlen(s2)) ;
  58. while (cp && *cp && (cp <= endp))
  59. {
  60. s = cp;
  61. t = (wchar_t*)s2;
  62. while (s && *s && t && *t)
  63. {
  64. l = towupper(*s);
  65. r = towupper(*t);
  66. if (l != r)
  67. break;
  68. s++, t++;
  69. }
  70. if (*t == 0)
  71. return cp;
  72. cp = CharNext(cp);
  73. }
  74. return NULL;
  75. }
  76. //////////////////////////////////////////////////////////////////////
  77. // iTunesSD1 - Classes for dealing with the iPodShuffle
  78. //////////////////////////////////////////////////////////////////////
  79. iTunesSD1::iTunesSD1()
  80. {
  81. }
  82. iTunesSD1::~iTunesSD1()
  83. {
  84. }
  85. long iTunesSD1::write(const iPod_mhlt::mhit_map_t *songs, unsigned char * data, const unsigned long datasize)
  86. {
  87. #ifdef IPODDB_PROFILER
  88. profiler(iPodDB__iTunesSD_write);
  89. #endif
  90. const unsigned int numsongs = songs->size();
  91. const unsigned int total_size = 18 + (numsongs * 558);
  92. ASSERT(datasize >= total_size);
  93. if(datasize < total_size)
  94. return(-1);
  95. long ptr=0;
  96. put3(numsongs, &data[ptr]);
  97. ptr+=3;
  98. put3(0x010600, &data[ptr]);
  99. ptr+=3;
  100. put3(0x12, &data[ptr]);
  101. ptr+=3;
  102. put3(0, &data[ptr]);
  103. ptr+=3;
  104. put3(0, &data[ptr]);
  105. ptr+=3;
  106. put3(0, &data[ptr]);
  107. ptr+=3;
  108. iPod_mhlt::mhit_map_t::const_iterator begin = songs->begin();
  109. iPod_mhlt::mhit_map_t::const_iterator end = songs->end();
  110. for(iPod_mhlt::mhit_map_t::const_iterator it = begin; it != end; it++)
  111. {
  112. iPod_mhit *m = ((*it).second);
  113. iTunesSD_Song song(m);
  114. long ret = song.write(&data[ptr], datasize - ptr);
  115. if (ret < 0)
  116. return ret;
  117. ptr += ret;
  118. }
  119. return(ptr);
  120. }
  121. iTunesSD_Song::iTunesSD_Song(const iPod_mhit *m) : size_total(0x22e), starttime(0), stoptime(0), volume(0x64), filetype(0), playflags(iTunesSD_Song::SHUFFLE)
  122. {
  123. memset(filename, 0, (SDSONG_FILENAME_LEN + 1) * sizeof(wchar_t));
  124. iPod_mhod *mhod = m->FindString(MHOD_LOCATION);
  125. ASSERT(mhod);
  126. if(mhod)
  127. {
  128. // Convert from HFS format (:iPod_Control:Music:F00:filename) to quasi-FAT format (/iPod_Control/Music/F00/filename) filepaths
  129. SetFilename(mhod->str);
  130. wchar_t *w = filename;
  131. while(w && *w != '\0')
  132. {
  133. if(*w == ':')
  134. *w = '/';
  135. w = CharNext(w);
  136. }
  137. SetStartTime(m->starttime);
  138. SetStopTime(m->stoptime);
  139. int volume = (int)m->volume;
  140. // If Sound Check information is present, use that instead of volume
  141. if(m->soundcheck != 0)
  142. {
  143. // This code converts SoundCheck back into a gain value, then into a -255 to 255 mhit::volume value
  144. const double gain = -10.0 * log10(m->soundcheck / 1000.0);
  145. volume = (int)(gain * 12.75); // XXX - this might not be the best way to convert the gain value...
  146. }
  147. if(volume < -255)
  148. volume = -255;
  149. else if(volume > 255)
  150. volume = 255;
  151. // Convert the volume value into a percentage for SetVolume
  152. SetVolume((int)((double)volume / 2.55));
  153. // To determine the filetype, first check the MHOD_FILETYPE type. If that isn't available, fallback to file extension
  154. iPod_mhod *mtype = m->FindString(MHOD_FILETYPE);
  155. if(mtype != NULL)
  156. {
  157. if(wcsistr(mtype->str, L"MPEG") != NULL || wcsistr(mtype->str, L"MP3") != NULL)
  158. filetype = iTunesSD_Song::MP3;
  159. else if(wcsistr(mtype->str, L"AAC") != NULL)
  160. filetype = iTunesSD_Song::AAC;
  161. else if(wcsistr(mtype->str, L"WAV") != NULL)
  162. filetype = iTunesSD_Song::WAV;
  163. }
  164. if(filetype == 0)
  165. {
  166. if(wcsistr(mhod->str, L".mp3") != NULL)
  167. filetype = iTunesSD_Song::MP3;
  168. else if(wcsistr(mhod->str, L".m4a") != NULL || wcsistr(mhod->str, L".m4b") != NULL || wcsistr(mhod->str, L".m4p") != NULL)
  169. filetype = iTunesSD_Song::AAC;
  170. else if(wcsistr(mhod->str, L".wav") != NULL)
  171. filetype = iTunesSD_Song::WAV;
  172. }
  173. ASSERT(filetype != 0);
  174. if(filename == 0)
  175. filetype = iTunesSD_Song::MP3; // Default to mp3
  176. if(wcsistr(mhod->str, L".m4b") != NULL)
  177. playflags = iTunesSD_Song::BOOKMARKABLE; // Only playback in normal mode
  178. else
  179. playflags = iTunesSD_Song::SHUFFLE; // Playable in normal/shuffle modes, but not bookmarkable
  180. }
  181. }
  182. long iTunesSD_Song::write(unsigned char * data, const unsigned long datasize)
  183. {
  184. #ifdef IPODDB_PROFILER
  185. profiler(iPodDB__iTunesSD_Song_write);
  186. #endif
  187. long ptr=0;
  188. ASSERT(size_total == 0x22e);
  189. ASSERT(filetype != 0);
  190. put3(size_total, &data[ptr]);
  191. ptr+=3;
  192. put3(0x005aa501, &data[ptr]);
  193. ptr+=3;
  194. put3(starttime, &data[ptr]);
  195. ptr+=3;
  196. put3(0, &data[ptr]);
  197. ptr+=3;
  198. put3(0, &data[ptr]);
  199. ptr+=3;
  200. put3(stoptime, &data[ptr]);
  201. ptr+=3;
  202. put3(0, &data[ptr]);
  203. ptr+=3;
  204. put3(0, &data[ptr]);
  205. ptr+=3;
  206. put3(volume, &data[ptr]);
  207. ptr+=3;
  208. put3(filetype, &data[ptr]);
  209. ptr+=3;
  210. put3(0x200, &data[ptr]);
  211. ptr+=3;
  212. const unsigned int bufSize = (SDSONG_FILENAME_LEN + 1) * sizeof(wchar_t);
  213. memcpy(&data[ptr], filename, bufSize);
  214. ptr+=bufSize;
  215. put3(playflags, &data[ptr]);
  216. ptr+=3;
  217. ASSERT(size_total == ptr);
  218. return(ptr);
  219. }
  220. void iTunesSD_Song::SetFilename(const wchar_t *filename)
  221. {
  222. #ifdef IPODDB_PROFILER
  223. profiler(iPodDB__iTunesStats_SetFilename);
  224. #endif
  225. ASSERT(filename != NULL);
  226. if(filename == NULL)
  227. return;
  228. if(filename)
  229. {
  230. lstrcpyn(this->filename, filename, SDSONG_FILENAME_LEN);
  231. }
  232. else
  233. {
  234. memset(this->filename, 0, SDSONG_FILENAME_LEN * sizeof(wchar_t));
  235. }
  236. }
  237. // Accepts values from -100 to 100, with 0 meaning no volume change
  238. void iTunesSD_Song::SetVolume(const int percent)
  239. {
  240. int p = percent;
  241. if(p > 100)
  242. p = 100;
  243. else if(p < -100)
  244. p = -100;
  245. // Volume ranges from 0 (-100%) to 100 (0%) to 200 (100%)
  246. volume = (unsigned int)(percent + 100);
  247. }
  248. /* Shadow DB version 2 */
  249. long iTunesSD2::write(const iPod_mhlt *songs, const iPod_mhlp *playlists, unsigned char * data, const unsigned long datasize)
  250. {
  251. uint32_t numsongs = songs->GetChildrenCount();
  252. uint32_t numplaylists = playlists->GetChildrenCount();
  253. size_t offset=0;
  254. size_t ptr=0;
  255. if (datasize < 64)
  256. return -1;
  257. write_header(data, ptr, "bdhs");
  258. write_uint32_t(data, ptr, 0x02000003); /* also have seen 0x02010001, perhaps a DB version number? */
  259. write_uint32_t(data, ptr, 64); /* length of header */
  260. write_uint32_t(data, ptr, numsongs);
  261. write_uint32_t(data, ptr, numplaylists); /* number of playlists */
  262. write_uint32_t(data, ptr, 0);
  263. write_uint32_t(data, ptr, 0);
  264. write_uint8_t(data, ptr, 0); /* volume limit */
  265. write_uint8_t(data, ptr, 1); /* voiceover */
  266. write_uint16_t(data, ptr, 0);
  267. write_uint32_t(data, ptr, numsongs); /* TODO number of tracks w/o podcasts and audiobooks*/
  268. write_uint32_t(data, ptr, 64); /* track header offset */
  269. write_uint32_t(data, ptr, 64+20 + numsongs*4+iTunesSD2_Song::header_size*numsongs); /* playlist header offset */
  270. write_uint32_t(data, ptr, 0);
  271. write_uint32_t(data, ptr, 0);
  272. write_uint32_t(data, ptr, 0);
  273. write_uint32_t(data, ptr, 0);
  274. write_uint32_t(data, ptr, 0);
  275. offset = 64;
  276. uint32_t hths_header_size = 20+numsongs*4;
  277. if (datasize - ptr < hths_header_size)
  278. return -1;
  279. write_header(data, ptr, "hths");
  280. write_uint32_t(data, ptr, hths_header_size); /* header length */
  281. write_uint32_t(data, ptr, numsongs);
  282. write_uint32_t(data, ptr, 0);
  283. write_uint32_t(data, ptr, 0);
  284. offset += hths_header_size;
  285. /* positions for each track */
  286. for (size_t i=0;i<numsongs;i++)
  287. {
  288. write_uint32_t(data, ptr, offset + iTunesSD2_Song::header_size * i);
  289. }
  290. /* write tracks */
  291. for (uint32_t i=0;i<numsongs;i++)
  292. {
  293. iPod_mhit *m = songs->GetTrack(i);
  294. long ret = iTunesSD2_Song::write(m, &data[ptr], datasize - ptr);
  295. if (ret < 0)
  296. return ret;
  297. ptr += ret;
  298. offset += ret;
  299. }
  300. uint32_t podcast_playlist_count=0;
  301. for (size_t i=0;i<numplaylists;i++)
  302. {
  303. iPod_mhyp *p = playlists->GetPlaylist(i);
  304. if (p->podcastflag)
  305. podcast_playlist_count++;
  306. }
  307. uint32_t hphs_header_size = 20 + numplaylists*4;
  308. if (datasize - ptr < hphs_header_size)
  309. return -1;
  310. write_header(data, ptr, "hphs");
  311. write_uint32_t(data, ptr, hphs_header_size); /* header length */
  312. write_uint32_t(data, ptr, numplaylists);
  313. write_uint16_t(data, ptr, 0);
  314. write_uint16_t(data, ptr, numplaylists-podcast_playlist_count); /* non-podcast playlists */
  315. write_uint16_t(data, ptr, 1); /* master playlists */
  316. write_uint16_t(data, ptr, numplaylists); /* non-audiobook playlists */
  317. offset += hphs_header_size;
  318. /* write offsets for each track */
  319. for (size_t i=0;i<numplaylists;i++)
  320. {
  321. iPod_mhyp *p = playlists->GetPlaylist(i);
  322. write_uint32_t(data, ptr, offset);
  323. offset += p->GetMhipChildrenCount()*4 + 44;
  324. }
  325. iPod_mhyp *master_playlist = playlists->GetPlaylist(0);
  326. /* write playlists */
  327. for (size_t i=0;i<numplaylists;i++)
  328. {
  329. iPod_mhyp *p = playlists->GetPlaylist(i);
  330. long ret = iTunesSD2_Playlist::write(master_playlist, p, &data[ptr], datasize - ptr);
  331. if (ret < 0)
  332. return ret;
  333. ptr += ret;
  334. }
  335. return ptr;
  336. }
  337. uint32_t iTunesSD2_Song::header_size = 372;
  338. long iTunesSD2_Song::write(const iPod_mhit *mhit, unsigned char *data, const unsigned long datasize)
  339. {
  340. if (datasize < header_size)
  341. return -1;
  342. size_t ptr=0;
  343. write_header(data, ptr, "rths");
  344. write_uint32_t(data, ptr, header_size); /* length of header */
  345. write_uint32_t(data, ptr, mhit->starttime); /* start time, in milliseconds */
  346. write_uint32_t(data, ptr, mhit->stoptime); /* stop time, in milliseconds */
  347. write_uint32_t(data, ptr, mhit->volume); /* volume */
  348. switch(mhit->filetype)
  349. {
  350. case FILETYPE_WAV:
  351. write_uint32_t(data, ptr, iTunesSD_Song::WAV); /* file type */
  352. break;
  353. case FILETYPE_M4A:
  354. case 0x4d344220:
  355. case 0x4d345020:
  356. write_uint32_t(data, ptr, iTunesSD_Song::AAC); /* file type */
  357. break;
  358. case FILETYPE_MP3:
  359. default:
  360. write_uint32_t(data, ptr, iTunesSD_Song::MP3); /* file type */
  361. break;
  362. }
  363. iPod_mhod *mhod = mhit->FindString(MHOD_LOCATION);
  364. char filename[256] = {0};
  365. int converted = WideCharToMultiByte(CP_UTF8, 0, mhod->str, -1, filename, 256, 0, 0);
  366. for (int i=0;i<converted;i++)
  367. {
  368. if (filename[i] == ':')
  369. filename[i] = '/';
  370. }
  371. memcpy(&data[ptr], filename, converted);
  372. ptr+=converted;
  373. memset(&data[ptr], 0, 256-converted);
  374. ptr+=256-converted;
  375. write_uint32_t(data, ptr, mhit->bookmarktime); /* bookmark time */
  376. write_uint8_t(data, ptr, 0); /* skip flag */
  377. write_uint8_t(data, ptr, mhit->rememberPosition); /* remember playback position */
  378. write_uint8_t(data, ptr, 0); /* part of gapless album */
  379. write_uint8_t(data, ptr, 0);
  380. write_uint32_t(data, ptr, mhit->pregap); /* pre-gap */
  381. write_uint32_t(data, ptr, mhit->postgap); /* post-gap */
  382. write_uint64_t(data, ptr, mhit->samplecount); /* number of samples */
  383. write_uint32_t(data, ptr, mhit->gaplessData); /* gapless data */
  384. write_uint32_t(data, ptr, 0);
  385. write_uint32_t(data, ptr, mhit->album_id); /* album ID */
  386. write_uint16_t(data, ptr, mhit->tracknum); /* track number */
  387. write_uint16_t(data, ptr, mhit->cdnum); /* disc number */
  388. write_uint32_t(data, ptr, 0);
  389. write_uint32_t(data, ptr, 0);
  390. write_uint64_t(data, ptr, mhit->dbid); /* dbid */
  391. write_uint32_t(data, ptr, 0); /* artist ID */
  392. write_uint32_t(data, ptr, 0);
  393. write_uint32_t(data, ptr, 0);
  394. write_uint32_t(data, ptr, 0);
  395. write_uint32_t(data, ptr, 0);
  396. write_uint32_t(data, ptr, 0);
  397. write_uint32_t(data, ptr, 0);
  398. write_uint32_t(data, ptr, 0);
  399. write_uint32_t(data, ptr, 0);
  400. return ptr;
  401. }
  402. long iTunesSD2_Playlist::write(const iPod_mhyp *master_playlist, const iPod_mhyp *playlist, unsigned char * data, const unsigned long datasize)
  403. {
  404. size_t ptr=0;
  405. uint32_t tracks = playlist->GetMhipChildrenCount();
  406. uint32_t header_size = 44 + tracks*4;
  407. if (datasize < header_size)
  408. return -1;
  409. write_header(data, ptr, "lphs");
  410. write_uint32_t(data, ptr, header_size); /* header length */
  411. write_uint32_t(data, ptr, tracks); /* number of tracks */
  412. /* number of music tracks TODO: special handling for master playlist */
  413. if (playlist->podcastflag)
  414. write_uint32_t(data, ptr, 0);
  415. else
  416. write_uint32_t(data, ptr, tracks);
  417. write_uint64_t(data, ptr, playlist->playlistID); /* playlist ID */
  418. /* playlist type */
  419. if (playlist->podcastflag)
  420. write_uint32_t(data, ptr, 3); /* podcast */
  421. else if (playlist->hidden)
  422. write_uint32_t(data, ptr, 1); /* master playlist */
  423. else
  424. write_uint32_t(data, ptr, 2); /* normal */
  425. write_uint32_t(data, ptr, 0);
  426. write_uint32_t(data, ptr, 0);
  427. write_uint32_t(data, ptr, 0);
  428. write_uint32_t(data, ptr, 0);
  429. if (master_playlist == playlist)
  430. {
  431. for (uint32_t i=0;i<tracks;i++)
  432. {
  433. write_uint32_t(data, ptr, i);
  434. }
  435. }
  436. else
  437. {
  438. for (uint32_t i=0;i<tracks;i++)
  439. {
  440. iPod_mhip *item = playlist->GetPlaylistEntry(i);
  441. uint32_t master_index = master_playlist->FindPlaylistEntry(item->songindex);
  442. assert(master_index != -1);
  443. write_uint32_t(data, ptr, master_index);
  444. }
  445. }
  446. return ptr;
  447. }