summaryrefslogtreecommitdiffstats
path: root/src/db-itunes-parser.h
blob: ba93a5756b9261a6a66c85b9bfe11deb7ce709f2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
/*
 *  Copyright (C) 2005-2007 Christophe Fergeau
 *
 * 
 *  The code contained in this file is free software; you can redistribute
 *  it and/or modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either version
 *  2.1 of the License, or (at your option) any later version.
 *  
 *  This file is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *  
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this code; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 * 
 *  iTunes and iPod are trademarks of Apple
 * 
 *  This product is not supported/written/published by Apple!
 *
 * $Id$
 */


#ifndef DB_PARSER_H
#define DB_PARSER_H

#include <glib.h>

struct _MHeader {
	unsigned char header_id[4];
	gint32 header_len;
};

typedef struct _MHeader MHeader;

struct _MhlHeader {
	unsigned char header_id[4];
	gint32 header_len;
	gint32 num_children;
	unsigned char padding[];
};

typedef struct _MhlHeader MhlHeader;


typedef struct _MhbdHeader MhbdHeader;
typedef struct _ArtworkDB_MhsdHeader ArtworkDB_MhsdHeader;
/*typedef struct _MhsdHeader MhsdHeader;*/
typedef struct _MhltHeader MhltHeader;
typedef struct _MhlpHeader MhlpHeader;
typedef struct _MhypHeader MhypHeader;
typedef struct _MhipHeader MhipHeader;
typedef struct _MhitHeader MhitHeader;
typedef struct _ArtworkDB_MhodHeader ArtworkDB_MhodHeader;
/*typedef struct _MhodHeader MhodHeader;*/
typedef struct _MhfdHeader MhfdHeader;
typedef struct _MhliHeader MhliHeader;
typedef struct _MhiiHeader MhiiHeader;
typedef struct _MhniHeader MhniHeader;
typedef struct _MhlaHeader MhlaHeader;
typedef struct _MhbaHeader MhbaHeader;
typedef struct _MhlfHeader MhlfHeader;
typedef struct _MhifHeader MhifHeader;
typedef struct _MhiaHeader MhiaHeader;

typedef struct _MhitHeader471 MhitHeader471;
/* MHOD typedef mess */
typedef struct _ArtworkDB_MhodHeaderString ArtworkDB_MhodHeaderString;
typedef struct _MhodHeaderString MhodHeaderString;
typedef struct _MhodHeaderSmartPlaylistData MhodHeaderSmartPlaylistData;
typedef struct _MhodHeaderSmartPlaylistRuleString MhodHeaderSmartPlaylistRuleString; 
typedef struct _MhodHeaderSmartPlaylistRuleNonString MhodHeaderSmartPlaylistRuleNonString;
typedef struct _MhodHeaderSmartPlaylistRule MhodHeaderSmartPlaylistRule;

struct _MhbdHeader {
	unsigned char header_id[4];
	gint32 header_len;
	gint32 total_len;
	gint32 unknown1;
	gint32 version;
	gint32 num_children;
	gint64 db_id;
	gint32 unknown2;
	unsigned char padding[];
};

enum MhsdIndexType {
	MHSD_TRACK_LIST = 1,
	MHSD_PLAYLIST_LIST = 2
};

enum MhsdPhotoIndexType {
	MHSD_IMAGE_LIST = 1,
	MHSD_ALBUM_LIST = 2,
	MHSD_FILE_LIST = 3
};

struct _ArtworkDB_MhsdHeader {
	unsigned char header_id[4];
	gint32 header_len;
	gint32 total_len;
        /* Strangely, the following field is only 16 bits long in the
	 * ArtworkDB (it's definitely 32 bits in the iTunesDB). This
	 * could well be an error with the first generation of mobile
	 * phones with iPod support).
	 */
	gint16 index;
        gint16 unknown014;
	unsigned char padding[];
};

struct _iTunesDB_MhsdHeader {
	unsigned char header_id[4];
	gint32 header_len;
	gint32 total_len;
	gint32 index;
	unsigned char padding[];
};
struct _MhltHeader {
	unsigned char header_id[4];
	gint32 header_len;
	gint32 num_songs;
	unsigned char padding[];
};

struct _MhlpHeader {
	unsigned char header_id[4];
	gint32 header_len;
	gint32 num_playlists;
	unsigned char padding[];
};

