diff options
author | Flavio Stanchina <fstanchina@users.sourceforge.net> | 2005-10-10 20:40:45 +0000 |
---|---|---|
committer | Flavio Stanchina <fstanchina@users.sourceforge.net> | 2005-10-10 20:40:45 +0000 |
commit | 5191d5305df522f29ebf112fdd0cdf89b6fcb870 (patch) | |
tree | c221a35f2709820cb0d26fb7dd4745167a5b2480 /src | |
parent | f532f816cc4e478523932dc3ce914b840f5c06bb (diff) | |
download | libgpod-5191d5305df522f29ebf112fdd0cdf89b6fcb870.tar.gz libgpod-5191d5305df522f29ebf112fdd0cdf89b6fcb870.tar.xz libgpod-5191d5305df522f29ebf112fdd0cdf89b6fcb870.zip |
Added a few structures (notably MHBA and MHIA) to support the Photo Database.
Split 'gint32 image_dimensions' into 'gint16 image_height, image_width'.
git-svn-id: https://gtkpod.svn.sf.net/svnroot/gtkpod/libgpod/trunk@1115 f01d2545-417e-4e96-918e-98f8d0dbbcb6
Diffstat (limited to 'src')
-rw-r--r-- | src/db-artwork-debug.c | 57 | ||||
-rw-r--r-- | src/db-artwork-debug.h | 6 | ||||
-rw-r--r-- | src/db-artwork-parser.c | 99 | ||||
-rw-r--r-- | src/db-artwork-writer.c | 11 | ||||
-rw-r--r-- | src/db-image-parser.c | 12 | ||||
-rw-r--r-- | src/db-itunes-parser.h | 56 |
6 files changed, 208 insertions, 33 deletions
diff --git a/src/db-artwork-debug.c b/src/db-artwork-debug.c index d8ccb96..90e4107 100644 --- a/src/db-artwork-debug.c +++ b/src/db-artwork-debug.c @@ -39,6 +39,15 @@ dump_mhif (MhifHeader *mhif) g_print ("\tImage size: %d bytes\n", GINT_FROM_LE (mhif->image_size)); } +G_GNUC_INTERNAL void +dump_mhia (MhiaHeader *mhia) +{ + g_print ("MHIA (%d):\n", sizeof (MhiaHeader)); + g_print ("\tHeader length: %d\n", GINT_FROM_LE (mhia->header_len)); + g_print ("\tTotal length: %d\n", GINT_FROM_LE (mhia->total_len)); + g_print ("\tUnknown1: %08x\n", GINT_FROM_LE (mhia->unknown1)); + g_print ("\tImage ID: %08x\n", GINT_FROM_LE (mhia->image_id)); +} static char * get_utf16_string (void* buffer, gint length) @@ -60,15 +69,31 @@ get_utf16_string (void* buffer, gint length) } +G_GNUC_INTERNAL void +dump_mhod_type_1 (MhodHeaderArtworkType1 *mhod1) +{ + g_print ("MHOD [artwork type 1] (%d):\n", sizeof (MhodHeaderArtworkType1)); + g_print ("\tHeader length: %d\n", GINT_FROM_LE (mhod1->header_len)); + g_print ("\tTotal length: %d\n", GINT_FROM_LE (mhod1->total_len)); + g_print ("\tType: %08x\n", GINT_FROM_LE (mhod1->type)); + g_print ("\tUnknown1: %08x\n", GINT_FROM_LE (mhod1->unknown1)); + g_print ("\tUnknown2: %08x\n", GINT_FROM_LE (mhod1->unknown2)); + g_print ("\tString length: %u\n", GINT_FROM_LE (mhod1->string_len)); + g_print ("\tUnknown3: %08x\n", GINT_FROM_LE (mhod1->unknown3)); + g_print ("\tUnknown4: %08x\n", GINT_FROM_LE (mhod1->unknown4)); + /* FIXME: do I need to translate UTF-8 to local encoding? */ + g_print ("\tString: \"%.*s\"\n", GINT_FROM_LE (mhod1->string_len), mhod1->string); +} + G_GNUC_INTERNAL void dump_mhod_type_3 (MhodHeaderArtworkType3 *mhod3) { gchar *str; - g_print ("MHOD (%d):\n", sizeof (MhodHeaderArtworkType3)); + g_print ("MHOD [artwork type 3] (%d):\n", sizeof (MhodHeaderArtworkType3)); g_print ("\tHeader length: %d\n", GINT_FROM_LE (mhod3->header_len)); g_print ("\tTotal length: %d\n", GINT_FROM_LE (mhod3->total_len)); - g_print ("\tType: %d\n", GINT_FROM_LE (mhod3->type)); + g_print ("\tType: %08x\n", GINT_FROM_LE (mhod3->type)); g_print ("\tUnknown1: %08x\n", GINT_FROM_LE (mhod3->unknown1)); g_print ("\tUnknown2: %08x\n", GINT_FROM_LE (mhod3->unknown2)); g_print ("\tString length: %u\n", GINT_FROM_LE (mhod3->string_len)); @@ -82,6 +107,9 @@ dump_mhod_type_3 (MhodHeaderArtworkType3 *mhod3) G_GNUC_INTERNAL void dump_mhni (MhniHeader *mhni) { + unsigned int width = GINT16_FROM_LE (mhni->image_width); + unsigned int height = GINT16_FROM_LE (mhni->image_height); + g_print ("MHNI (%d):\n", sizeof (MhniHeader)); g_print ("\tHeader length: %d\n", GINT_FROM_LE (mhni->header_len)); g_print ("\tTotal length: %d\n", GINT_FROM_LE (mhni->total_len)); @@ -92,7 +120,7 @@ dump_mhni (MhniHeader *mhni) g_print ("\tithmb offset: %u bytes\n", GINT_FROM_LE (mhni->ithmb_offset)); g_print ("\tImage size: %u bytes\n", GINT_FROM_LE (mhni->image_size)); g_print ("\tUnknown3: %08x\n", GINT_FROM_LE (mhni->unknown3)); - g_print ("\tImage dimensions: %08x\n", GINT_FROM_LE (mhni->image_dimensions)); + g_print ("\tImage dimensions: %ux%u\n", width, height); } G_GNUC_INTERNAL void @@ -101,7 +129,7 @@ dump_mhod (MhodHeader *mhod) g_print ("MHOD (%d):\n", sizeof (MhodHeader)); g_print ("\tHeader length: %d\n", GINT_FROM_LE (mhod->header_len)); g_print ("\tTotal length: %d\n", GINT_FROM_LE (mhod->total_len)); - g_print ("\tType: %d\n", GINT_FROM_LE (mhod->type)); + g_print ("\tType: %08x\n", GINT_FROM_LE (mhod->type)); g_print ("\tUnknown1: %08x\n", GINT_FROM_LE (mhod->unknown1)); g_print ("\tUnknown2: %08x\n", GINT_FROM_LE (mhod->unknown2)); } @@ -163,7 +191,7 @@ dump_mhsd (MhsdHeader *mhsd) G_GNUC_INTERNAL void dump_mhfd (MhfdHeader *mhfd) { - g_print ("MHFD (%d): \n", sizeof (MhfdHeader)); + g_print ("MHFD (%d):\n", sizeof (MhfdHeader)); g_print ("\tHeader length: %d\n", GINT_FROM_LE (mhfd->header_len)); g_print ("\tTotal length: %d\n", GINT_FROM_LE (mhfd->total_len)); g_print ("\tUnknown1: %08x\n", GINT_FROM_LE (mhfd->unknown1)); @@ -179,4 +207,23 @@ dump_mhfd (MhfdHeader *mhfd) g_print ("\tUnknown10: %08x\n", GINT_FROM_LE (mhfd->unknown10)); g_print ("\tUnknown11: %08x\n", GINT_FROM_LE (mhfd->unknown11)); } + +G_GNUC_INTERNAL void +dump_mhba (MhbaHeader *mhba) +{ + int i; + + g_print ("MHBA (%d):\n", sizeof (MhbaHeader)); + g_print ("\tHeader length: %d\n", GINT_FROM_LE (mhba->header_len)); + g_print ("\tTotal length: %d\n", GINT_FROM_LE (mhba->total_len)); + g_print ("\tNumber of Data Objects: %d\n", GINT_FROM_LE (mhba->num_mhods)); + g_print ("\tNumber of pictures in the album: %d\n", GINT_FROM_LE (mhba->num_mhias)); + g_print ("\tPlaylist ID: %08x\n", GINT_FROM_LE (mhba->playlist_id)); + g_print ("\tUnknown2: %08x\n", GINT_FROM_LE (mhba->unknown2)); + g_print ("\tUnknown3: %08x\n", GINT_FROM_LE (mhba->unknown3)); + for (i = 0; i < 7; i++) + g_print ("\tUnknown[%d]: %08x\n", i, GINT_FROM_LE (mhba->unknown[i])); + g_print ("\tPrev playlist ID: %08x\n", GINT_FROM_LE (mhba->prev_playlist_id)); +} + #endif diff --git a/src/db-artwork-debug.h b/src/db-artwork-debug.h index fe9dd70..df35058 100644 --- a/src/db-artwork-debug.h +++ b/src/db-artwork-debug.h @@ -30,6 +30,8 @@ #ifdef DEBUG_ARTWORKDB extern G_GNUC_INTERNAL void dump_mhif (MhifHeader *mhif); +extern G_GNUC_INTERNAL void dump_mhia (MhiaHeader *mhia); +extern G_GNUC_INTERNAL void dump_mhod_type_1 (MhodHeaderArtworkType1 *mhod); extern G_GNUC_INTERNAL void dump_mhod_type_3 (MhodHeaderArtworkType3 *mhod); extern G_GNUC_INTERNAL void dump_mhni (MhniHeader *mhni); extern G_GNUC_INTERNAL void dump_mhod (MhodHeader *mhod); @@ -37,8 +39,11 @@ extern G_GNUC_INTERNAL void dump_mhii (MhiiHeader *mhii); extern G_GNUC_INTERNAL void dump_mhl (MhlHeader *mhl, const char *id); extern G_GNUC_INTERNAL void dump_mhsd (MhsdHeader *mhsd); extern G_GNUC_INTERNAL void dump_mhfd (MhfdHeader *mhfd); +extern G_GNUC_INTERNAL void dump_mhba (MhbaHeader *mhba); #else #define dump_mhif(x) +#define dump_mhia(x) +#define dump_mhod_type_1(x) #define dump_mhod_type_3(x) #define dump_mhni(x) #define dump_mhod(x) @@ -46,6 +51,7 @@ extern G_GNUC_INTERNAL void dump_mhfd (MhfdHeader *mhfd); #define dump_mhl(x,y) #define dump_mhsd(x) #define dump_mhfd(x) +#define dump_mhba(x) #endif #endif diff --git a/src/db-artwork-parser.c b/src/db-artwork-parser.c index 99473e8..2b05eaa 100644 --- a/src/db-artwork-parser.c +++ b/src/db-artwork-parser.c @@ -64,6 +64,20 @@ parse_mhif (DBParseContext *ctx, Itdb_iTunesDB *db, GError *error) return 0; } +static int +parse_mhia (DBParseContext *ctx, Itdb_iTunesDB *db, GError *error) +{ + MhiaHeader *mhia; + + mhia = db_parse_context_get_m_header (ctx, MhiaHeader, "mhia"); + if (mhia == NULL) { + return -1; + } + dump_mhia (mhia); + db_parse_context_set_total_len (ctx, GINT_FROM_LE (mhia->total_len)); + return 0; +} + #ifdef DEBUG_ARTWORKDB static int parse_mhod_3 (DBParseContext *ctx, GError *error) @@ -81,11 +95,11 @@ parse_mhod_3 (DBParseContext *ctx, GError *error) return -1; } mhod3 = (MhodHeaderArtworkType3*)mhod; - dump_mhod_type_3 (mhod3); - if ((GINT_FROM_LE (mhod3->type) & 0xff) != MHOD_TYPE_ALBUM) { + if ((GINT_FROM_LE (mhod3->type) & 0x00FFFFFF) != MHOD_ARTWORK_TYPE_FILE_NAME) { return -1; } + dump_mhod_type_3 (mhod3); return 0; } #endif @@ -111,6 +125,9 @@ parse_mhni (DBParseContext *ctx, iPodSong *song, GError *error) /* No information useful to us in mhod type 3, do not parse * it in non-debug mode + * FIXME: really? it contains the thumbnail file name! + * we infer it from the correlation id, but is this + * always The Right Thing to do? */ mhod_ctx = db_parse_context_get_sub_context (ctx, ctx->header_len); if (mhod_ctx == NULL) { @@ -133,24 +150,35 @@ parse_mhod (DBParseContext *ctx, iPodSong *song, GError *error) { MhodHeader *mhod; DBParseContext *mhni_ctx; + int type; mhod = db_parse_context_get_m_header (ctx, MhodHeader, "mhod"); if (mhod == NULL) { return -1; } db_parse_context_set_total_len (ctx, GINT_FROM_LE (mhod->total_len)); - dump_mhod (mhod); - if (GINT_FROM_LE (mhod->type) != MHOD_TYPE_LOCATION) { - return -1; - } - - mhni_ctx = db_parse_context_get_sub_context (ctx, ctx->header_len); - if (mhni_ctx == NULL) { - return -1; + /* The MHODs found in the ArtworkDB and Photo Database files are + * significantly different than those found in the iTunesDB. + * For example, the "type" is split like this: + * - low 3 bytes are actual type; + * - high byte is padding length of string (0-3). + */ + type = GINT_FROM_LE (mhod->type) & 0x00FFFFFF; + if (type == MHOD_ARTWORK_TYPE_ALBUM_NAME) + dump_mhod_type_1 ((MhodHeaderArtworkType1 *)mhod); + else + dump_mhod (mhod); + + /* if this is a container... */ + if (type == MHOD_ARTWORK_TYPE_THUMBNAIL) { + mhni_ctx = db_parse_context_get_sub_context (ctx, ctx->header_len); + if (mhni_ctx == NULL) { + return -1; + } + parse_mhni (mhni_ctx, song, NULL); + g_free (mhni_ctx); } - parse_mhni (mhni_ctx, song, NULL); - g_free (mhni_ctx); return 0; } @@ -205,6 +233,47 @@ parse_mhii (DBParseContext *ctx, Itdb_iTunesDB *db, GError *error) static int +parse_mhba (DBParseContext *ctx, Itdb_iTunesDB *db, GError *error) +{ + MhbaHeader *mhba; + DBParseContext *mhod_ctx; + DBParseContext *mhia_ctx; + int num_children; + off_t cur_offset; + + mhba = db_parse_context_get_m_header (ctx, MhbaHeader, "mhba"); + if (mhba == NULL) { + return -1; + } + db_parse_context_set_total_len (ctx, GINT_FROM_LE (mhba->total_len)); + + dump_mhba (mhba); + + cur_offset = ctx->header_len; + mhod_ctx = db_parse_context_get_sub_context (ctx, cur_offset); + num_children = GINT_FROM_LE (mhba->num_mhods); + while ((num_children > 0) && (mhod_ctx != NULL)) { + parse_mhod (mhod_ctx, NULL, NULL); + num_children--; + cur_offset += mhod_ctx->total_len; + g_free (mhod_ctx); + mhod_ctx = db_parse_context_get_sub_context (ctx, cur_offset); + } + mhia_ctx = db_parse_context_get_sub_context (ctx, cur_offset); + num_children = GINT_FROM_LE (mhba->num_mhias); + while ((num_children > 0) && (mhia_ctx != NULL)) { + parse_mhia (mhia_ctx, db, NULL); + num_children--; + cur_offset += mhia_ctx->total_len; + g_free (mhia_ctx); + mhia_ctx = db_parse_context_get_sub_context (ctx, cur_offset); + } + + return 0; +} + + +static int parse_mhl (DBParseContext *ctx, Itdb_iTunesDB *db, GError *error, const char *id, ParseListItem parse_child) { @@ -265,7 +334,7 @@ parse_mhsd (DBParseContext *ctx, Itdb_iTunesDB *db, GError **error) case MHSD_ALBUM_LIST: { DBParseContext *mhla_context; mhla_context = db_parse_context_get_next_child (ctx); - parse_mhl (mhla_context, db, NULL, "mhla", NULL); + parse_mhl (mhla_context, db, NULL, "mhla", parse_mhba); g_free (mhla_context); break; } @@ -304,6 +373,10 @@ parse_mhfd (DBParseContext *ctx, Itdb_iTunesDB *db, GError **error) dump_mhfd (mhfd); cur_pos = ctx->header_len; + /* The mhfd record always has 3 mhsd children, so it's hardcoded here. + * It could be replaced with a loop using the nb_children field from + * the mhfd record. [explanation by Christophe] + */ mhsd_context = db_parse_context_get_sub_context (ctx, cur_pos); if (mhsd_context == NULL) { return -1; diff --git a/src/db-artwork-writer.c b/src/db-artwork-writer.c index ca46417..655d05b 100644 --- a/src/db-artwork-writer.c +++ b/src/db-artwork-writer.c @@ -328,7 +328,6 @@ write_mhni (Itdb_Image *image, iPodBuffer *buffer) unsigned int total_bytes; int bytes_written; iPodBuffer *sub_buffer; - unsigned int dim; if (image == NULL) { return -1; @@ -351,12 +350,10 @@ write_mhni (Itdb_Image *image, iPodBuffer *buffer) mhni->correlation_id = GINT_TO_LE (IPOD_THUMBNAIL_FULL_SIZE_CORRELATION_ID); break; } - dim = image->width & 0xffff; - dim <<= 16; - dim |= image->height & 0xffff; - mhni->image_dimensions = GINT_TO_LE (dim); - mhni->image_size = GINT_TO_LE (image->size); - mhni->ithmb_offset = GINT_TO_LE (image->offset); + mhni->image_width = GINT16_TO_LE (image->width); + mhni->image_height = GINT16_TO_LE (image->height); + mhni->image_size = GINT32_TO_LE (image->size); + mhni->ithmb_offset = GINT32_TO_LE (image->offset); sub_buffer = ipod_buffer_get_sub_buffer (buffer, total_bytes); if (sub_buffer == NULL) { diff --git a/src/db-image-parser.c b/src/db-image-parser.c index 3842135..2d8e8dc 100644 --- a/src/db-image-parser.c +++ b/src/db-image-parser.c @@ -154,10 +154,10 @@ ipod_image_new_from_mhni (MhniHeader *mhni, const char *mount_point) } img->filename = ipod_image_get_ithmb_filename (mount_point, GINT_FROM_LE (mhni->correlation_id)); - img->size = GINT_FROM_LE (mhni->image_size); - img->offset = GINT_FROM_LE (mhni->ithmb_offset); - img->width = (GINT_FROM_LE (mhni->image_dimensions) & 0xffff0000) >> 16; - img->height = (GINT_FROM_LE (mhni->image_dimensions) & 0x0000ffff); + img->size = GINT32_FROM_LE (mhni->image_size); + img->offset = GINT32_FROM_LE (mhni->ithmb_offset); + img->width = GINT16_FROM_LE (mhni->image_width); + img->height = GINT16_FROM_LE (mhni->image_height); switch (mhni->correlation_id) { case IPOD_THUMBNAIL_FULL_SIZE_CORRELATION_ID: @@ -169,8 +169,8 @@ ipod_image_new_from_mhni (MhniHeader *mhni, const char *mount_point) img->type = ITDB_IMAGE_NOW_PLAYING; break; default: - g_print ("Unrecognized image size: %08x\n", - GINT_FROM_LE (mhni->image_dimensions)); + g_print ("Unrecognized image size: %ux%u\n", + img->width, img->height); g_free (img); return NULL; } diff --git a/src/db-itunes-parser.h b/src/db-itunes-parser.h index bf5f7f2..54ef6b5 100644 --- a/src/db-itunes-parser.h +++ b/src/db-itunes-parser.h @@ -61,12 +61,15 @@ 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 _MhodHeaderString MhodHeaderString; +typedef struct _MhodHeaderArtworkType1 MhodHeaderArtworkType1; typedef struct _MhodHeaderArtworkType3 MhodHeaderArtworkType3; typedef struct _MhodHeaderSmartPlaylistData MhodHeaderSmartPlaylistData; typedef struct _MhodHeaderSmartPlaylistRuleString MhodHeaderSmartPlaylistRuleString; @@ -311,11 +314,35 @@ struct _MhodHeaderString { gint32 unknown2; gint32 position; gint32 string_len; - gint32 encoding; + 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 _MhodHeaderArtworkType1 { + unsigned char header_id[4]; + gint32 header_len; + gint32 total_len; + gint32 type; /* low 3 bytes are type (always 1); high byte is padding length (0-3) */ + gint32 unknown1; + gint32 unknown2; + gint32 string_len; + gint32 unknown3; /* might be the string encoding */ + gint32 unknown4; /* always zero? */ + unsigned char string[]; +}; + struct _MhodHeaderArtworkType3 { unsigned char header_id[4]; gint32 header_len; @@ -507,7 +534,8 @@ struct _MhniHeader { gint32 ithmb_offset; gint32 image_size; gint32 unknown3; - gint32 image_dimensions; + gint16 image_height; + gint16 image_width; unsigned char padding[]; }; @@ -518,6 +546,21 @@ struct _MhlaHeader { 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 playlist_id; /* starts out at $64 and increments by 1 */ + gint32 unknown2; /* unknown, seems to be always 0 */ + gint32 unknown3; /* unknown, but is 0x10000 for the Photo Library and 0x60000 for normal albums + * (maybe not a 4 byte field?) */ + gint32 unknown[7]; /* more zeroes */ + gint32 prev_playlist_id; /* the id of the previous playlist */ + unsigned char padding[]; +}; + struct _MhlfHeader { unsigned char header_id[4]; gint32 header_len; @@ -535,6 +578,15 @@ struct _MhifHeader { 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 */ + gint32 image_id; /* the id of the mhii record this mhia refers to */ + unsigned char padding[]; +}; #endif /* PARSE_DB_H */ |