diff options
author | jcsjcs <jcsjcs@f01d2545-417e-4e96-918e-98f8d0dbbcb6> | 2006-03-23 15:06:32 +0000 |
---|---|---|
committer | jcsjcs <jcsjcs@f01d2545-417e-4e96-918e-98f8d0dbbcb6> | 2006-03-23 15:06:32 +0000 |
commit | aabf1eb86076a811d69ca4d1d84d85491b17e394 (patch) | |
tree | 405f62eac144bf39a2acb281f474b0ccf531f22c /src | |
parent | 83e5c938530cb4e04356c6d1be9e1da67234d599 (diff) | |
download | libgpod-aabf1eb86076a811d69ca4d1d84d85491b17e394.tar.gz libgpod-aabf1eb86076a811d69ca4d1d84d85491b17e394.tar.xz libgpod-aabf1eb86076a811d69ca4d1d84d85491b17e394.zip |
Alpha version of reversed-endian Artwork writing. Status: iTunesDB
can be written and is accepted on mobile phones, ArtworkDB can be
read and be written as well, but newly added artwork will not yet
display.
* itdb.h: adjusted a couple of field lengths (4 byte -> 2 byte or
even 1 byte) to address endian issues.
git-svn-id: https://gtkpod.svn.sf.net/svnroot/gtkpod/libgpod/trunk@1225 f01d2545-417e-4e96-918e-98f8d0dbbcb6
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 1 | ||||
-rw-r--r-- | src/db-artwork-debug.c | 6 | ||||
-rw-r--r-- | src/db-artwork-parser.c | 111 | ||||
-rw-r--r-- | src/db-artwork-parser.h | 6 | ||||
-rw-r--r-- | src/db-artwork-writer.c | 201 | ||||
-rw-r--r-- | src/db-image-parser.c | 20 | ||||
-rw-r--r-- | src/db-itunes-parser.h | 69 | ||||
-rw-r--r-- | src/db-parse-context.c | 24 | ||||
-rw-r--r-- | src/db-parse-context.h | 36 | ||||
-rw-r--r-- | src/itdb.h | 15 | ||||
-rw-r--r-- | src/itdb_artwork.c | 9 | ||||
-rw-r--r-- | src/itdb_device.c | 26 | ||||
-rw-r--r-- | src/itdb_device.h | 14 | ||||
-rw-r--r-- | src/itdb_endianness.h | 60 | ||||
-rw-r--r-- | src/itdb_itunesdb.c | 19 | ||||
-rw-r--r-- | src/itdb_track.c | 12 | ||||
-rw-r--r-- | src/ithumb-writer.c | 22 |
17 files changed, 454 insertions, 197 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 11feb18..b2c70d4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -20,6 +20,7 @@ libgpod_la_SOURCES = \ ithumb-writer.c \ itdb_device.c \ itdb_device.h \ + itdb_endianness.h \ glib-compat.h diff --git a/src/db-artwork-debug.c b/src/db-artwork-debug.c index 3903038..5d8d3b8 100644 --- a/src/db-artwork-debug.c +++ b/src/db-artwork-debug.c @@ -24,6 +24,8 @@ #include "db-artwork-debug.h" +/* FIXME: endianness (whole file) */ + #ifdef DEBUG_ARTWORKDB G_GNUC_INTERNAL void dump_mhif (MhifHeader *mhif) @@ -169,8 +171,8 @@ dump_mhsd (MhsdHeader *mhsd) g_print ("MHSD (%d):\n", sizeof (MhsdHeader)); g_print ("\tHeader length: %d\n", GINT_FROM_LE (mhsd->header_len)); g_print ("\tTotal length: %d\n", GINT_FROM_LE (mhsd->total_len)); - g_print ("\tIndex: %d ", GINT_FROM_LE (mhsd->index)); - switch (GINT_FROM_LE (mhsd->index)) { + g_print ("\tIndex: %d ", GINT16_FROM_LE (mhsd->index)); + switch (GINT16_FROM_LE (mhsd->index)) { case MHSD_IMAGE_LIST: g_print ("(Image list)\n"); break; diff --git a/src/db-artwork-parser.c b/src/db-artwork-parser.c index 0599b78..17dd390 100644 --- a/src/db-artwork-parser.c +++ b/src/db-artwork-parser.c @@ -31,6 +31,7 @@ #include <sys/types.h> #include "itdb.h" +#include "itdb_endianness.h" #include "db-artwork-debug.h" #include "db-artwork-parser.h" #include "db-image-parser.h" @@ -69,7 +70,7 @@ parse_mhif (DBParseContext *ctx, Itdb_iTunesDB *db, GError *error) return -1; } dump_mhif (mhif); - db_parse_context_set_total_len (ctx, GINT_FROM_LE (mhif->total_len)); + db_parse_context_set_total_len (ctx, get_gint32_db (db, mhif->total_len)); return 0; } @@ -83,12 +84,12 @@ parse_mhia (DBParseContext *ctx, Itdb_iTunesDB *db, GError *error) return -1; } dump_mhia (mhia); - db_parse_context_set_total_len (ctx, GINT_FROM_LE (mhia->total_len)); + db_parse_context_set_total_len (ctx, get_gint32_db (db, mhia->total_len)); return 0; } static char * -get_utf16_string (void* buffer, gint length) +get_utf16_string (void* buffer, gint length, guint byte_order) { char *result; gunichar2 *tmp; @@ -98,7 +99,7 @@ get_utf16_string (void* buffer, gint length) */ tmp = g_memdup (buffer, length); for (i = 0; i < length/2; i++) { - tmp[i] = GINT16_FROM_LE (tmp[i]); + tmp[i] = get_gint16 (tmp[i], byte_order); } result = g_utf16_to_utf8 (tmp, length/2, NULL, NULL, NULL); g_free (tmp); @@ -108,15 +109,25 @@ get_utf16_string (void* buffer, gint length) } static char * -mhod3_get_ithmb_filename (MhodHeaderArtworkType3 *mhod3, +mhod3_get_ithmb_filename (ArtworkDB_MhodHeaderArtworkType3 *mhod3, Itdb_iTunesDB *db) { - char *filename; + char *filename=NULL; g_assert (mhod3 != NULL); g_assert (db != NULL); - - filename = get_utf16_string (mhod3->string, mhod3->string_len); + + if (mhod3->mhod_version == 2) + filename = get_utf16_string ((gunichar2 *)mhod3->string, + get_gint32_db (db, mhod3->string_len), + db->device->byte_order); + else if ((mhod3->mhod_version == 0) || + (mhod3->mhod_version == 1)) + filename = g_strndup (mhod3->string, + get_gint32_db (db, mhod3->string_len)); + else + g_warning (_("Unexpected mhod3 string type: %d\n"), + mhod3->mhod_version); return filename; } @@ -125,20 +136,22 @@ static int parse_mhod_3 (DBParseContext *ctx, Itdb_iTunesDB *db, Itdb_Thumb *thumb, GError *error) { - MhodHeader *mhod; - MhodHeaderArtworkType3 *mhod3; + ArtworkDB_MhodHeader *mhod; + ArtworkDB_MhodHeaderArtworkType3 *mhod3; + gint32 mhod3_type; - mhod = db_parse_context_get_m_header (ctx, MhodHeader, "mhod"); + mhod = db_parse_context_get_m_header (ctx, ArtworkDB_MhodHeader, "mhod"); if (mhod == NULL) { return -1; } - db_parse_context_set_total_len (ctx, GINT_FROM_LE (mhod->total_len)); + db_parse_context_set_total_len (ctx, get_gint32_db (db, mhod->total_len)); - if (GINT_FROM_LE (mhod->total_len) < sizeof (MhodHeaderArtworkType3)){ + if (get_gint32_db (db, mhod->total_len) < sizeof (ArtworkDB_MhodHeaderArtworkType3)){ return -1; } - mhod3 = (MhodHeaderArtworkType3*)mhod; - if ((GINT_FROM_LE (mhod3->type) & 0x00FFFFFF) != MHOD_ARTWORK_TYPE_FILE_NAME) { + mhod3 = (ArtworkDB_MhodHeaderArtworkType3*)mhod; + mhod3_type = get_gint16_db (db, mhod3->type); + if (mhod3_type != MHOD_ARTWORK_TYPE_FILE_NAME) { return -1; } thumb->filename = mhod3_get_ithmb_filename (mhod3, db); @@ -157,7 +170,7 @@ parse_mhni (DBParseContext *ctx, iPodSong *song, GError *error) if (mhni == NULL) { return -1; } - db_parse_context_set_total_len (ctx, GINT_FROM_LE (mhni->total_len)); + db_parse_context_set_total_len (ctx, get_gint32_db (song->itdb, mhni->total_len)); dump_mhni (mhni); thumb = ipod_image_new_from_mhni (mhni, song->itdb); @@ -181,15 +194,17 @@ parse_mhni (DBParseContext *ctx, iPodSong *song, GError *error) static int parse_mhod (DBParseContext *ctx, iPodSong *song, GError *error) { - MhodHeader *mhod; + ArtworkDB_MhodHeader *mhod; DBParseContext *mhni_ctx; int type; + gint32 total_len; - mhod = db_parse_context_get_m_header (ctx, MhodHeader, "mhod"); + mhod = db_parse_context_get_m_header (ctx, ArtworkDB_MhodHeader, "mhod"); if (mhod == NULL) { return -1; } - db_parse_context_set_total_len (ctx, GINT_FROM_LE (mhod->total_len)); + total_len = get_gint32_db (song->itdb, mhod->total_len); + db_parse_context_set_total_len (ctx, total_len); /* The MHODs found in the ArtworkDB and Photo Database files are * significantly different than those found in the iTunesDB. @@ -197,7 +212,7 @@ parse_mhod (DBParseContext *ctx, iPodSong *song, GError *error) * - low 3 bytes are actual type; * - high byte is padding length of string (0-3). */ - type = GINT_FROM_LE (mhod->type) & 0x00FFFFFF; + type = get_gint16_db (song->itdb, mhod->type); if (type == MHOD_ARTWORK_TYPE_ALBUM_NAME) dump_mhod_type_1 ((MhodHeaderArtworkType1 *)mhod); else @@ -230,30 +245,30 @@ parse_mhii (DBParseContext *ctx, Itdb_iTunesDB *db, GError *error) if (mhii == NULL) { return -1; } - db_parse_context_set_total_len (ctx, GINT_FROM_LE (mhii->total_len)); + db_parse_context_set_total_len (ctx, get_gint32_db (db, mhii->total_len)); dump_mhii (mhii); #ifdef DEBUG_ARTWORKDB song = NULL; #else - song = get_song_by_dbid (db, GINT64_FROM_LE (mhii->song_id)); + song = get_song_by_dbid (db, get_gint64_db (db, mhii->song_id)); if (song == NULL) { return -1; } - song->artwork->artwork_size = GINT_FROM_LE (mhii->orig_img_size); + song->artwork->artwork_size = get_gint32_db (db, mhii->orig_img_size); if ((song->artwork_size+song->artwork_count) != song->artwork->artwork_size) { g_warning (_("iTunesDB and ArtworkDB artwork sizes inconsistent (%d+%d != %d)"), song->artwork_size, song->artwork_count, song->artwork->artwork_size); } - song->artwork->id = GINT_FROM_LE (mhii->image_id); + song->artwork->id = get_gint32_db (db, mhii->image_id); #endif cur_offset = ctx->header_len; mhod_ctx = db_parse_context_get_sub_context (ctx, cur_offset); - num_children = GINT_FROM_LE (mhii->num_children); + num_children = get_gint32_db (db, mhii->num_children); while ((num_children > 0) && (mhod_ctx != NULL)) { parse_mhod (mhod_ctx, song, NULL); num_children--; @@ -279,13 +294,13 @@ parse_mhba (DBParseContext *ctx, Itdb_iTunesDB *db, GError *error) if (mhba == NULL) { return -1; } - db_parse_context_set_total_len (ctx, GINT_FROM_LE (mhba->total_len)); + db_parse_context_set_total_len (ctx, get_gint32_db (db, 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); + num_children = get_gint32_db (db, mhba->num_mhods); while ((num_children > 0) && (mhod_ctx != NULL)) { parse_mhod (mhod_ctx, NULL, NULL); num_children--; @@ -294,7 +309,7 @@ parse_mhba (DBParseContext *ctx, Itdb_iTunesDB *db, GError *error) 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); + num_children = get_gint32_db (db, mhba->num_mhias); while ((num_children > 0) && (mhia_ctx != NULL)) { parse_mhia (mhia_ctx, db, NULL); num_children--; @@ -323,7 +338,7 @@ parse_mhl (DBParseContext *ctx, Itdb_iTunesDB *db, GError *error, dump_mhl (mhl, id); - num_children = GINT_FROM_LE (mhl->num_children); + num_children = get_gint32_db (db, mhl->num_children); if (num_children < 0) { return -1; } @@ -348,16 +363,16 @@ parse_mhl (DBParseContext *ctx, Itdb_iTunesDB *db, GError *error, static int parse_mhsd (DBParseContext *ctx, Itdb_iTunesDB *db, GError **error) { - MhsdHeader *mhsd; + ArtworkDB_MhsdHeader *mhsd; - mhsd = db_parse_context_get_m_header (ctx, MhsdHeader, "mhsd"); + mhsd = db_parse_context_get_m_header (ctx, ArtworkDB_MhsdHeader, "mhsd"); if (mhsd == NULL) { return -1; } - db_parse_context_set_total_len (ctx, GINT_FROM_LE (mhsd->total_len)); + db_parse_context_set_total_len (ctx, get_gint32_db (db, mhsd->total_len)); dump_mhsd (mhsd); - switch (GINT_FROM_LE (mhsd->index)) { + switch (get_gint16_db (db, mhsd->index)) { case MHSD_IMAGE_LIST: { DBParseContext *mhli_context; mhli_context = db_parse_context_get_next_child (ctx); @@ -381,7 +396,7 @@ parse_mhsd (DBParseContext *ctx, Itdb_iTunesDB *db, GError **error) } default: g_warning (_("Unexpected mhsd index: %d\n"), - GINT_FROM_LE (mhsd->index)); + get_gint16_db (db, mhsd->index)); return -1; break; } @@ -396,6 +411,7 @@ parse_mhfd (DBParseContext *ctx, Itdb_iTunesDB *db, GError **error) MhfdHeader *mhfd; DBParseContext *mhsd_context; unsigned int cur_pos; + gint total_len; mhfd = db_parse_context_get_m_header (ctx, MhfdHeader, "mhfd"); if (mhfd == NULL) { @@ -403,7 +419,8 @@ parse_mhfd (DBParseContext *ctx, Itdb_iTunesDB *db, GError **error) } /* Sanity check */ - g_return_val_if_fail (GINT_FROM_LE (mhfd->total_len) == ctx->total_len, -1); + total_len = get_gint32_db (db, mhfd->total_len); + g_return_val_if_fail (total_len == ctx->total_len, -1); dump_mhfd (mhfd); cur_pos = ctx->header_len; @@ -480,15 +497,6 @@ ipod_db_get_artwork_db_path (const char *mount_point) } -static char * -ipod_db_get_photo_db_path (const char *mount_point) -{ - const char *paths[] = {"Photos", "Photo Database", NULL}; - g_return_val_if_fail (mount_point != NULL, NULL); - return itdb_resolve_path (mount_point, paths); - -} - static gboolean ipod_supports_cover_art (Itdb_Device *device) { @@ -535,7 +543,9 @@ ipod_parse_artwork_db (Itdb_iTunesDB *db) { goto error; } - ctx = db_parse_context_new_from_file (filename); + + ctx = db_parse_context_new_from_file (filename, + db->device->byte_order); g_free (filename); if (ctx == NULL) { goto error; @@ -552,6 +562,16 @@ ipod_parse_artwork_db (Itdb_iTunesDB *db) return -1; } +#if 0 +static char * +ipod_db_get_photo_db_path (const char *mount_point) +{ + const char *paths[] = {"Photos", "Photo Database", NULL}; + g_return_val_if_fail (mount_point != NULL, NULL); + return itdb_resolve_path (mount_point, paths); + +} + int ipod_parse_photo_db (const char *mount_point) { @@ -573,3 +593,4 @@ ipod_parse_photo_db (const char *mount_point) return 0; } +#endif diff --git a/src/db-artwork-parser.h b/src/db-artwork-parser.h index 5c117fa..c97ee17 100644 --- a/src/db-artwork-parser.h +++ b/src/db-artwork-parser.h @@ -30,9 +30,11 @@ #define iPodSong Itdb_Track -G_GNUC_INTERNAL int ipod_parse_photo_db (const char *filename); +G_GNUC_INTERNAL char *ipod_db_get_artwork_db_path (const char *mount_point); G_GNUC_INTERNAL int ipod_parse_artwork_db (Itdb_iTunesDB *db); G_GNUC_INTERNAL int ipod_write_artwork_db (Itdb_iTunesDB *db); -G_GNUC_INTERNAL char *ipod_db_get_artwork_db_path (const char *mount_point); +#if 0 +G_GNUC_INTERNAL int ipod_parse_photo_db (const char *filename); +#endif #endif diff --git a/src/db-artwork-writer.c b/src/db-artwork-writer.c index b890495..2b8d91b 100644 --- a/src/db-artwork-writer.c +++ b/src/db-artwork-writer.c @@ -31,6 +31,7 @@ #include "db-artwork-debug.h" #include "db-itunes-parser.h" #include "db-image-parser.h" +#include "itdb_endianness.h" #include <errno.h> #include <fcntl.h> @@ -57,6 +58,7 @@ struct iPodMmapBuffer { struct _iPodBuffer { struct iPodMmapBuffer *mmap; off_t offset; + guint byte_order; }; typedef struct _iPodBuffer iPodBuffer; @@ -172,6 +174,7 @@ ipod_buffer_get_sub_buffer (iPodBuffer *buffer, off_t offset) } sub_buffer->mmap = buffer->mmap; sub_buffer->offset = buffer->offset + offset; + sub_buffer->byte_order = buffer->byte_order; buffer->mmap->ref_count++; @@ -179,7 +182,7 @@ ipod_buffer_get_sub_buffer (iPodBuffer *buffer, off_t offset) } static iPodBuffer * -ipod_buffer_new (const char *filename) +ipod_buffer_new (const char *filename, guint byte_order) { int fd; struct iPodMmapBuffer *mmap_buf; @@ -224,6 +227,7 @@ ipod_buffer_new (const char *filename) return NULL; } buffer->mmap = mmap_buf; + buffer->byte_order = byte_order; return buffer; } @@ -239,9 +243,6 @@ enum iPodThumbnailType { IPOD_THUMBNAIL_NOW_PLAYING }; -#define IPOD_THUMBNAIL_FULL_SIZE_SIZE (140*140*2) -#define IPOD_THUMBNAIL_NOW_PLAYING_SIZE (56*56*2) - #define RETURN_SIZE_FOR(id, size) if (strncmp (id, header_id, 4) == 0) return (size) @@ -266,12 +267,13 @@ get_padded_header_size (gchar header_id[4]) } static void * -init_header (iPodBuffer *buffer, gchar header_id[4], guint header_len) +init_header (iPodBuffer *buffer, gchar _header_id[4], guint header_len) { MHeader *mh; int padded_size; + gchar *header_id; - padded_size = get_padded_header_size (header_id); + padded_size = get_padded_header_size (_header_id); if (padded_size != 0) { header_len = padded_size; } @@ -281,9 +283,15 @@ init_header (iPodBuffer *buffer, gchar header_id[4], guint header_len) } mh = (MHeader*)ipod_buffer_get_pointer (buffer); memset (mh, 0, header_len); + + header_id = g_strndup (_header_id, 4); + if (buffer->byte_order == G_BIG_ENDIAN) { + g_strreverse (header_id); + } strncpy ((char *)mh->header_id, header_id, 4); - mh->header_len = GINT_TO_LE (header_len); - + mh->header_len = get_gint32 (header_len, buffer->byte_order); + + g_free (header_id); return mh; } @@ -291,48 +299,78 @@ init_header (iPodBuffer *buffer, gchar header_id[4], guint header_len) static int write_mhod_type_3 (Itdb_Thumb *thumb, iPodBuffer *buffer) { - MhodHeaderArtworkType3 *mhod; + ArtworkDB_MhodHeaderArtworkType3 *mhod; unsigned int total_bytes; int len; - gunichar2 *utf16; - int i; + gunichar2 *utf16, *strp; + int i, pad; g_assert (thumb->filename != NULL); - mhod = (MhodHeaderArtworkType3 *)init_header (buffer, "mhod", - sizeof (MhodHeaderArtworkType3)); + mhod = (ArtworkDB_MhodHeaderArtworkType3 *) + init_header (buffer, "mhod", + sizeof (ArtworkDB_MhodHeaderArtworkType3)); if (mhod == NULL) { return -1; } - total_bytes = sizeof (MhodHeaderArtworkType3); - mhod->total_len = GINT_TO_LE (total_bytes); + total_bytes = sizeof (ArtworkDB_MhodHeaderArtworkType3); + mhod->total_len = get_gint32 (total_bytes, buffer->byte_order); /* Modify header length, since iTunes only puts the length of * MhodHeader in header_len */ - mhod->header_len = GINT_TO_LE (sizeof (MhodHeader)); - mhod->type = GINT_TO_LE (3); - mhod->mhod_version = GINT_TO_LE (2); + mhod->header_len = get_gint32 (sizeof (ArtworkDB_MhodHeader), + buffer->byte_order); + mhod->type = get_gint16 (3, buffer->byte_order); len = strlen (thumb->filename); - /* number of bytes of the string encoded in UTF-16 */ - mhod->string_len = GINT_TO_LE (2*len); - /* Make sure we have enough free space to write the string */ - if (ipod_buffer_maybe_grow (buffer, total_bytes + 2*len) != 0) { + if (ipod_buffer_maybe_grow (buffer, total_bytes + 2*len+2) != 0) { return -1; } - utf16 = g_utf8_to_utf16 (thumb->filename, -1, NULL, NULL, NULL); - if (utf16 == NULL) { + + /* Some magic: endianess-reversed (BE) mobile phones use UTF8 + * (version 1) with padding, standard iPods (LE) use UTF16 + * (version 2).*/ + + switch (buffer->byte_order) + { + case G_LITTLE_ENDIAN: + mhod->mhod_version = 2; + + /* number of bytes of the string encoded in UTF-16 */ + mhod->string_len = get_gint32 (2*len, buffer->byte_order); + + utf16 = g_utf8_to_utf16 (thumb->filename, -1, NULL, NULL, NULL); + if (utf16 == NULL) { return -1; - } - memcpy (mhod->string, utf16, 2*len); - g_free (utf16); - for (i = 0; i < len; i++) { - mhod->string[i] = GINT_TO_LE (mhod->string[i]); - } - total_bytes += 2*len; - mhod->total_len = GINT_TO_LE (total_bytes); + } + strp = (gunichar2 *)mhod->string; + memcpy (strp, utf16, 2*len); + g_free (utf16); + for (i = 0; i < len; i++) { + strp[i] = get_gint16 (strp[i], buffer->byte_order); + } + total_bytes += 2*len; + break; + case G_BIG_ENDIAN: + mhod->mhod_version = 1; + mhod->string_len = get_gint32 (len, buffer->byte_order); + memcpy (mhod->string, thumb->filename, len); + /* pad string if necessary */ + /* e.g. len = 7 bytes, len%4 = 3, 4-3=1 -> requires 1 byte + padding */ + pad = 4 - (len % 4); + if (pad == 4) pad = 0; + for (i=0; i<pad; ++i) + { + mhod->string[len+i] = 0; + } + mhod->padding = pad; + total_bytes += (len+pad); + } + + mhod->total_len = get_gint32 (total_bytes, buffer->byte_order); dump_mhod_type_3 (mhod); @@ -356,14 +394,14 @@ write_mhni (Itdb_Thumb *thumb, int correlation_id, iPodBuffer *buffer) if (mhni == NULL) { return -1; } - total_bytes = GINT_FROM_LE (mhni->header_len); - mhni->total_len = GINT_TO_LE (total_bytes); + total_bytes = get_gint32 (mhni->header_len, buffer->byte_order); + mhni->total_len = get_gint32 (total_bytes, buffer->byte_order); - mhni->correlation_id = GINT_TO_LE (correlation_id); - mhni->image_width = GINT16_TO_LE (thumb->width); - mhni->image_height = GINT16_TO_LE (thumb->height); - mhni->image_size = GINT32_TO_LE (thumb->size); - mhni->ithmb_offset = GINT32_TO_LE (thumb->offset); + mhni->correlation_id = get_gint32 (correlation_id, buffer->byte_order); + mhni->image_width = get_gint16 (thumb->width, buffer->byte_order); + mhni->image_height = get_gint16 (thumb->height, buffer->byte_order); + mhni->image_size = get_gint32 (thumb->size, buffer->byte_order); + mhni->ithmb_offset = get_gint32 (thumb->offset, buffer->byte_order); sub_buffer = ipod_buffer_get_sub_buffer (buffer, total_bytes); if (sub_buffer == NULL) { @@ -375,11 +413,11 @@ write_mhni (Itdb_Thumb *thumb, int correlation_id, iPodBuffer *buffer) return -1; } total_bytes += bytes_written; - mhni->total_len = GINT_TO_LE (total_bytes); + mhni->total_len = get_gint32 (total_bytes, buffer->byte_order); /* Only update number of children when all went well to try to get * something somewhat consistent when there are errors */ - mhni->num_children = GINT_TO_LE (1); + mhni->num_children = get_gint32 (1, buffer->byte_order); dump_mhni (mhni); @@ -389,7 +427,7 @@ write_mhni (Itdb_Thumb *thumb, int correlation_id, iPodBuffer *buffer) static int write_mhod (Itdb_Thumb *thumb, int correlation_id, iPodBuffer *buffer) { - MhodHeader *mhod; + ArtworkDB_MhodHeader *mhod; unsigned int total_bytes; int bytes_written; iPodBuffer *sub_buffer; @@ -398,14 +436,15 @@ write_mhod (Itdb_Thumb *thumb, int correlation_id, iPodBuffer *buffer) return -1; } - mhod = (MhodHeader *)init_header (buffer, "mhod", - sizeof (MhodHeader)); + mhod = (ArtworkDB_MhodHeader *) + init_header (buffer, "mhod", + sizeof (ArtworkDB_MhodHeader)); if (mhod == NULL) { return -1; } - total_bytes = sizeof (MhodHeader); - mhod->total_len = GINT_TO_LE (total_bytes); - mhod->type = GINT_TO_LE (MHOD_TYPE_LOCATION); + total_bytes = sizeof (ArtworkDB_MhodHeader); + mhod->total_len = get_gint32 (total_bytes, buffer->byte_order); + mhod->type = get_gint16 (MHOD_TYPE_LOCATION, buffer->byte_order); sub_buffer = ipod_buffer_get_sub_buffer (buffer, total_bytes); if (sub_buffer == NULL) { return -1; @@ -416,7 +455,7 @@ write_mhod (Itdb_Thumb *thumb, int correlation_id, iPodBuffer *buffer) return -1; } total_bytes += bytes_written; - mhod->total_len = GINT_TO_LE (total_bytes); + mhod->total_len = get_gint32 (total_bytes, buffer->byte_order); dump_mhod (mhod); @@ -436,18 +475,20 @@ write_mhii (Itdb_Track *song, iPodBuffer *buffer) if (mhii == NULL) { return -1; } - total_bytes = GINT_FROM_LE (mhii->header_len); - mhii->song_id = GINT64_TO_LE (song->dbid); - mhii->image_id = GUINT_TO_LE (song->artwork->id); - mhii->orig_img_size = GINT_TO_LE (song->artwork->artwork_size); + total_bytes = get_gint32 (mhii->header_len, buffer->byte_order); + mhii->song_id = get_gint64 (song->dbid, buffer->byte_order); + mhii->image_id = get_guint32 (song->artwork->id, buffer->byte_order); + mhii->orig_img_size = get_gint32 (song->artwork->artwork_size, + buffer->byte_order); num_children = 0; for (it = song->artwork->thumbnails; it != NULL; it = it->next) { iPodBuffer *sub_buffer; Itdb_Thumb *thumb; const Itdb_ArtworkFormat *img_info; - mhii->num_children = GINT_TO_LE (num_children); - mhii->total_len = GINT_TO_LE (total_bytes); + mhii->num_children = get_gint32 (num_children, + buffer->byte_order); + mhii->total_len = get_gint32 (total_bytes, buffer->byte_order); sub_buffer = ipod_buffer_get_sub_buffer (buffer, total_bytes); if (sub_buffer == NULL) { return -1; @@ -471,8 +512,8 @@ write_mhii (Itdb_Track *song, iPodBuffer *buffer) num_children++; } - mhii->num_children = GINT_TO_LE (num_children); - mhii->total_len = GINT_TO_LE (total_bytes); + mhii->num_children = get_gint32 (num_children, buffer->byte_order); + mhii->total_len = get_gint32 (total_bytes, buffer->byte_order); dump_mhii (mhii); @@ -493,7 +534,7 @@ write_mhli (Itdb_iTunesDB *db, iPodBuffer *buffer) } num_thumbs = 0; - total_bytes = GINT_FROM_LE (mhli->header_len); + total_bytes = get_gint32 (mhli->header_len, buffer->byte_order); for (it = db->tracks; it != NULL; it = it->next) { Itdb_Track *song; int bytes_written; @@ -515,7 +556,7 @@ write_mhli (Itdb_iTunesDB *db, iPodBuffer *buffer) } } - mhli->num_children = GINT_TO_LE (num_thumbs); + mhli->num_children = get_gint32 (num_thumbs, buffer->byte_order); dump_mhl ((MhlHeader *)mhli, "mhli"); @@ -534,7 +575,7 @@ write_mhla (Itdb_iTunesDB *db, iPodBuffer *buffer) dump_mhl ((MhlHeader *)mhla, "mhla"); - return GINT_FROM_LE (mhla->header_len); + return get_gint32 (mhla->header_len, buffer->byte_order); } @@ -556,12 +597,14 @@ write_mhif (Itdb_iTunesDB *db, iPodBuffer *buffer, enum iPodThumbnailType type) return -1; } - mhif->correlation_id = GINT_TO_LE (img_info->correlation_id); - mhif->image_size = GINT_TO_LE (img_info->height * img_info->width * 2); + mhif->correlation_id = get_gint32 (img_info->correlation_id, + buffer->byte_order); + mhif->image_size = get_gint32 (img_info->height * img_info->width * 2, + buffer->byte_order); dump_mhif (mhif); - return GINT_FROM_LE (mhif->header_len); + return get_gint32 (mhif->header_len, buffer->byte_order); } @@ -578,7 +621,7 @@ write_mhlf (Itdb_iTunesDB *db, iPodBuffer *buffer) return -1; } - total_bytes = GINT_FROM_LE (mhlf->header_len); + total_bytes = get_gint32 (mhlf->header_len, buffer->byte_order); sub_buffer = ipod_buffer_get_sub_buffer (buffer, total_bytes); if (sub_buffer == NULL) { @@ -598,7 +641,7 @@ write_mhlf (Itdb_iTunesDB *db, iPodBuffer *buffer) * thumbnails: F1016_1.ithmb for the bigger thumbnails (39200 bytes) * and F1017_1.ithmb for the 'now playing' thumbnails (6272) */ - mhlf->num_files = GINT_TO_LE (1); + mhlf->num_files = get_gint32 (1, buffer->byte_order); sub_buffer = ipod_buffer_get_sub_buffer (buffer, total_bytes); if (sub_buffer == NULL) { @@ -618,7 +661,7 @@ write_mhlf (Itdb_iTunesDB *db, iPodBuffer *buffer) * thumbnails: F1016_1.ithmb for the bigger thumbnails (39200 bytes) * and F1017_1.ithmb for the 'now playing' thumbnails (6272) */ - mhlf->num_files = GINT_TO_LE (2); + mhlf->num_files = get_gint32 (2, buffer->byte_order); dump_mhl ((MhlHeader *)mhlf, "mhlf"); @@ -629,20 +672,20 @@ write_mhlf (Itdb_iTunesDB *db, iPodBuffer *buffer) static int write_mhsd (Itdb_iTunesDB *db, iPodBuffer *buffer, enum MhsdType type) { - MhsdHeader *mhsd; + ArtworkDB_MhsdHeader *mhsd; unsigned int total_bytes; int bytes_written; iPodBuffer *sub_buffer; g_assert (type >= MHSD_TYPE_MHLI); g_assert (type <= MHSD_TYPE_MHLF); - mhsd = (MhsdHeader *)init_header (buffer, "mhsd", sizeof (MhsdHeader)); + mhsd = (ArtworkDB_MhsdHeader *)init_header (buffer, "mhsd", sizeof (ArtworkDB_MhsdHeader)); if (mhsd == NULL) { return -1; } - total_bytes = GINT_FROM_LE (mhsd->header_len); - mhsd->total_len = GINT_TO_LE (total_bytes); - mhsd->index = GINT_TO_LE (type); + total_bytes = get_gint32 (mhsd->header_len, buffer->byte_order); + mhsd->total_len = get_gint32 (total_bytes, buffer->byte_order); + mhsd->index = get_gint16 (type, buffer->byte_order); bytes_written = -1; sub_buffer = ipod_buffer_get_sub_buffer (buffer, total_bytes); @@ -665,7 +708,7 @@ write_mhsd (Itdb_iTunesDB *db, iPodBuffer *buffer, enum MhsdType type) return -1; } else { total_bytes += bytes_written; - mhsd->total_len = GINT_TO_LE (total_bytes); + mhsd->total_len = get_gint32 (total_bytes, buffer->byte_order); } dump_mhsd (mhsd); @@ -685,11 +728,11 @@ write_mhfd (Itdb_iTunesDB *db, iPodBuffer *buffer, int id_max) if (mhfd == NULL) { return -1; } - total_bytes = GINT_FROM_LE (mhfd->header_len); - mhfd->total_len = GINT_TO_LE (total_bytes); - mhfd->unknown2 = GINT_TO_LE (1); - mhfd->unknown4 = GINT_TO_LE (id_max); - mhfd->unknown7 = GINT_TO_LE (2); + total_bytes = get_gint32 (mhfd->header_len, buffer->byte_order); + mhfd->total_len = get_gint32 (total_bytes, buffer->byte_order); + mhfd->unknown2 = get_gint32 (1, buffer->byte_order); + mhfd->unknown4 = get_gint32 (id_max, buffer->byte_order); + mhfd->unknown_flag1 = 2; for (i = 1 ; i <= 3; i++) { iPodBuffer *sub_buffer; @@ -703,8 +746,8 @@ write_mhfd (Itdb_iTunesDB *db, iPodBuffer *buffer, int id_max) return -1; } total_bytes += bytes_written; - mhfd->total_len = GINT_TO_LE (total_bytes); - mhfd->num_children = GINT_TO_LE (i); + mhfd->total_len = get_gint32 (total_bytes, buffer->byte_order); + mhfd->num_children = get_gint32 (i, buffer->byte_order); } dump_mhfd (mhfd); @@ -756,7 +799,7 @@ ipod_write_artwork_db (Itdb_iTunesDB *db) */ return -1; } - buf = ipod_buffer_new (filename); + buf = ipod_buffer_new (filename, db->device->byte_order); if (buf == NULL) { g_print ("Couldn't create %s\n", filename); g_free (filename); diff --git a/src/db-image-parser.c b/src/db-image-parser.c index 296d82c..0ae79ae 100644 --- a/src/db-image-parser.c +++ b/src/db-image-parser.c @@ -30,12 +30,13 @@ #include <glib-object.h> #include "itdb_device.h" +#include "itdb_endianness.h" #include "db-artwork-parser.h" #include "db-image-parser.h" #include <glib/gi18n-lib.h> static int -image_type_from_corr_id (Itdb_Device *device, int corr_id) +image_type_from_corr_id (Itdb_Device *device, gint16 corr_id) { const Itdb_ArtworkFormat *formats; @@ -88,21 +89,24 @@ itdb_get_artwork_info_from_type (Itdb_Device *device, int image_type) G_GNUC_INTERNAL Itdb_Thumb * ipod_image_new_from_mhni (MhniHeader *mhni, Itdb_iTunesDB *db) { - Itdb_Thumb *img; + gint16 corr_id; + img = g_new0 (Itdb_Thumb, 1); if (img == NULL) { return NULL; } - img->size = GUINT32_FROM_LE (mhni->image_size); - img->offset = GUINT32_FROM_LE (mhni->ithmb_offset); - img->width = GINT16_FROM_LE (mhni->image_width); - img->height = GINT16_FROM_LE (mhni->image_height); + img->size = get_guint32_db (db, mhni->image_size); + img->offset = get_guint32_db (db, mhni->ithmb_offset); + img->width = get_gint16_db (db, mhni->image_width); + img->height = get_gint16_db (db, mhni->image_height); - img->type = image_type_from_corr_id (db->device, mhni->correlation_id); + corr_id = get_gint32_db (db, mhni->correlation_id); + img->type = image_type_from_corr_id (db->device, corr_id); if ((img->type != IPOD_COVER_SMALL) && (img->type != IPOD_COVER_LARGE)) { g_warning ("Unexpected cover type in mhni: type %d, size: %ux%u (%d), offset: %d\n", - img->type, img->width, img->height, mhni->correlation_id, img->offset); + img->type, img->width, img->height, + corr_id, img->offset); g_free (img); return NULL; } diff --git a/src/db-itunes-parser.h b/src/db-itunes-parser.h index bdd8498..a126f87 100644 --- a/src/db-itunes-parser.h +++ b/src/db-itunes-parser.h @@ -49,13 +49,15 @@ typedef struct _MhlHeader MhlHeader; typedef struct _MhbdHeader MhbdHeader; -typedef struct _MhsdHeader MhsdHeader; +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 _MhodHeader MhodHeader; +typedef struct _ArtworkDB_MhodHeader ArtworkDB_MhodHeader; +/*typedef struct _MhodHeader MhodHeader;*/ typedef struct _MhfdHeader MhfdHeader; typedef struct _MhliHeader MhliHeader; typedef struct _MhiiHeader MhiiHeader; @@ -68,9 +70,10 @@ typedef struct _MhiaHeader MhiaHeader; typedef struct _MhitHeader471 MhitHeader471; /* MHOD typedef mess */ +typedef struct _ArtworkDB_MhodHeaderArtworkType3 ArtworkDB_MhodHeaderArtworkType3; typedef struct _MhodHeaderString MhodHeaderString; typedef struct _MhodHeaderArtworkType1 MhodHeaderArtworkType1; -typedef struct _MhodHeaderArtworkType3 MhodHeaderArtworkType3; +/* typedef struct _MhodHeaderArtworkType3 MhodHeaderArtworkType3; */ typedef struct _MhodHeaderSmartPlaylistData MhodHeaderSmartPlaylistData; typedef struct _MhodHeaderSmartPlaylistRuleString MhodHeaderSmartPlaylistRuleString; typedef struct _MhodHeaderSmartPlaylistRuleNonString MhodHeaderSmartPlaylistRuleNonString; @@ -99,14 +102,27 @@ enum MhsdPhotoIndexType { MHSD_FILE_LIST = 3 }; -struct _MhsdHeader { +struct _ArtworkDB_MhsdHeader { unsigned char header_id[4]; gint32 header_len; gint32 total_len; - gint32 index; + /* 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; @@ -305,6 +321,21 @@ struct _MhodHeader { 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; @@ -330,10 +361,12 @@ enum MhodArtworkType { MHOD_ARTWORK_TYPE_IMAGE = 5 /* container: full resolution image (in the Photo Database) */ }; -struct _MhodHeaderArtworkType1 { +struct __MhodHeaderArtworkType1 { unsigned char header_id[4]; gint32 header_len; gint32 total_len; +/* FIXME: mobile phone ArtworkDB are known to have a 2 byte type. The + high byte again seems to indicate the padding */ gint32 type; /* low 3 bytes are type (always 1); high byte is padding length (0-3) */ gint32 unknown1; gint32 unknown2; @@ -356,6 +389,25 @@ struct _MhodHeaderArtworkType3 { gunichar2 string[]; }; +struct _ArtworkDB_MhodHeaderArtworkType3 { + unsigned char header_id[4]; + gint32 header_len; + gint32 total_len; + gint16 type; /* 3 */ + gint8 unknown13; + gint8 padding; + gint32 unknown1; + gint32 unknown2; + gint32 string_len; + gint8 mhod_version; /* 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, @@ -494,7 +546,10 @@ struct _MhfdHeader { gint32 unknown4; gint64 unknown5; gint64 unknown6; - gint32 unknown7; + gint8 unknown_flag1; + gint8 unknown_flag2; + gint8 unknown_flag3; + gint8 unknown_flag4; gint32 unknown8; gint32 unknown9; gint32 unknown10; diff --git a/src/db-parse-context.c b/src/db-parse-context.c index 6cb657d..6268d21 100644 --- a/src/db-parse-context.c +++ b/src/db-parse-context.c @@ -35,9 +35,10 @@ #include "glib-compat.h" #include "db-parse-context.h" #include "db-itunes-parser.h" +#include "itdb_endianness.h" DBParseContext * -db_parse_context_new (const unsigned char *buffer, off_t len) +db_parse_context_new (const unsigned char *buffer, off_t len, guint byte_order) { DBParseContext *result; @@ -49,6 +50,7 @@ db_parse_context_new (const unsigned char *buffer, off_t len) result->buffer = buffer; result->cur_pos = buffer; result->total_len = len; + result->byte_order = byte_order; return result; } @@ -106,7 +108,8 @@ db_parse_context_get_sub_context (DBParseContext *ctx, off_t offset) return NULL; } return db_parse_context_new (&ctx->buffer[offset], - ctx->total_len - offset); + ctx->total_len - offset, + ctx->byte_order); } @@ -127,15 +130,21 @@ void * db_parse_context_get_m_header_internal (DBParseContext *ctx, const char *id, off_t size) { MHeader *h; + char *header_id; if (db_parse_context_get_remaining_length (ctx) < 8) { return NULL; } h = (MHeader *)ctx->cur_pos; - if (strncmp (id, (char *)h->header_id, 4) != 0) { + header_id = g_strndup ((char *)h->header_id, 4); + if (ctx->byte_order == G_BIG_ENDIAN) { + g_strreverse (header_id); + } + if (strncmp (id, header_id, 4) != 0) { return NULL; } + g_free (header_id); /* FIXME: this test sucks for compat: if a field is smaller than * expected, we probably should create a buffer of the appropriate @@ -143,17 +152,18 @@ db_parse_context_get_m_header_internal (DBParseContext *ctx, const char *id, off * that buffer in the rest of the code (maybe it's harmful to have * some fields at 0 in some headers though...) */ - if (GINT_FROM_LE (h->header_len) < size) { + if (get_gint32 (h->header_len, ctx->byte_order) < size) { return NULL; } - db_parse_context_set_header_len (ctx, GINT_FROM_LE (h->header_len)); + db_parse_context_set_header_len (ctx, get_gint32 (h->header_len, + ctx->byte_order)); return h; } DBParseContext * -db_parse_context_new_from_file (const char *filename) +db_parse_context_new_from_file (const char *filename, guint byte_order) { int fd; struct stat stat_buf; @@ -196,7 +206,7 @@ db_parse_context_new_from_file (const char *filename) goto error; } - ctx = db_parse_context_new (buffer, stat_buf.st_size); + ctx = db_parse_context_new (buffer, stat_buf.st_size, byte_order); if (ctx == NULL) { munmap (buffer, stat_buf.st_size); } diff --git a/src/db-parse-context.h b/src/db-parse-context.h index 528856f..8df157e 100644 --- a/src/db-parse-context.h +++ b/src/db-parse-context.h @@ -33,6 +33,7 @@ struct _DBParseContext { const unsigned char *cur_pos; off_t header_len; off_t total_len; + guint byte_order; }; typedef struct _DBParseContext DBParseContext; @@ -40,15 +41,32 @@ typedef struct _DBParseContext DBParseContext; #define db_parse_context_get_m_header(ctx, type, id) (type *)db_parse_context_get_m_header_internal (ctx, id, sizeof (type)) -G_GNUC_INTERNAL DBParseContext *db_parse_context_new (const unsigned char *buffer, off_t len) G_GNUC_INTERNAL; -G_GNUC_INTERNAL void db_parse_context_set_total_len (DBParseContext *ctx, off_t len) G_GNUC_INTERNAL; -G_GNUC_INTERNAL off_t db_parse_context_get_remaining_length (DBParseContext *ctx) G_GNUC_INTERNAL; -G_GNUC_INTERNAL DBParseContext *db_parse_context_get_sub_context (DBParseContext *ctx, - off_t offset) G_GNUC_INTERNAL; -G_GNUC_INTERNAL DBParseContext *db_parse_context_get_next_child (DBParseContext *ctx) G_GNUC_INTERNAL; -G_GNUC_INTERNAL void *db_parse_context_get_m_header_internal (DBParseContext *ctx, const char *id, off_t size) G_GNUC_INTERNAL; +G_GNUC_INTERNAL DBParseContext * +db_parse_context_new (const unsigned char *buffer, + off_t len, guint byte_order); -G_GNUC_INTERNAL DBParseContext *db_parse_context_new_from_file (const char *filename) G_GNUC_INTERNAL; -G_GNUC_INTERNAL void db_parse_context_destroy (DBParseContext *ctx, gboolean unmap); +G_GNUC_INTERNAL void +db_parse_context_set_total_len (DBParseContext *ctx, off_t len); + +G_GNUC_INTERNAL off_t +db_parse_context_get_remaining_length (DBParseContext *ctx) G_GNUC_INTERNAL; + +G_GNUC_INTERNAL DBParseContext * +db_parse_context_get_sub_context (DBParseContext *ctx, off_t offset); + + +G_GNUC_INTERNAL DBParseContext * +db_parse_context_get_next_child (DBParseContext *ctx); + + +G_GNUC_INTERNAL void * +db_parse_context_get_m_header_internal (DBParseContext *ctx, + const char *id, off_t size); + +G_GNUC_INTERNAL DBParseContext * +db_parse_context_new_from_file (const char *filename, guint byte_order); + +G_GNUC_INTERNAL void +db_parse_context_destroy (DBParseContext *ctx, gboolean unmap); #endif @@ -1,4 +1,4 @@ -/* Time-stamp: <2006-03-16 23:50:32 jcs> +/* Time-stamp: <2006-03-23 23:30:34 jcs> | | Copyright (C) 2002-2005 Jorg Schuler <jcsjcs at users sourceforge net> | Part of the gtkpod project. @@ -619,12 +619,13 @@ struct _Itdb_Track 0700 GMT. For podcasts: release date as displayed next to the title in the Podcast playlist */ - guint32 unk144; /* unknown, but MP3 songs appear to be always - 0x0000000c or 0x0100000c (if played one or - more times in iTunes), AAC songs are always - 0x01000033, Audible files are 0x01000029, WAV - files are 0x0. itdb will attempt to set this - value when adding a track. */ + guint16 unk144; /* unknown, but MP3 songs appear to be always + 0x000c, AAC songs are always 0x0033, Audible + files are 0x0029, WAV files are 0x0. itdb + will attempt to set this value when adding a + track. */ + guint16 unk146; /* unknown, but appears to be 1 if played at + least once in iTunes and 0 otherwise. */ guint32 unk148; /* unknown - used for Apple Store DRM songs (always 0x01010100?), zero otherwise */ guint32 unk152; /* unknown */ diff --git a/src/itdb_artwork.c b/src/itdb_artwork.c index 3bc8260..94b08b6 100644 --- a/src/itdb_artwork.c +++ b/src/itdb_artwork.c @@ -31,6 +31,7 @@ #include "itdb_private.h" #include "db-image-parser.h" +#include "itdb_endianness.h" #include <errno.h> #include <stdio.h> #include <string.h> @@ -214,7 +215,7 @@ gchar *itdb_thumb_get_filename (Itdb_Device *device, Itdb_Thumb *thumb) #if HAVE_GDKPIXBUF static guchar * -unpack_RGB_565 (guint16 *pixels, guint bytes_len) +unpack_RGB_565 (guint16 *pixels, guint bytes_len, guint byte_order) { guchar *result; guint i; @@ -226,8 +227,8 @@ unpack_RGB_565 (guint16 *pixels, guint bytes_len) } for (i = 0; i < bytes_len/2; i++) { guint16 cur_pixel; - - cur_pixel = GINT16_FROM_LE (pixels[i]); + /* FIXME: endianness */ + cur_pixel = get_gint16 (pixels[i], byte_order); /* Unpack pixels */ result[3*i] = (cur_pixel & RED_MASK) >> RED_SHIFT; result[3*i+1] = (cur_pixel & GREEN_MASK) >> GREEN_SHIFT; @@ -321,7 +322,7 @@ itdb_thumb_get_rgb_data (Itdb_Device *device, Itdb_Thumb *thumb) return NULL; } - pixels = unpack_RGB_565 (pixels565, thumb->size); + pixels = unpack_RGB_565 (pixels565, thumb->size, device->byte_order); g_free (pixels565); return pixels; diff --git a/src/itdb_device.c b/src/itdb_device.c index c0fe191..91066ee 100644 --- a/src/itdb_device.c +++ b/src/itdb_device.c @@ -1,4 +1,4 @@ -/* Time-stamp: <2006-03-17 00:02:22 jcs> +/* Time-stamp: <2006-03-21 17:22:25 jcs> | | Copyright (C) 2002-2005 Jorg Schuler <jcsjcs at users sourceforge net> | Part of the gtkpod project. @@ -117,6 +117,13 @@ static const Itdb_IpodModel ipod_model_table [] = { /* HP iPods, need contributions for this table */ {"E436", 40 * GB, MODEL_TYPE_REGULAR, FOURTH_GENERATION}, {"S492", 30 * GB, MODEL_TYPE_COLOR, FOURTH_GENERATION}, + + /* No known model number -- create a Device/SysInfo file with + * one entry, e.g.: + ModelNumStr: Mmobile1 + */ + + {"mobile1", -1, MODEL_TYPE_MOBILE_1, MOBILE_GENERATION}, {NULL, 0, 0, 0} }; @@ -139,6 +146,7 @@ static const gchar *ipod_model_name_table [] = { "Nano (Black)", "Video (White)", "Video (Black)", + "Mobile (1)", NULL }; #endif @@ -171,6 +179,12 @@ static const Itdb_ArtworkFormat ipod_video_artwork_info[] = { {-1, -1, -1, -1} }; +static const Itdb_ArtworkFormat ipod_mobile_1_artwork_info[] = { + {IPOD_COVER_SMALL, 50, 50, 2002}, + {IPOD_COVER_LARGE, 150, 150, 2003}, + {-1, -1, -1, -1} +}; + /* This will be indexed using a value from the MODEL_TYPE enum */ static const Itdb_ArtworkFormat *ipod_artwork_info_table[] = { NULL, /* Invalid */ @@ -188,7 +202,8 @@ static const Itdb_ArtworkFormat *ipod_artwork_info_table[] = { ipod_nano_artwork_info, /* Nano (White) */ ipod_nano_artwork_info, /* Nano (Black) */ ipod_video_artwork_info, /* Video (White) */ - ipod_video_artwork_info /* Video (Black) */ + ipod_video_artwork_info, /* Video (Black) */ + ipod_mobile_1_artwork_info /* Mobile (1) */ }; @@ -406,11 +421,8 @@ itdb_device_autodetect_endianess (Itdb_Device *device) { g_return_if_fail (device); - /* endianess_set will be set to FALSE. This field is only set to - TRUE when importing an iTunesDB. */ - device->endianess_set = FALSE; /* default: non-reversed */ - device->endianess_reversed = FALSE; + device->byte_order = G_LITTLE_ENDIAN; if (device->mountpoint) { @@ -422,7 +434,7 @@ itdb_device_autodetect_endianess (Itdb_Device *device) if (strstr (cd_l, "itunes/itunes_control") == (cd_l + strlen (cd_l) - strlen ("itunes/itunes_control"))) { - device->endianess_reversed = TRUE; + device->byte_order = G_BIG_ENDIAN; } g_free (cd_l); g_free (control_dir); diff --git a/src/itdb_device.h b/src/itdb_device.h index 5755d3c..0b1d1ea 100644 --- a/src/itdb_device.h +++ b/src/itdb_device.h @@ -1,4 +1,4 @@ -/* Time-stamp: <2006-03-16 23:02:20 jcs> +/* Time-stamp: <2006-03-21 17:22:34 jcs> | | Copyright (C) 2002-2005 Jorg Schuler <jcsjcs at users sourceforge net> | Part of the gtkpod project. @@ -53,11 +53,17 @@ struct _Itdb_Device { gchar *mountpoint; /* mountpoint of the iPod */ gint musicdirs; /* number of /iPod_Control/Music/F.. dirs */ + guint byte_order; /* G_LITTLE_ENDIAN "regular" endianness + * G_BIG_ENDIAN "reversed" endianness (e.g. mobile + * phone iTunesDBs) + */ +#if 0 gboolean endianess_set; /* the endianess_reversed flag has been detected or set */ gboolean endianess_reversed; /* this iTunesDB has to be written in reversed endian order (e.g. mobile phone iTunesDBs) */ +#endif GHashTable *sysinfo; /* hash with value/key pairs of all entries in Device/SysInfo */ }; @@ -83,7 +89,8 @@ typedef enum { SECOND_GENERATION, THIRD_GENERATION, FOURTH_GENERATION, - FIFTH_GENERATION + FIFTH_GENERATION, + MOBILE_GENERATION } Itdb_Generation; typedef enum { @@ -102,7 +109,8 @@ typedef enum { MODEL_TYPE_NANO_WHITE, MODEL_TYPE_NANO_BLACK, MODEL_TYPE_VIDEO_WHITE, - MODEL_TYPE_VIDEO_BLACK + MODEL_TYPE_VIDEO_BLACK, + MODEL_TYPE_MOBILE_1 } Itdb_ModelType; diff --git a/src/itdb_endianness.h b/src/itdb_endianness.h new file mode 100644 index 0000000..9cbf692 --- /dev/null +++ b/src/itdb_endianness.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2005 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! + * + */ +#ifndef __ITDB_ENDIANNESS_H__ +#define __ITDB_ENDIANNESS_H__ + +#include <glib.h> +#include "itdb.h" +#include "itdb_device.h" + +#define DB_TO_CPU_GET(lower_case_type, upper_case_type) \ + static inline lower_case_type \ + get_##lower_case_type (lower_case_type val, guint byte_order) \ + { \ + if (byte_order == G_BIG_ENDIAN) { \ + return upper_case_type##_FROM_BE (val); \ + } else if (byte_order == G_LITTLE_ENDIAN) { \ + return upper_case_type##_FROM_LE (val); \ + } else { \ + g_assert_not_reached (); \ + } \ + return 0; /* never reached */ \ + } + +#define DB_TO_CPU_GET_DB(lower_case_type, upper_case_type) \ + DB_TO_CPU_GET(lower_case_type, upper_case_type) \ + static inline lower_case_type \ + get_##lower_case_type##_db (Itdb_iTunesDB *db, lower_case_type val) \ + { \ + g_assert (db->device != NULL); \ + return get_##lower_case_type (val, db->device->byte_order); \ +} + + +DB_TO_CPU_GET_DB(guint32, GUINT32) +DB_TO_CPU_GET_DB(gint32, GINT32) +DB_TO_CPU_GET_DB(gint16, GINT16) +DB_TO_CPU_GET_DB(gint64, GINT64) + /*DB_TO_CPU_GET(gint, GINT)*/ +#endif diff --git a/src/itdb_itunesdb.c b/src/itdb_itunesdb.c index 062545b..f72c17d 100644 --- a/src/itdb_itunesdb.c +++ b/src/itdb_itunesdb.c @@ -1,4 +1,4 @@ -/* Time-stamp: <2006-03-18 10:21:27 jcs> +/* Time-stamp: <2006-03-23 23:30:35 jcs> | | Copyright (C) 2002-2005 Jorg Schuler <jcsjcs at users sourceforge net> | Part of the gtkpod project. @@ -2054,7 +2054,8 @@ static glong get_mhit (FImport *fimp, glong mhit_seek) track->unk132 = get32lint (cts, seek+132); track->samplerate2 = get32lfloat (cts, seek+136); track->time_released = get32lint (cts, seek+140); - track->unk144 = get32lint (cts, seek+144); + track->unk144 = get16lint (cts, seek+144); + track->unk146 = get16lint (cts, seek+146); track->unk148 = get32lint (cts, seek+148); track->unk152 = get32lint (cts, seek+152); } @@ -2526,8 +2527,15 @@ static gboolean parse_fimp (FImport *fimp) } /* copy the 'reversed endian flag' */ + if (cts->reversed) { + fimp->itdb->device->byte_order = G_BIG_ENDIAN; + } else { + fimp->itdb->device->byte_order = G_LITTLE_ENDIAN; + } +#if 0 fimp->itdb->device->endianess_set = TRUE; fimp->itdb->device->endianess_reversed = cts->reversed; +#endif parse_tracks (fimp, mhsd_1); if (fimp->error) return FALSE; @@ -3213,7 +3221,8 @@ static void mk_mhit (WContents *cts, Itdb_Track *track) put32lint (cts, track->unk132); put32lfloat (cts, track->samplerate2); put32lint (cts, track->time_released); - put32lint (cts, track->unk144); + put16lint (cts, track->unk144); + put16lint (cts, track->unk146); put32lint (cts, track->unk148); put32lint (cts, track->unk152); /* since iTunesDB version 0x0c */ @@ -4105,7 +4114,7 @@ gboolean itdb_write_file (Itdb_iTunesDB *itdb, const gchar *filename, if (!filename) filename = itdb->filename; /* set endianess flag */ - if (!itdb->device->endianess_set) + if (!itdb->device->byte_order) itdb_device_autodetect_endianess (itdb->device); #if HAVE_GDKPIXBUF @@ -4122,7 +4131,7 @@ gboolean itdb_write_file (Itdb_iTunesDB *itdb, const gchar *filename, fexp->wcontents = wcontents_new (filename); cts = fexp->wcontents; - cts->reversed = itdb->device->endianess_reversed; + cts->reversed = (itdb->device->byte_order == G_BIG_ENDIAN); reassign_ids (fexp); diff --git a/src/itdb_track.c b/src/itdb_track.c index c85e207..9f051a9 100644 --- a/src/itdb_track.c +++ b/src/itdb_track.c @@ -1,4 +1,4 @@ -/* Time-stamp: <2006-03-15 00:11:15 jcs> +/* Time-stamp: <2006-03-23 23:30:34 jcs> | | Copyright (C) 2002-2005 Jorg Schuler <jcsjcs at users sourceforge net> | Part of the gtkpod project. @@ -123,26 +123,26 @@ static void itdb_track_set_defaults (Itdb_Track *tr) { if (haystack (tr->filetype, mp3_desc)) { - tr->unk144 = 0x0000000c; + tr->unk144 = 0x000c; } else if (haystack (tr->filetype, mp4_desc)) { if (haystack (tr->filetype, audible_subdesc)) { - tr->unk144 = 0x01000029; + tr->unk144 = 0x0029; } else { - tr->unk144 = 0x01000033; + tr->unk144 = 0x0033; } } else if (haystack (tr->filetype, wav_desc)) { - tr->unk144 = 0x00; + tr->unk144 = 0x0000; } else { - tr->unk144 = 0x00; /* default value */ + tr->unk144 = 0x0000; /* default value */ } } if (is_video_ipod (tr->itdb->device)) diff --git a/src/ithumb-writer.c b/src/ithumb-writer.c index 957aca8..4cf2523 100644 --- a/src/ithumb-writer.c +++ b/src/ithumb-writer.c @@ -29,6 +29,7 @@ #ifdef HAVE_GDKPIXBUF #include "itdb_private.h" +#include "itdb_endianness.h" #include <errno.h> #include <locale.h> @@ -46,6 +47,7 @@ struct _iThumbWriter { FILE *f; gchar *filename; Itdb_ArtworkFormat *img_info; + guint byte_order; GHashTable *cache; }; typedef struct _iThumbWriter iThumbWriter; @@ -56,7 +58,7 @@ typedef struct _iThumbWriter iThumbWriter; * square */ static guint16 * -pack_RGB_565 (GdkPixbuf *pixbuf, int dst_width, int dst_height) +pack_RGB_565 (GdkPixbuf *pixbuf, int dst_width, int dst_height, guint byte_order) { guchar *pixels; guint16 *result; @@ -93,7 +95,8 @@ pack_RGB_565 (GdkPixbuf *pixbuf, int dst_width, int dst_height) r = (r << RED_SHIFT) & RED_MASK; g = (g << GREEN_SHIFT) & GREEN_MASK; b = (b << BLUE_SHIFT) & BLUE_MASK; - result[h*dst_width + w] = (GINT16_TO_LE (r | g | b)); + result[h*dst_width + w] = get_gint16 (r | g | b, + byte_order); } } return result; @@ -140,6 +143,7 @@ ipod_image_get_ithmb_filename (const char *mount_point, gint correlation_id, gin { filename = g_build_filename (artwork_dir, buf, NULL); } +/* printf ("%s %s\n", buf, filename);*/ g_free (buf); @@ -203,7 +207,8 @@ ithumb_writer_write_thumbnail (iThumbWriter *writer, thumb->filename = g_strdup_printf (":F%04u_1.ithmb", writer->img_info->correlation_id); pixels = pack_RGB_565 (pixbuf, writer->img_info->width, - writer->img_info->height); + writer->img_info->height, + writer->byte_order); g_object_unref (G_OBJECT (pixbuf)); if (pixels == NULL) @@ -244,7 +249,9 @@ write_thumbnail (gpointer _writer, gpointer _artwork) } static iThumbWriter * -ithumb_writer_new (const char *mount_point, const Itdb_ArtworkFormat *info) +ithumb_writer_new (const char *mount_point, + const Itdb_ArtworkFormat *info, + guint byte_order) { char *filename; iThumbWriter *writer; @@ -256,6 +263,8 @@ ithumb_writer_new (const char *mount_point, const Itdb_ArtworkFormat *info) writer->cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + writer->byte_order = byte_order; + filename = ipod_image_get_ithmb_filename (mount_point, info->correlation_id, 1); @@ -586,9 +595,9 @@ itdb_write_ithumb_files (Itdb_iTunesDB *db) GList *it; const gchar *mount_point; const Itdb_ArtworkFormat *format; -/* g_print ("%s\n", G_GNUC_FUNCTION);*/ g_return_val_if_fail (db, -1); + g_return_val_if_fail (db->device, -1); mount_point = itdb_get_mountpoint (db); /* FIXME: support writing to directory rather than writing to @@ -614,7 +623,8 @@ itdb_write_ithumb_files (Itdb_iTunesDB *db) case IPOD_COVER_LARGE: ithmb_rearrange_existing_thumbnails (db, format); - writer = ithumb_writer_new (mount_point, format); + writer = ithumb_writer_new (mount_point, format, + db->device->byte_order); if (writer != NULL) { writers = g_list_prepend (writers, writer); } |