struct _MhypHeader {
	unsigned char header_id[4];
	gint32 header_len;
	gint32 total_len;
	gint32 num_mhod;
	gint32 num_items;
	gint32 hidden;
	gint32 timestamp;
	gint32 playlist_id;
	gint32 unknown3;
	gint32 unknown4;
	gint32 unknown5;
	unsigned char padding[];
};

struct _MhipHeader {
	unsigned char header_id[4];
	gint32 header_len;
	gint32 total_len;
	gint32 unknown1;
	gint32 format_id;
	gint32 unknown2;
	gint32 track_id;
	gint32 timestamp;
	unsigned char padding[];
};

/* MHIT header as written by iTunes 4.7.1, the added fields (from unknown17 to
 * the end of the struct) are pretty useless, so we don't use this struct
 */
struct _MhitHeader471 {
	unsigned char header_id[4];
	gint32 header_len;
	gint32 total_len;
	gint32 num_mhod;
	gint32 track_id;
	gint32 visible;
	gint32 filetype;
	/* FIXME: endianness issue with the order of the 3 fields above ? */
	gint16 type;
	gchar  compilation;
	gchar  rating;
	gint32 date_added;
	gint32 size;
	gint32 length;
	gint32 track_number;
	gint32 track_total;
	gint32 year;
	gint32 bitrate;
	/* FIXME: endianness issue with the order of the 2 fields above ? */
	gint16 unknown;
	gint16 sample_rate;
	gint32 volume;
	gint32 start_time;
	gint32 stop_time;
	gint32 sound_check;
	gint32 play_count;
	gint32 play_count2;
	gint32 last_played;
	gint32 disc_number;
	gint32 disc_total;
	gint32 user_id;
	gint32 last_modified;
	gint32 bookmark_time;
	gint64 song_id;
	/* FIXME: endianness issue with the order of the 5 fields above ? */
	gchar  checked;
	gchar  app_rating;
	gint16 bpm;
	gint16 artwork_count;
	gint16 unknown9;
	gint32 artwork_size;
	gint32 unknown11;
	gint32 sample_rate2;
	gint32 unknown13;
	gint32 unknown14;
	gint32 unknown15;
	gint32 unknown16;
	gint32 unknown17;
	gint32 unknown18;
	gint32 unknown19;
	gint64 song_id2;
	gint32 unknown20;
	gint32 unknown21;
	gint32 unknown22;
	gint32 unknown23;
	gint32 unknown24;
	gint32 unknown25;
	gint32 unknown26;
	gint32 unknown27;
	gint32 unknown28;
	gint32 unknown29;
	gint32 unknown30;
	gint32 unknown31;
	gint32 unknown32;
	gint32 unknown33;
	gint32 unknown34;
	gint32 unknown35;
	gint32 unknown36;
	unsigned char padding[];
};

struct _MhitHeader {
	unsigned char header_id[4];
	gint32 header_len;
	gint32 total_len;
	gint32 num_mhod;
	gint32 track_id;
	gint32 visible;
	gint32 filetype;
	/* FIXME: endianness issue with the order of the 3 fields above ? */
	gint16 type;
	gchar  compilation;
	gchar  rating;
	gint32 date_added;
	gint32 size;
	gint32 length;
	gint32 track_number;
	gint32 track_total;
	gint32 year;
	gint32 bitrate;
	/* FIXME: endianness issue with the order of the 2 fields above ? */
	gint16 unknown;
	gint16 sample_rate;
	gint32 volume;
	gint32 start_time;
	gint32 stop_time;
	gint32 sound_check;
	gint32 play_count;
	gint32 play_count2;
	gint32 last_played;
	gint32 disc_number;
	gint32 disc_total;
	gint32 user_id;
	gint32 last_modified;
	gint32 bookmark_time;
	gint64 song_id;
	/* FIXME: endianness issue with the order of the 5 fields above ? */
	gchar  checked;
	gchar  app_rating;
	gint16 bpm;
	gint16 artwork_count;
	gint16 unknown9;
	gint32 artwork_size;
	gint32 unknown11;
	gint32 sample_rate2;
	gint32 unknown13;
	gint32 unknown14;
	gint32 unknown15;
	gint32 unknown16;
	unsigned char padding[];
};

