1 /* 2 * Copyright (C) 2005-2007 Christophe Fergeau 3 * 4 * 5 * The code contained in this file is free software; you can redistribute 6 * it and/or modify it under the terms of the GNU Lesser General Public 7 * License as published by the Free Software Foundation; either version 8 * 2.1 of the License, or (at your option) any later version. 9 * 10 * This file is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public 16 * License along with this code; if not, write to the Free Software 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 * 19 * iTunes and iPod are trademarks of Apple 20 * 21 * This product is not supported/written/published by Apple! 22 * 23 * $Id$ 24 */ 25 26 27 #ifndef DB_PARSER_H 28 #define DB_PARSER_H 29 30 #include <glib.h> 31 32 struct _MHeader { 33 unsigned char header_id[4]; 34 gint32 header_len; 35 }; 36 37 typedef struct _MHeader MHeader; 38 39 struct _MhlHeader { 40 unsigned char header_id[4]; 41 gint32 header_len; 42 gint32 num_children; 43 unsigned char padding[]; 44 }; 45 46 typedef struct _MhlHeader MhlHeader; 47 48 49 typedef struct _MhbdHeader MhbdHeader; 50 typedef struct _ArtworkDB_MhsdHeader ArtworkDB_MhsdHeader; 51 /*typedef struct _MhsdHeader MhsdHeader;*/ 52 typedef struct _MhltHeader MhltHeader; 53 typedef struct _MhlpHeader MhlpHeader; 54 typedef struct _MhypHeader MhypHeader; 55 typedef struct _MhipHeader MhipHeader; 56 typedef struct _MhitHeader MhitHeader; 57 typedef struct _ArtworkDB_MhodHeader ArtworkDB_MhodHeader; 58 /*typedef struct _MhodHeader MhodHeader;*/ 59 typedef struct _MhfdHeader MhfdHeader; 60 typedef struct _MhliHeader MhliHeader; 61 typedef struct _MhiiHeader MhiiHeader; 62 typedef struct _MhniHeader MhniHeader; 63 typedef struct _MhlaHeader MhlaHeader; 64 typedef struct _MhbaHeader MhbaHeader; 65 typedef struct _MhlfHeader MhlfHeader; 66 typedef struct _MhifHeader MhifHeader; 67 typedef struct _MhiaHeader MhiaHeader; 68 69 typedef struct _MhitHeader471 MhitHeader471; 70 /* MHOD typedef mess */ 71 typedef struct _ArtworkDB_MhodHeaderString ArtworkDB_MhodHeaderString; 72 typedef struct _MhodHeaderString MhodHeaderString; 73 typedef struct _MhodHeaderSmartPlaylistData MhodHeaderSmartPlaylistData; 74 typedef struct _MhodHeaderSmartPlaylistRuleString MhodHeaderSmartPlaylistRuleString; 75 typedef struct _MhodHeaderSmartPlaylistRuleNonString MhodHeaderSmartPlaylistRuleNonString; 76 typedef struct _MhodHeaderSmartPlaylistRule MhodHeaderSmartPlaylistRule; 77 78 struct _MhbdHeader { 79 gchar header_id[4]; 80 guint32 header_len; 81 guint32 total_len; 82 guint32 unknown1; 83 guint32 version; 84 guint32 num_children; 85 guint64 db_id; 86 guint16 platform; 87 guint16 unk_0x22; 88 guint64 id_0x24; 89 guint32 unk_0x2c; 90 guint16 hashing_scheme; 91 guchar unk_0x32[20]; 92 gchar language_id[2]; 93 guint64 db_persistent_id; 94 guint32 unk_0x50; 95 guint32 unk_0x54; 96 guchar hash58[20]; 97 gint32 timezone_offset; 98 guint16 unk_0x70; 99 guchar hash72[46]; 100 guint16 audio_language; 101 guint16 subtitle_language; 102 guint16 unk_0xa4; 103 guint16 unk_0xa6; 104 guint16 unk_0xa8; 105 guchar align_0xa9; 106 guchar hashAB[57]; 107 guchar padding[]; 108 } __attribute__((__packed__)); 109 110 enum MhsdIndexType { 111 MHSD_TRACK_LIST = 1, 112 MHSD_PLAYLIST_LIST = 2 113 }; 114 115 enum MhsdPhotoIndexType { 116 MHSD_IMAGE_LIST = 1, 117 MHSD_ALBUM_LIST = 2, 118 MHSD_FILE_LIST = 3 119 }; 120 121 struct _ArtworkDB_MhsdHeader { 122 unsigned char header_id[4]; 123 gint32 header_len; 124 gint32 total_len; 125 /* Strangely, the following field is only 16 bits long in the 126 * ArtworkDB (it's definitely 32 bits in the iTunesDB). This 127 * could well be an error with the first generation of mobile 128 * phones with iPod support). 129 */ 130 gint16 index; 131 gint16 unknown014; 132 unsigned char padding[]; 133 }; 134 135 struct _iTunesDB_MhsdHeader { 136 unsigned char header_id[4]; 137 gint32 header_len; 138 gint32 total_len; 139 gint32 index; 140 unsigned char padding[]; 141 }; 142 struct _MhltHeader { 143 unsigned char header_id[4]; 144 gint32 header_len; 145 gint32 num_songs; 146 unsigned char padding[]; 147 }; 148 149 struct _MhlpHeader { 150 unsigned char header_id[4]; 151 gint32 header_len; 152 gint32 num_playlists; 153 unsigned char padding[]; 154 }; 155 156 struct _MhypHeader { 157 unsigned char header_id[4]; 158 gint32 header_len; 159 gint32 total_len; 160 gint32 num_mhod; 161 gint32 num_items; 162 gint32 hidden; 163 gint32 timestamp; 164 gint32 playlist_id; 165 gint32 unknown3; 166 gint32 unknown4; 167 gint32 unknown5; 168 unsigned char padding[]; 169 }; 170 171 struct _MhipHeader { 172 unsigned char header_id[4]; 173 gint32 header_len; 174 gint32 total_len; 175 gint32 unknown1; 176 gint32 format_id; 177 gint32 unknown2; 178 gint32 track_id; 179 gint32 timestamp; 180 unsigned char padding[]; 181 }; 182 183 /* MHIT header as written by iTunes 4.7.1, the added fields (from unknown17 to 184 * the end of the struct) are pretty useless, so we don't use this struct 185 */ 186 struct _MhitHeader471 { 187 unsigned char header_id[4]; 188 gint32 header_len; 189 gint32 total_len; 190 gint32 num_mhod; 191 gint32 track_id; 192 gint32 visible; 193 gint32 filetype; 194 /* FIXME: endianness issue with the order of the 3 fields above ? */ 195 gint16 type; 196 gchar compilation; 197 gchar rating; 198 gint32 date_added; 199 gint32 size; 200 gint32 length; 201 gint32 track_number; 202 gint32 track_total; 203 gint32 year; 204 gint32 bitrate; 205 /* FIXME: endianness issue with the order of the 2 fields above ? */ 206 gint16 unknown; 207 gint16 sample_rate; 208 gint32 volume; 209 gint32 start_time; 210 gint32 stop_time; 211 gint32 sound_check; 212 gint32 play_count; 213 gint32 play_count2; 214 gint32 last_played; 215 gint32 disc_number; 216 gint32 disc_total; 217 gint32 user_id; 218 gint32 last_modified; 219 gint32 bookmark_time; 220 gint64 song_id; 221 /* FIXME: endianness issue with the order of the 5 fields above ? */ 222 gchar checked; 223 gchar app_rating; 224 gint16 bpm; 225 gint16 artwork_count; 226 gint16 unknown9; 227 gint32 artwork_size; 228 gint32 unknown11; 229 gint32 sample_rate2; 230 gint32 unknown13; 231 gint32 unknown14; 232 gint32 unknown15; 233 gint32 unknown16; 234 gint32 unknown17; 235 gint32 unknown18; 236 gint32 unknown19; 237 gint64 song_id2; 238 gint32 unknown20; 239 gint32 unknown21; 240 gint32 unknown22; 241 gint32 unknown23; 242 gint32 unknown24; 243 gint32 unknown25; 244 gint32 unknown26; 245 gint32 unknown27; 246 gint32 unknown28; 247 gint32 unknown29; 248 gint32 unknown30; 249 gint32 unknown31; 250 gint32 unknown32; 251 gint32 unknown33; 252 gint32 unknown34; 253 gint32 unknown35; 254 gint32 unknown36; 255 unsigned char padding[]; 256 }; 257 258 struct _MhitHeader { 259 unsigned char header_id[4]; 260 gint32 header_len; 261 gint32 total_len; 262 gint32 num_mhod; 263 gint32 track_id; 264 gint32 visible; 265 gint32 filetype; 266 /* FIXME: endianness issue with the order of the 3 fields above ? */ 267 gint16 type; 268 gchar compilation; 269 gchar rating; 270 gint32 date_added; 271 gint32 size; 272 gint32 length; 273 gint32 track_number; 274 gint32 track_total; 275 gint32 year; 276 gint32 bitrate; 277 /* FIXME: endianness issue with the order of the 2 fields above ? */ 278 gint16 unknown; 279 gint16 sample_rate; 280 gint32 volume; 281 gint32 start_time; 282 gint32 stop_time; 283 gint32 sound_check; 284 gint32 play_count; 285 gint32 play_count2; 286 gint32 last_played; 287 gint32 disc_number; 288 gint32 disc_total; 289 gint32 user_id; 290 gint32 last_modified; 291 gint32 bookmark_time; 292 gint64 song_id; 293 /* FIXME: endianness issue with the order of the 5 fields above ? */ 294 gchar checked; 295 gchar app_rating; 296 gint16 bpm; 297 gint16 artwork_count; 298 gint16 unknown9; 299 gint32 artwork_size; 300 gint32 unknown11; 301 gint32 sample_rate2; 302 gint32 unknown13; 303 gint32 unknown14; 304 gint32 unknown15; 305 gint32 unknown16; 306 unsigned char padding[]; 307 }; 308 309 enum MhodEncoding { 310 MHOD_ENCODING_UTF16 = 0, 311 MHOD_ENCODING_UTF8 = 1 312 }; 313 314 enum MhodType { 315 MHOD_TYPE_TITLE = 1, 316 MHOD_TYPE_LOCATION = 2, 317 MHOD_TYPE_ALBUM = 3, 318 MHOD_TYPE_ARTIST = 4, 319 MHOD_TYPE_GENRE = 5, 320 MHOD_TYPE_FILETYPE = 6, 321 MHOD_TYPE_EQ_SETTING = 7, 322 MHOD_TYPE_COMMENT = 8, 323 MHOD_TYPE_COMPOSER = 12, 324 MHOD_TYPE_GROUPING = 13, 325 MHOD_TYPE_SMART_PLAYLIST_DATA = 50, 326 MHOD_TYPE_SMART_PLAYLIST_RULES = 51, 327 MHOD_TYPE_LIBRARY_PLAYLIST_INDEX = 52, 328 MHOD_TYPE_100 = 100 329 }; 330 331 struct _MhodHeader { 332 unsigned char header_id[4]; 333 gint32 header_len; 334 gint32 total_len; 335 gint32 type; 336 gint32 unknown1; 337 gint32 unknown2; 338 }; 339 340 struct _ArtworkDB_MhodHeader { 341 unsigned char header_id[4]; 342 gint32 header_len; 343 gint32 total_len; 344 /* Strangely, the following field is only 16 bits long in the 345 * ArtworkDB (it's definitely 32 bits in the iTunesDB). This 346 * could well be an error with the first generation of mobile 347 * phones with iPod support). 348 */ 349 gint16 type; 350 gint16 unknown014; 351 gint32 unknown1; 352 gint32 unknown2; 353 }; 354 355 struct _MhodHeaderString { 356 unsigned char header_id[4]; 357 gint32 header_len; 358 gint32 total_len; 359 gint32 type; /* < 50 */ 360 gint32 unknown1; 361 gint32 unknown2; 362 gint32 position; 363 gint32 string_len; 364 gint32 unknown3; /* It was thought that this was string encoding: 365 * 0 == UTF-16, 1 == UTF-8, however, recent iTunesDB 366 * files have had this set to 1 even with UTF-16 strings. 367 * Therefore this is definitely incorrect, and the 368 * correct meaning has not yet been discovered yet. */ 369 gint32 unknown4; 370 unsigned char string[]; 371 }; 372 373 enum MhodArtworkType { 374 MHOD_ARTWORK_TYPE_ALBUM_NAME = 1, /* string: album name (in the Photo Database) */ 375 MHOD_ARTWORK_TYPE_THUMBNAIL = 2, /* container: thumbnail image */ 376 MHOD_ARTWORK_TYPE_FILE_NAME = 3, /* string: file name */ 377 MHOD_ARTWORK_TYPE_IMAGE = 5 /* container: full resolution image (in the Photo Database) */ 378 }; 379 380 struct _ArtworkDB_MhodHeaderString { 381 unsigned char header_id[4]; 382 gint32 header_len; 383 gint32 total_len; 384 gint16 type; 385 gint8 unknown13; 386 gint8 padding_len; 387 gint32 unknown1; 388 gint32 unknown2; 389 gint32 string_len; 390 gint8 encoding; /* 0,1: string is UTF8, 2: string is UTF16-LE */ 391 gint8 unknown5; 392 gint16 unknown6; 393 gint32 unknown4; 394 gchar string[]; 395 }; 396 397 enum MhodLimitType { 398 MHOD_LIMIT_MINUTES = 1, 399 MHOD_LIMIT_MEGABYTES = 2, 400 MHOD_LIMIT_SONGS = 3, 401 MHOD_LIMIT_HOURS = 4, 402 MHOD_LIMIT_GIGABYTES = 5 403 }; 404 405 enum MhodLimitSortType { 406 MHOD_LIMIT_SORT_RANDOM = 0x02, 407 MHOD_LIMIT_SORT_SONG_NAME = 0x03, 408 MHOD_LIMIT_SORT_ALBUM = 0x04, 409 MHOD_LIMIT_SORT_ARTIST = 0x05, 410 MHOD_LIMIT_SORT_GENRE = 0x07, 411 MHOD_LIMIT_SORT_MOST_RECENTLY_ADDED = 0x10, 412 MHOD_LIMIT_SORT_MOST_OFTEN_PLAYED = 0x14, 413 MHOD_LIMIT_SORT_MOST_RECENTLY_PLAYED = 0x15, 414 MHOD_LIMIT_SORT_HIGHEST_RATING = 0x17 415 }; 416 417 struct _MhodHeaderSmartPlaylistData { 418 unsigned char header_id[4]; 419 gint32 header_len; 420 gint32 total_len; 421 gint32 type; /* 50 */ 422 gint32 unknown1; 423 gint32 unknown2; 424 gchar live_update; 425 gchar rules_enable; 426 gchar limit_enable; 427 gchar limit_type; 428 gchar limit_sort; 429 gchar unknow3[3]; 430 gint32 limit; 431 gchar match_checked_only; 432 gchar reverse_limit_sort; 433 unsigned char padding[]; 434 }; 435 436 437 enum MhodSmartPlaylistRuleFieldType { 438 MHOD_FIELD_SONG_NAME = 0x02, 439 MHOD_FIELD_ALBUM = 0x03, 440 MHOD_FIELD_ARTIST = 0x04, 441 MHOD_FIELD_BITRATE = 0x05, 442 MHOD_FIELD_SAMPLE_RATE = 0x06, 443 MHOD_FIELD_YEAR = 0x07, 444 MHOD_FIELD_GENRE = 0x08, 445 MHOD_FIELD_KIND = 0x09, 446 MHOD_FIELD_DATE_MODIFIED = 0x0a, 447 MHOD_FIELD_TRACK_NUMBER = 0x0b, 448 MHOD_FIELD_SIZE = 0x0c, 449 MHOD_FIELD_TIME = 0x0d, 450 MHOD_FIELD_COMMENT = 0x0e, 451 MHOD_FIELD_DATE_ADDED = 0x10, 452 MHOD_FIELD_COMPOSER = 0x12, 453 MHOD_FIELD_PLAY_COUNT = 0x16, 454 MHOD_FIELD_LAST_PLAYED = 0x17, 455 MHOD_FIELD_DISC_NUMBER = 0x18, 456 MHOD_FIELD_RATING = 0x19, 457 MHOD_FIELD_COMPILATION = 0x1f, 458 MHOD_FIELD_BPM = 0x23, 459 MHOD_FIELD_GROUPING = 0x27, 460 MHOD_FIELD_PLAYLIST = 0x28 461 }; 462 463 enum MhodSmartPlaylistRuleAction { 464 MHOD_RULE_IS = 1 << 0, 465 MHOD_RULE_CONTAINS = 1 << 1, 466 MHOD_RULE_BEGINS_WITH = 1 << 2, 467 MHOD_RULE_ENDS_WITH = 1 << 3, 468 MHOD_RULE_GREATER_THAN = 1 << 4, 469 MHOD_RULE_GREATER_THAN_OR_EQUAL_TO = 1 << 5, 470 MHOD_RULE_LESS_THAN = 1 << 6, 471 MHOD_RULE_LESS_THAN_OR_EQUAL_TO = 1 << 7, 472 MHOD_RULE_IN_THE_RANGE = 1 << 8, 473 MHOD_RULE_IS_THE_LAST = 1 << 9, 474 MHOD_RULE_NOT = 1 << 24, 475 MHOD_RULE_STRING = 1 << 25 476 }; 477 478 479 struct _MhodHeaderSmartPlaylistRuleString { 480 /* Big endian fields */ 481 gint32 field; 482 gint32 action; 483 gchar padding[44]; 484 gint32 string_len; 485 gchar string[]; 486 }; 487 488 struct _MhodHeaderSmartPlaylistRuleNonString { 489 /* Big endian fields */ 490 gint32 field; 491 gint32 action; 492 gchar padding[44]; 493 gint32 length; 494 guint64 from_value; 495 gint64 from_date; 496 guint64 from_unit; 497 guint64 to_value; 498 gint64 to_date; 499 guint64 to_unit; 500 gchar unknown[20]; 501 }; 502 503 struct _MhodHeaderSmartPlaylistRule { 504 unsigned char header_id[4]; 505 gint32 header_len; 506 gint32 total_len; 507 gint32 type; /* 51 */ 508 gint32 unknown1; 509 gint32 unknown2; 510 gchar rules_id[4]; 511 /* Fields stored in big-endian from there */ 512 gint32 unknown5; 513 gint32 number_of_rules; 514 gint32 rules_operator; 515 gchar padding[120]; 516 union { 517 MhodHeaderSmartPlaylistRuleString rule_string; 518 MhodHeaderSmartPlaylistRuleNonString rule_non_string; 519 } rule; 520 }; 521 522 523 524 struct _MhfdHeader { 525 unsigned char header_id[4]; 526 gint32 header_len; 527 gint32 total_len; 528 gint32 unknown1; 529 gint32 unknown2; /* always seem to be 1 for older databases, 530 in an ArtworkDB generated by iTunes 4.9 or 531 above, it's 2. Caution: iTunes7 removes 532 the whole database if this field is 1 */ 533 gint32 num_children; 534 gint32 unknown3; 535 gint32 next_id; 536 gint64 unknown5; 537 gint64 unknown6; 538 gint8 unknown_flag1; 539 gint8 unknown_flag2; 540 gint8 unknown_flag3; 541 gint8 unknown_flag4; 542 gint32 unknown8; 543 gint32 unknown9; 544 gint32 unknown10; 545 gint32 unknown11; 546 unsigned char padding[]; 547 }; 548 549 struct _MhliHeader { 550 unsigned char header_id[4]; 551 gint32 header_len; 552 gint32 num_children; 553 unsigned char padding[]; 554 }; 555 556 struct _MhiiHeader { 557 unsigned char header_id[4]; 558 gint32 header_len; 559 gint32 total_len; 560 gint32 num_children; 561 gint32 image_id; 562 gint64 song_id; 563 gint32 unknown4; 564 gint32 rating; 565 gint32 unknown6; 566 gint32 orig_date; 567 gint32 digitized_date; 568 gint32 orig_img_size; 569 unsigned char padding[]; 570 } __attribute__((__packed__)); 571 /* I we don't put the 'packed' attribute above, some 64 bit systems 572 * will pad the 64 bit integer to be aligned to an 8-byte boundary. 573 * Hopefully there won't be any systems around that crash when 574 * accessing 64 bit integers not aligned to 8-byte boundaries. */ 575 576 577 struct _MhniHeader { 578 unsigned char header_id[4]; 579 gint32 header_len; 580 gint32 total_len; 581 gint32 num_children; 582 gint32 format_id; 583 gint32 ithmb_offset; 584 gint32 image_size; 585 gint16 vertical_padding; 586 gint16 horizontal_padding; 587 gint16 image_height; 588 gint16 image_width; 589 unsigned char padding[]; 590 }; 591 592 struct _MhlaHeader { 593 unsigned char header_id[4]; 594 gint32 header_len; 595 gint32 num_children; 596 unsigned char padding[]; 597 }; 598 599 struct _MhbaHeader { 600 unsigned char header_id[4]; 601 gint32 header_len; 602 gint32 total_len; 603 gint32 num_mhods; /* number of Data Objects in the List, 604 probably always 1 */ 605 gint32 num_mhias; /* number of pictures in the album */ 606 gint32 album_id; /* starts out at $64 and increments by 1 */ 607 gint32 unk024; /* unknown, seems to be always 0 */ 608 gint16 unk028; /* unknown, seems to be always 0 */ 609 guint8 album_type; /* 1 = master photo list ("Photo Library"), 610 2 = normal album, sometimes 4 and 5 */ 611 guint8 playmusic; /* play music during slideshow (from iPhoto setting) */ 612 guint8 repeat; /* repeat the slideshow (from iPhoto setting) */ 613 guint8 random; /* show the slides in random order (from iPhoto 614 setting) */ 615 guint8 show_titles;/* show slide captions (from iPhoto setting) */ 616 guint8 transition_direction; /* 0=none, 1=left-to-right, 617 2=right-to-left, 3=top-to-bottom, 618 4=bottom-to-top (from iPhoto setting) */ 619 gint32 slide_duration; /* in seconds (from iPhoto setting) */ 620 gint32 transition_duration; /* in milliseconds (from iPhoto setting) */ 621 gint32 unk044; /* unknown, seems to always be 0 */ 622 gint32 unk048; /* unknown, seems to always be 0 */ 623 gint64 song_id; /* dbid2 of track in iTunesDB to play during 624 slideshow (from iPhoto setting) */ 625 gint32 prev_album_id; /* the id of the previous photoalbum */ 626 unsigned char padding[]; 627 }; 628 629 struct _MhlfHeader { 630 unsigned char header_id[4]; 631 gint32 header_len; 632 gint32 num_files; 633 unsigned char padding[]; 634 }; 635 636 struct _MhifHeader { 637 unsigned char header_id[4]; 638 gint32 header_len; 639 gint32 total_len; 640 gint32 unknown1; 641 gint32 format_id; 642 gint32 image_size; 643 unsigned char padding[]; 644 }; 645 646 struct _MhiaHeader { 647 unsigned char header_id[4]; 648 gint32 header_len; 649 gint32 total_len; /* probably the size of the header and all child records; 650 * as there aren't any child records this is equal to header length */ 651 gint32 unknown1; /* seems to be zero */ 652 guint32 image_id; /* the id of the mhii record this mhia refers to */ 653 unsigned char padding[]; 654 }; 655 656 657 #endif /* PARSE_DB_H */ 658