summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorjcsjcs <jcsjcs@f01d2545-417e-4e96-918e-98f8d0dbbcb6>2006-03-23 15:06:32 +0000
committerjcsjcs <jcsjcs@f01d2545-417e-4e96-918e-98f8d0dbbcb6>2006-03-23 15:06:32 +0000
commitaabf1eb86076a811d69ca4d1d84d85491b17e394 (patch)
tree405f62eac144bf39a2acb281f474b0ccf531f22c /src
parent83e5c938530cb4e04356c6d1be9e1da67234d599 (diff)
downloadlibgpod-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.am1
-rw-r--r--src/db-artwork-debug.c6
-rw-r--r--src/db-artwork-parser.c111
-rw-r--r--src/db-artwork-parser.h6
-rw-r--r--src/db-artwork-writer.c201
-rw-r--r--src/db-image-parser.c20
-rw-r--r--src/db-itunes-parser.h69
-rw-r--r--src/db-parse-context.c24
-rw-r--r--src/db-parse-context.h36
-rw-r--r--src/itdb.h15
-rw-r--r--src/itdb_artwork.c9
-rw-r--r--src/itdb_device.c26
-rw-r--r--src/itdb_device.h14
-rw-r--r--src/itdb_endianness.h60
-rw-r--r--src/itdb_itunesdb.c19
-rw-r--r--src/itdb_track.c12
-rw-r--r--src/ithumb-writer.c22
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
diff --git a/src/itdb.h b/src/itdb.h
index 51cea19..74f7d6c 100644
--- a/src/itdb.h
+++ b/src/itdb.h
@@ -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);
}