enum MhodEncoding {
	MHOD_ENCODING_UTF16 = 0,
	MHOD_ENCODING_UTF8 = 1
};

enum MhodType {
	MHOD_TYPE_TITLE = 1,
	MHOD_TYPE_LOCATION = 2,
	MHOD_TYPE_ALBUM = 3,
	MHOD_TYPE_ARTIST = 4,
	MHOD_TYPE_GENRE = 5,
	MHOD_TYPE_FILETYPE = 6,
	MHOD_TYPE_EQ_SETTING = 7,
	MHOD_TYPE_COMMENT = 8,
	MHOD_TYPE_COMPOSER = 12,
	MHOD_TYPE_GROUPING = 13,
	MHOD_TYPE_SMART_PLAYLIST_DATA = 50,
	MHOD_TYPE_SMART_PLAYLIST_RULES = 51,
	MHOD_TYPE_LIBRARY_PLAYLIST_INDEX = 52,
	MHOD_TYPE_100 = 100
};

struct _MhodHeader {
	unsigned char header_id[4];
	gint32 header_len;
	gint32 total_len;
	gint32 type;
	gint32 unknown1;
	gint32 unknown2;
};

struct _ArtworkDB_MhodHeader {
	unsigned char header_id[4];
	gint32 header_len;
	gint32 total_len;
    /* Strangely, the following field is only 16 bits long in the
	 * ArtworkDB (it's definitely 32 bits in the iTunesDB). This
	 * could well be an error with the first generation of mobile
	 * phones with iPod support).
	 */
	gint16 type;
        gint16 unknown014;
	gint32 unknown1;
	gint32 unknown2;
};

struct _MhodHeaderString {
	unsigned char header_id[4];
	gint32 header_len;
	gint32 total_len;
	gint32 type; /* < 50 */
	gint32 unknown1;
	gint32 unknown2;
	gint32 position;
	gint32 string_len;
	gint32 unknown3; /* It was thought that this was string encoding:
			  * 0 == UTF-16, 1 == UTF-8, however, recent iTunesDB
			  * files have had this set to 1 even with UTF-16 strings.
			  * Therefore this is definitely incorrect, and the
			  * correct meaning has not yet been discovered yet. */
	gint32 unknown4;
	unsigned char string[];
};

enum MhodArtworkType {
	MHOD_ARTWORK_TYPE_ALBUM_NAME = 1, /* string:    album name (in the Photo Database) */
	MHOD_ARTWORK_TYPE_THUMBNAIL  = 2, /* container: thumbnail image */
	MHOD_ARTWORK_TYPE_FILE_NAME  = 3, /* string:    file name */
	MHOD_ARTWORK_TYPE_IMAGE      = 5  /* container: full resolution image (in the Photo Database) */
};

struct _ArtworkDB_MhodHeaderString {
	unsigned char header_id[4];
	gint32 header_len;
	gint32 total_len;
        gint16 type;
        gint8  unknown13;
	gint8  padding_len;
	gint32 unknown1;
	gint32 unknown2;
	gint32 string_len;
	gint8 encoding; /* 0,1: string is UTF8, 2: string is UTF16-LE */
        gint8 unknown5;
        gint16 unknown6;
	gint32 unknown4;
        gchar  string[];
};

enum MhodLimitType {
	MHOD_LIMIT_MINUTES = 1,
	MHOD_LIMIT_MEGABYTES = 2,
	MHOD_LIMIT_SONGS = 3,
	MHOD_LIMIT_HOURS = 4,
	MHOD_LIMIT_GIGABYTES = 5
};

enum MhodLimitSortType {
	MHOD_LIMIT_SORT_RANDOM = 0x02,
	MHOD_LIMIT_SORT_SONG_NAME = 0x03,
	MHOD_LIMIT_SORT_ALBUM = 0x04,
	MHOD_LIMIT_SORT_ARTIST = 0x05,
	MHOD_LIMIT_SORT_GENRE = 0x07,
	MHOD_LIMIT_SORT_MOST_RECENTLY_ADDED = 0x10,
	MHOD_LIMIT_SORT_MOST_OFTEN_PLAYED = 0x14,
	MHOD_LIMIT_SORT_MOST_RECENTLY_PLAYED = 0x15,
	MHOD_LIMIT_SORT_HIGHEST_RATING = 0x17
};

struct _MhodHeaderSmartPlaylistData {
	unsigned char header_id[4];
	gint32 header_len;
	gint32 total_len;
	gint32 type; /* 50 */
	gint32 unknown1;
	gint32 unknown2;
	gchar  live_update;
	gchar  rules_enable;
	gchar  limit_enable;
	gchar  limit_type;
	gchar  limit_sort;
	gchar  unknow3[3];
	gint32 limit;
	gchar  match_checked_only;
	gchar  reverse_limit_sort;
	unsigned char padding[];
};


enum MhodSmartPlaylistRuleFieldType {
	MHOD_FIELD_SONG_NAME = 0x02,
	MHOD_FIELD_ALBUM = 0x03,
	MHOD_FIELD_ARTIST = 0x04,
	MHOD_FIELD_BITRATE = 0x05,
	MHOD_FIELD_SAMPLE_RATE = 0x06,
	MHOD_FIELD_YEAR = 0x07,
	MHOD_FIELD_GENRE = 0x08,
	MHOD_FIELD_KIND = 0x09,	
	MHOD_FIELD_DATE_MODIFIED = 0x0a,
	MHOD_FIELD_TRACK_NUMBER = 0x0b,
	MHOD_FIELD_SIZE = 0x0c,
	MHOD_FIELD_TIME = 0x0d,
	MHOD_FIELD_COMMENT = 0x0e,
	MHOD_FIELD_DATE_ADDED = 0x10,
	MHOD_FIELD_COMPOSER = 0x12,
	MHOD_FIELD_PLAY_COUNT = 0x16,
	MHOD_FIELD_LAST_PLAYED = 0x17,
	MHOD_FIELD_DISC_NUMBER = 0x18,
	MHOD_FIELD_RATING = 0x19,
	MHOD_FIELD_COMPILATION = 0x1f,
	MHOD_FIELD_BPM = 0x23,
	MHOD_FIELD_GROUPING = 0x27,
	MHOD_FIELD_PLAYLIST = 0x28
};

enum MhodSmartPlaylistRuleAction {
	MHOD_RULE_IS = 1 << 0, 
	MHOD_RULE_CONTAINS = 1 << 1,
	MHOD_RULE_BEGINS_WITH = 1 << 2,
	MHOD_RULE_ENDS_WITH = 1 << 3,
	MHOD_RULE_GREATER_THAN = 1 << 4,
	MHOD_RULE_GREATER_THAN_OR_EQUAL_TO = 1 << 5,
	MHOD_RULE_LESS_THAN = 1 << 6,
	MHOD_RULE_LESS_THAN_OR_EQUAL_TO = 1 << 7,
	MHOD_RULE_IN_THE_RANGE = 1 << 8,
	MHOD_RULE_IS_THE_LAST = 1 << 9,
	MHOD_RULE_NOT = 1 << 24,
	MHOD_RULE_STRING = 1 << 25
};


struct _MhodHeaderSmartPlaylistRuleString {
	/* Big endian fields */
	gint32 field;
	gint32 action;
	gchar  padding[44];
	gint32 string_len;
	gchar  string[];
};

struct _MhodHeaderSmartPlaylistRuleNonString {
	/* Big endian fields */
	gint32  field;
	gint32  action;
	gchar   padding[44];
	gint32  length;
	guint64 from_value;
	gint64  from_date;
	guint64 from_unit;
	guint64 to_value;
	gint64  to_date;
	guint64 to_unit;
	gchar   unknown[20];
};

struct _MhodHeaderSmartPlaylistRule {
	unsigned char header_id[4];
	gint32 header_len;
	gint32 total_len;
	gint32 type; /* 51 */
	gint32 unknown1;
	gint32 unknown2;
	gchar  rules_id[4];
	/* Fields stored in big-endian from there */
	gint32 unknown5;
	gint32 number_of_rules;
	gint32 rules_operator;
	gchar  padding[120];
	union {
		MhodHeaderSmartPlaylistRuleString rule_string;
		MhodHeaderSmartPlaylistRuleNonString rule_non_string;
	} rule;
};



struct _MhfdHeader {
	unsigned char header_id[4];
	gint32 header_len;
	gint32 total_len;
	gint32 unknown1;
	gint32 unknown2; /* always seem to be 1 for older databases,
			    in an ArtworkDB generated by iTunes 4.9 or
			    above, it's 2. Caution: iTunes7 removes
			    the whole database if this field is 1 */
	gint32 num_children;
	gint32 unknown3;
	gint32 next_id;
	gint64 unknown5;
	gint64 unknown6;
	gint8  unknown_flag1;
	gint8  unknown_flag2;
	gint8  unknown_flag3;
	gint8  unknown_flag4;
	gint32 unknown8;
	gint32 unknown9;
	gint32 unknown10;
	gint32 unknown11;
	unsigned char padding[];
};

struct _MhliHeader {
	unsigned char header_id[4];
	gint32 header_len;
	gint32 num_children;
	unsigned char padding[];
};

struct _MhiiHeader {
	unsigned char header_id[4];
	gint32 header_len;
	gint32 total_len;
	gint32 num_children;
	gint32 image_id;
	gint64 song_id;
	gint32 unknown4;
	gint32 rating;
	gint32 unknown6;
	gint32 orig_date;
	gint32 digitized_date;
	gint32 orig_img_size;
	unsigned char padding[];
} __attribute__((__packed__));
/* I we don't put the 'packed' attribute above, some 64 bit systems
 * will pad the 64 bit integer to be aligned to an 8-byte boundary.
 * Hopefully there won't be any systems around that crash when
 * accessing 64 bit integers not aligned to 8-byte boundaries. */


struct _MhniHeader {
	unsigned char header_id[4];
	gint32 header_len;
	gint32 total_len;
	gint32 num_children;
	gint32 format_id;
	gint32 ithmb_offset;
	gint32 image_size;
	gint16 vertical_padding;
	gint16 horizontal_padding;
	gint16 image_height;
	gint16 image_width;
	unsigned char padding[];
};

struct _MhlaHeader {
	unsigned char header_id[4];
	gint32 header_len;
	gint32 num_children;
	unsigned char padding[];
};

struct _MhbaHeader {
	unsigned char header_id[4];
	gint32 header_len;
	gint32 total_len;
	gint32 num_mhods;  /* number of Data Objects in the List,
			      probably always 1 */
	gint32 num_mhias;  /* number of pictures in the album */
	gint32 album_id;   /* starts out at $64 and increments by 1 */
	gint32 unk024;     /* unknown, seems to be always 0 */
	gint16 unk028;     /* unknown, seems to be always 0 */
	guint8 album_type; /* 1 = master photo list ("Photo Library"),
			      2 = normal album, sometimes 4 and 5 */
	guint8 playmusic;  /* play music during slideshow (from iPhoto setting) */
	guint8 repeat;     /* repeat the slideshow (from iPhoto setting) */
	guint8 random;     /* show the slides in random order (from iPhoto
			      setting) */
	guint8 show_titles;/* show slide captions (from iPhoto setting) */
	guint8 transition_direction; /* 0=none, 1=left-to-right,
			      2=right-to-left, 3=top-to-bottom,
			      4=bottom-to-top (from iPhoto setting) */
	gint32 slide_duration; /* in seconds (from iPhoto setting) */
	gint32 transition_duration; /* in milliseconds (from iPhoto setting) */
	gint32 unk044;     /* unknown, seems to always be 0 */
	gint32 unk048;     /* unknown, seems to always be 0 */
	gint64 song_id;    /* dbid2 of track in iTunesDB to play during
			      slideshow (from iPhoto setting) */
	gint32 prev_album_id; /* the id of the previous photoalbum */
	unsigned char padding[];
};

struct _MhlfHeader {
	unsigned char header_id[4];
	gint32 header_len;
	gint32 num_files;
	unsigned char padding[];
};

struct _MhifHeader {
	unsigned char header_id[4];
	gint32 header_len;
	gint32 total_len;
	gint32 unknown1;
	gint32 format_id;
	gint32 image_size;
	unsigned char padding[];
};

struct _MhiaHeader {
	unsigned char header_id[4];
	gint32 header_len;
	gint32 total_len; /* probably the size of the header and all child records;
			   * as there aren't any child records this is equal to header length */
	gint32 unknown1; /* seems to be zero */
	guint32 image_id; /* the id of the mhii record this mhia refers to */
	unsigned char padding[];
};


#endif /* PARSE_DB_H */