summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am1
-rw-r--r--src/db-artwork-debug.c40
-rw-r--r--src/db-artwork-debug.h6
-rw-r--r--src/db-artwork-parser.c344
-rw-r--r--src/db-artwork-parser.h11
-rw-r--r--src/db-artwork-writer.c431
-rw-r--r--src/db-image-parser.c23
-rw-r--r--src/db-image-parser.h4
-rw-r--r--src/db-itunes-parser.h48
-rw-r--r--src/db-parse-context.c30
-rw-r--r--src/db-parse-context.h6
-rw-r--r--src/itdb.h106
-rw-r--r--src/itdb_artwork.c18
-rw-r--r--src/itdb_device.c303
-rw-r--r--src/itdb_device.h9
-rw-r--r--src/itdb_endianness.h18
-rw-r--r--src/itdb_itunesdb.c465
-rw-r--r--src/itdb_photoalbum.c375
-rw-r--r--src/itdb_playlist.c4
-rw-r--r--src/itdb_private.h6
-rw-r--r--src/ithumb-writer.c247
21 files changed, 2020 insertions, 475 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index b2c70d4..5d6de47 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -6,6 +6,7 @@ libgpod_la_SOURCES = \
itdb_itunesdb.c \
itdb_playlist.c \
itdb_private.h \
+ itdb_photoalbum.c \
itdb_track.c \
db-artwork-parser.c \
db-artwork-parser.h \
diff --git a/src/db-artwork-debug.c b/src/db-artwork-debug.c
index 5d8d3b8..e632db3 100644
--- a/src/db-artwork-debug.c
+++ b/src/db-artwork-debug.c
@@ -76,7 +76,8 @@ dump_mhod_type_1 (MhodHeaderArtworkType1 *mhod1)
g_print ("MHOD [artwork type 1] (%d):\n", sizeof (MhodHeaderArtworkType1));
g_print ("\tHeader length: %d\n", GINT_FROM_LE (mhod1->header_len));
g_print ("\tTotal length: %d\n", GINT_FROM_LE (mhod1->total_len));
- g_print ("\tType: %08x\n", GINT_FROM_LE (mhod1->type));
+ g_print ("\tPadding: %04x\n", GINT_FROM_LE (mhod1->padding));
+ g_print ("\tType: %04x\n", GINT_FROM_LE (mhod1->type));
g_print ("\tUnknown1: %08x\n", GINT_FROM_LE (mhod1->unknown1));
g_print ("\tUnknown2: %08x\n", GINT_FROM_LE (mhod1->unknown2));
g_print ("\tString length: %u\n", GINT_FROM_LE (mhod1->string_len));
@@ -87,14 +88,15 @@ dump_mhod_type_1 (MhodHeaderArtworkType1 *mhod1)
}
G_GNUC_INTERNAL void
-dump_mhod_type_3 (MhodHeaderArtworkType3 *mhod3)
+dump_mhod_type_3 (ArtworkDB_MhodHeaderArtworkType3 *mhod3)
{
gchar *str;
- g_print ("MHOD [artwork type 3] (%d):\n", sizeof (MhodHeaderArtworkType3));
+ g_print ("MHOD [artwork type 3] (%d):\n", sizeof (ArtworkDB_MhodHeaderArtworkType3));
g_print ("\tHeader length: %d\n", GINT_FROM_LE (mhod3->header_len));
g_print ("\tTotal length: %d\n", GINT_FROM_LE (mhod3->total_len));
- g_print ("\tType: %08x\n", GINT_FROM_LE (mhod3->type));
+ g_print ("\tPadding: %04x\n", GINT_FROM_LE (mhod3->padding));
+ g_print ("\tType: %04x\n", GINT_FROM_LE (mhod3->type));
g_print ("\tUnknown1: %08x\n", GINT_FROM_LE (mhod3->unknown1));
g_print ("\tUnknown2: %08x\n", GINT_FROM_LE (mhod3->unknown2));
g_print ("\tString length: %u\n", GINT_FROM_LE (mhod3->string_len));
@@ -120,14 +122,15 @@ dump_mhni (MhniHeader *mhni)
GINT_FROM_LE (mhni->correlation_id));
g_print ("\tithmb offset: %u bytes\n", GINT_FROM_LE (mhni->ithmb_offset));
g_print ("\tImage size: %u bytes\n", GINT_FROM_LE (mhni->image_size));
- g_print ("\tUnknown3: %08x\n", GINT_FROM_LE (mhni->unknown3));
+ g_print ("\tVertical padding: %d\n", GINT_FROM_LE (mhni->vertical_padding));
+ g_print ("\tHorizontal padding: %d\n", GINT_FROM_LE (mhni->horizontal_padding));
g_print ("\tImage dimensions: %ux%u\n", width, height);
}
G_GNUC_INTERNAL void
-dump_mhod (MhodHeader *mhod)
+dump_mhod (ArtworkDB_MhodHeader *mhod)
{
- g_print ("MHOD (%d):\n", sizeof (MhodHeader));
+ g_print ("MHOD (%d):\n", sizeof (ArtworkDB_MhodHeader));
g_print ("\tHeader length: %d\n", GINT_FROM_LE (mhod->header_len));
g_print ("\tTotal length: %d\n", GINT_FROM_LE (mhod->total_len));
g_print ("\tType: %08x\n", GINT_FROM_LE (mhod->type));
@@ -147,8 +150,8 @@ dump_mhii (MhiiHeader *mhii)
g_print ("\tUnknown4: %08x\n", GINT_FROM_LE (mhii->unknown4));
g_print ("\tUnknown5: %08x\n", GINT_FROM_LE (mhii->unknown5));
g_print ("\tUnknown6: %08x\n", GINT_FROM_LE (mhii->unknown6));
- g_print ("\tUnknown7: %08x\n", GINT_FROM_LE (mhii->unknown7));
- g_print ("\tUnknown8: %08x\n", GINT_FROM_LE (mhii->unknown8));
+ g_print ("\tOrig Date: %08x\n", GINT_FROM_LE (mhii->orig_date));
+ g_print ("\tDigitised Date: %08x\n", GINT_FROM_LE (mhii->digitised_date));
g_print ("\tImage size: %d bytes\n", GINT_FROM_LE (mhii->orig_img_size));
}
@@ -166,9 +169,9 @@ dump_mhl (MhlHeader *mhl, const char *id)
}
G_GNUC_INTERNAL void
-dump_mhsd (MhsdHeader *mhsd)
+dump_mhsd (ArtworkDB_MhsdHeader *mhsd)
{
- g_print ("MHSD (%d):\n", sizeof (MhsdHeader));
+ g_print ("MHSD (%d):\n", sizeof (ArtworkDB_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 ", GINT16_FROM_LE (mhsd->index));
@@ -199,10 +202,10 @@ dump_mhfd (MhfdHeader *mhfd)
g_print ("\tUnknown2: %08x\n", GINT_FROM_LE (mhfd->unknown2));
g_print ("\tNumber of children: %d\n", GINT_FROM_LE (mhfd->num_children));
g_print ("\tUnknown3: %08x\n", GINT_FROM_LE (mhfd->unknown3));
- g_print ("\tUnknown4: %08x\n", GINT_FROM_LE (mhfd->unknown4));
+ g_print ("\tNext id: %08x\n", GINT_FROM_LE (mhfd->next_id));
g_print ("\tUnknown5: %016llx\n", GINT64_FROM_LE (mhfd->unknown5));
g_print ("\tUnknown6: %016llx\n", GINT64_FROM_LE (mhfd->unknown6));
- g_print ("\tUnknown7: %08x\n", GINT_FROM_LE (mhfd->unknown7));
+ g_print ("\tunknown_flag1: %04x\n", GINT_FROM_LE (mhfd->unknown_flag1));
g_print ("\tUnknown8: %08x\n", GINT_FROM_LE (mhfd->unknown8));
g_print ("\tUnknown9: %08x\n", GINT_FROM_LE (mhfd->unknown9));
g_print ("\tUnknown10: %08x\n", GINT_FROM_LE (mhfd->unknown10));
@@ -212,8 +215,6 @@ dump_mhfd (MhfdHeader *mhfd)
G_GNUC_INTERNAL void
dump_mhba (MhbaHeader *mhba)
{
- int i;
-
g_print ("MHBA (%d):\n", sizeof (MhbaHeader));
g_print ("\tHeader length: %d\n", GINT_FROM_LE (mhba->header_len));
g_print ("\tTotal length: %d\n", GINT_FROM_LE (mhba->total_len));
@@ -221,9 +222,12 @@ dump_mhba (MhbaHeader *mhba)
g_print ("\tNumber of pictures in the album: %d\n", GINT_FROM_LE (mhba->num_mhias));
g_print ("\tPlaylist ID: %08x\n", GINT_FROM_LE (mhba->playlist_id));
g_print ("\tUnknown2: %08x\n", GINT_FROM_LE (mhba->unknown2));
- g_print ("\tUnknown3: %08x\n", GINT_FROM_LE (mhba->unknown3));
- for (i = 0; i < 7; i++)
- g_print ("\tUnknown[%d]: %08x\n", i, GINT_FROM_LE (mhba->unknown[i]));
+ g_print ("\tUnknown3: %04x\n", GINT_FROM_LE (mhba->unknown3));
+ g_print ("\tMaster playlist: %02x\n", GINT_FROM_LE (mhba->master));
+ g_print ("\tRepeat: %02x\n", GINT_FROM_LE (mhba->repeat));
+ g_print ("\tRandom: %02x\n", GINT_FROM_LE (mhba->random));
+ g_print ("\tTransition direction: %02x\n", GINT_FROM_LE (mhba->transition_direction));
+ g_print ("\tSlide duration: %08x\n", GINT_FROM_LE (mhba->slide_duration));
g_print ("\tPrev playlist ID: %08x\n", GINT_FROM_LE (mhba->prev_playlist_id));
}
diff --git a/src/db-artwork-debug.h b/src/db-artwork-debug.h
index df35058..cd4d4d3 100644
--- a/src/db-artwork-debug.h
+++ b/src/db-artwork-debug.h
@@ -32,12 +32,12 @@
extern G_GNUC_INTERNAL void dump_mhif (MhifHeader *mhif);
extern G_GNUC_INTERNAL void dump_mhia (MhiaHeader *mhia);
extern G_GNUC_INTERNAL void dump_mhod_type_1 (MhodHeaderArtworkType1 *mhod);
-extern G_GNUC_INTERNAL void dump_mhod_type_3 (MhodHeaderArtworkType3 *mhod);
+extern G_GNUC_INTERNAL void dump_mhod_type_3 (ArtworkDB_MhodHeaderArtworkType3 *mhod);
extern G_GNUC_INTERNAL void dump_mhni (MhniHeader *mhni);
-extern G_GNUC_INTERNAL void dump_mhod (MhodHeader *mhod);
+extern G_GNUC_INTERNAL void dump_mhod (ArtworkDB_MhodHeader *mhod);
extern G_GNUC_INTERNAL void dump_mhii (MhiiHeader *mhii);
extern G_GNUC_INTERNAL void dump_mhl (MhlHeader *mhl, const char *id);
-extern G_GNUC_INTERNAL void dump_mhsd (MhsdHeader *mhsd);
+extern G_GNUC_INTERNAL void dump_mhsd (ArtworkDB_MhsdHeader *mhsd);
extern G_GNUC_INTERNAL void dump_mhfd (MhfdHeader *mhfd);
extern G_GNUC_INTERNAL void dump_mhba (MhbaHeader *mhba);
#else
diff --git a/src/db-artwork-parser.c b/src/db-artwork-parser.c
index 17dd390..df80305 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_private.h"
#include "itdb_endianness.h"
#include "db-artwork-debug.h"
#include "db-artwork-parser.h"
@@ -39,9 +40,9 @@
#include "db-parse-context.h"
#include <glib/gi18n-lib.h>
-typedef int (*ParseListItem)(DBParseContext *ctx, Itdb_iTunesDB *db, GError *error);
+typedef int (*ParseListItem)(DBParseContext *ctx, GError *error);
-#ifndef DEBUG_ARTWORKDB
+#ifndef NOT_DEFINED_DEBUG_ARTWORKDB
static Itdb_Track *
get_song_by_dbid (Itdb_iTunesDB *db, guint64 id)
{
@@ -61,7 +62,7 @@ get_song_by_dbid (Itdb_iTunesDB *db, guint64 id)
static int
-parse_mhif (DBParseContext *ctx, Itdb_iTunesDB *db, GError *error)
+parse_mhif (DBParseContext *ctx, GError *error)
{
MhifHeader *mhif;
@@ -70,21 +71,25 @@ parse_mhif (DBParseContext *ctx, Itdb_iTunesDB *db, GError *error)
return -1;
}
dump_mhif (mhif);
- db_parse_context_set_total_len (ctx, get_gint32_db (db, mhif->total_len));
+ db_parse_context_set_total_len (ctx, get_gint32 (mhif->total_len, ctx->byte_order));
return 0;
}
static int
-parse_mhia (DBParseContext *ctx, Itdb_iTunesDB *db, GError *error)
+parse_mhia (DBParseContext *ctx, Itdb_PhotoAlbum *photo_album, GError *error)
{
MhiaHeader *mhia;
+ gint image_id;
mhia = db_parse_context_get_m_header (ctx, MhiaHeader, "mhia");
if (mhia == NULL) {
return -1;
}
dump_mhia (mhia);
- db_parse_context_set_total_len (ctx, get_gint32_db (db, mhia->total_len));
+ image_id = get_gint32 (mhia->image_id, ctx->byte_order);
+ photo_album->members = g_list_append (photo_album->members
+ , GINT_TO_POINTER(image_id));
+ db_parse_context_set_total_len (ctx, get_gint32_db (ctx->db, mhia->total_len));
return 0;
}
@@ -109,22 +114,20 @@ get_utf16_string (void* buffer, gint length, guint byte_order)
}
static char *
-mhod3_get_ithmb_filename (ArtworkDB_MhodHeaderArtworkType3 *mhod3,
- Itdb_iTunesDB *db)
+mhod3_get_ithmb_filename (DBParseContext *ctx, ArtworkDB_MhodHeaderArtworkType3 *mhod3)
{
char *filename=NULL;
g_assert (mhod3 != NULL);
- g_assert (db != NULL);
if (mhod3->mhod_version == 2)
filename = get_utf16_string ((gunichar2 *)mhod3->string,
- get_gint32_db (db, mhod3->string_len),
- db->device->byte_order);
+ get_gint32 (mhod3->string_len, ctx->byte_order),
+ ctx->byte_order);
else if ((mhod3->mhod_version == 0) ||
(mhod3->mhod_version == 1))
filename = g_strndup (mhod3->string,
- get_gint32_db (db, mhod3->string_len));
+ get_gint32 (mhod3->string_len, ctx->byte_order));
else
g_warning (_("Unexpected mhod3 string type: %d\n"),
mhod3->mhod_version);
@@ -133,7 +136,7 @@ mhod3_get_ithmb_filename (ArtworkDB_MhodHeaderArtworkType3 *mhod3,
static int
-parse_mhod_3 (DBParseContext *ctx, Itdb_iTunesDB *db,
+parse_mhod_3 (DBParseContext *ctx,
Itdb_Thumb *thumb, GError *error)
{
ArtworkDB_MhodHeader *mhod;
@@ -144,23 +147,23 @@ parse_mhod_3 (DBParseContext *ctx, Itdb_iTunesDB *db,
if (mhod == NULL) {
return -1;
}
- db_parse_context_set_total_len (ctx, get_gint32_db (db, mhod->total_len));
+ db_parse_context_set_total_len (ctx, get_gint32 (mhod->total_len, ctx->byte_order));
- if (get_gint32_db (db, mhod->total_len) < sizeof (ArtworkDB_MhodHeaderArtworkType3)){
+ if (get_gint32 (mhod->total_len, ctx->byte_order) < sizeof (ArtworkDB_MhodHeaderArtworkType3)){
return -1;
}
mhod3 = (ArtworkDB_MhodHeaderArtworkType3*)mhod;
- mhod3_type = get_gint16_db (db, mhod3->type);
+ mhod3_type = get_gint16 (mhod3->type, ctx->byte_order);
if (mhod3_type != MHOD_ARTWORK_TYPE_FILE_NAME) {
return -1;
}
- thumb->filename = mhod3_get_ithmb_filename (mhod3, db);
+ thumb->filename = mhod3_get_ithmb_filename (ctx, mhod3);
dump_mhod_type_3 (mhod3);
return 0;
}
static int
-parse_mhni (DBParseContext *ctx, iPodSong *song, GError *error)
+parse_photo_mhni (DBParseContext *ctx, Itdb_Artwork *artwork, GError *error)
{
MhniHeader *mhni;
DBParseContext *mhod_ctx;
@@ -170,10 +173,40 @@ parse_mhni (DBParseContext *ctx, iPodSong *song, GError *error)
if (mhni == NULL) {
return -1;
}
- db_parse_context_set_total_len (ctx, get_gint32_db (song->itdb, mhni->total_len));
+ db_parse_context_set_total_len (ctx, get_gint32 (mhni->total_len, ctx->byte_order));
dump_mhni (mhni);
- thumb = ipod_image_new_from_mhni (mhni, song->itdb);
+ thumb = ipod_image_new_from_mhni (mhni, ctx->db);
+ if (thumb == NULL) {
+ return 0;
+ }
+
+ artwork->thumbnails = g_list_append (artwork->thumbnails, thumb);
+
+ mhod_ctx = db_parse_context_get_sub_context (ctx, ctx->header_len);
+ if (mhod_ctx == NULL) {
+ return -1;
+ }
+ parse_mhod_3 (mhod_ctx, thumb, error);
+ g_free (mhod_ctx);
+
+ return 0;
+}
+
+static int
+parse_mhni (DBParseContext *ctx, iPodSong *song, GError *error)
+{
+ MhniHeader *mhni;
+ DBParseContext *mhod_ctx;
+ Itdb_Thumb *thumb;
+
+ mhni = db_parse_context_get_m_header (ctx, MhniHeader, "mhni");
+ if (mhni == NULL) {
+ return -1;
+ }
+ db_parse_context_set_total_len (ctx, get_gint32 (mhni->total_len, ctx->byte_order));
+ dump_mhni (mhni);
+ thumb = ipod_image_new_from_mhni (mhni, ctx->db);
if (thumb == NULL) {
return 0;
}
@@ -185,26 +218,24 @@ parse_mhni (DBParseContext *ctx, iPodSong *song, GError *error)
if (mhod_ctx == NULL) {
return -1;
}
- parse_mhod_3 (mhod_ctx, song->itdb, thumb, error);
+ parse_mhod_3 (mhod_ctx, thumb, error);
g_free (mhod_ctx);
return 0;
}
static int
-parse_mhod (DBParseContext *ctx, iPodSong *song, GError *error)
+parse_photo_mhod (DBParseContext *ctx, Itdb_Artwork *artwork, GError *error)
{
ArtworkDB_MhodHeader *mhod;
DBParseContext *mhni_ctx;
int type;
- gint32 total_len;
mhod = db_parse_context_get_m_header (ctx, ArtworkDB_MhodHeader, "mhod");
if (mhod == NULL) {
return -1;
}
- total_len = get_gint32_db (song->itdb, mhod->total_len);
- db_parse_context_set_total_len (ctx, total_len);
+ db_parse_context_set_total_len (ctx, get_gint32 (mhod->total_len, ctx->byte_order));
/* The MHODs found in the ArtworkDB and Photo Database files are
* significantly different than those found in the iTunesDB.
@@ -212,11 +243,48 @@ parse_mhod (DBParseContext *ctx, iPodSong *song, GError *error)
* - low 3 bytes are actual type;
* - high byte is padding length of string (0-3).
*/
- type = get_gint16_db (song->itdb, mhod->type);
- if (type == MHOD_ARTWORK_TYPE_ALBUM_NAME)
+ type = get_gint16 (mhod->type, ctx->byte_order) & 0x00FFFFFF;
+
+ if ( type == MHOD_ARTWORK_TYPE_ALBUM_NAME) {
dump_mhod_type_1 ((MhodHeaderArtworkType1 *)mhod);
- else
+ } else {
dump_mhod (mhod);
+ }
+
+ /* if this is a container... */
+ if (type == MHOD_ARTWORK_TYPE_THUMBNAIL) {
+ mhni_ctx = db_parse_context_get_sub_context (ctx, ctx->header_len);
+ if (mhni_ctx == NULL) {
+ return -1;
+ }
+ parse_photo_mhni (mhni_ctx, artwork, NULL);
+ g_free (mhni_ctx);
+ }
+
+ return 0;
+}
+static int
+parse_mhod (DBParseContext *ctx, iPodSong *song, GError *error)
+{
+ ArtworkDB_MhodHeader *mhod;
+ DBParseContext *mhni_ctx;
+ int type;
+ gint32 total_len;
+
+ mhod = db_parse_context_get_m_header (ctx, ArtworkDB_MhodHeader, "mhod");
+ if (mhod == NULL) {
+ return -1;
+ }
+ total_len = get_gint32 (mhod->total_len, ctx->byte_order);
+ db_parse_context_set_total_len (ctx, total_len);
+
+ type = get_gint16 (mhod->type, ctx->byte_order);
+
+ if ( type == MHOD_ARTWORK_TYPE_ALBUM_NAME) {
+ dump_mhod_type_1 ((MhodHeaderArtworkType1 *)mhod);
+ } else {
+ dump_mhod (mhod);
+ }
/* if this is a container... */
if (type == MHOD_ARTWORK_TYPE_THUMBNAIL) {
@@ -233,60 +301,81 @@ parse_mhod (DBParseContext *ctx, iPodSong *song, GError *error)
static int
-parse_mhii (DBParseContext *ctx, Itdb_iTunesDB *db, GError *error)
+parse_mhii (DBParseContext *ctx, GError *error)
{
MhiiHeader *mhii;
DBParseContext *mhod_ctx;
int num_children;
off_t cur_offset;
iPodSong *song;
+ Itdb_Artwork *artwork;
mhii = db_parse_context_get_m_header (ctx, MhiiHeader, "mhii");
if (mhii == NULL) {
return -1;
}
- db_parse_context_set_total_len (ctx, get_gint32_db (db, mhii->total_len));
-
+ db_parse_context_set_total_len (ctx, get_gint32 (mhii->total_len, ctx->byte_order));
dump_mhii (mhii);
-#ifdef DEBUG_ARTWORKDB
- song = NULL;
-#else
- song = get_song_by_dbid (db, get_gint64_db (db, mhii->song_id));
- if (song == NULL) {
- return -1;
- }
-
- 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);
- }
+ switch (ctx->db->db_type) {
+ case DB_TYPE_PHOTO:
+ artwork = g_new0( Itdb_Artwork, 1 );
+ artwork->type = ITDB_PHOTO;
+ artwork->artwork_size = get_gint32 (mhii->orig_img_size, ctx->byte_order);
+ artwork->id = get_gint32 (mhii->image_id, ctx->byte_order);
+ artwork->creation_date = itdb_time_mac_to_host( get_gint32 (mhii->digitised_date, ctx->byte_order) );
- song->artwork->id = get_gint32_db (db, mhii->image_id);
+ cur_offset = ctx->header_len;
+ mhod_ctx = db_parse_context_get_sub_context (ctx, cur_offset);
+ num_children = get_gint32 (mhii->num_children, ctx->byte_order);
+ while ((num_children > 0) && (mhod_ctx != NULL)) {
+ parse_photo_mhod (mhod_ctx, artwork, NULL);
+ num_children--;
+ cur_offset += mhod_ctx->total_len;
+ g_free (mhod_ctx);
+ mhod_ctx = db_parse_context_get_sub_context (ctx, cur_offset);
+ }
+ ctx->db->db.photodb->photos = g_list_append (ctx->db->db.photodb->photos, artwork);
+ break;
+ case DB_TYPE_ITUNES:
+#ifdef NOT_DEFINED_DEBUG_ARTWORKDB
+ song = NULL;
+#else
+ song = get_song_by_dbid (ctx->db->db.itdb, get_gint64 (mhii->song_id, ctx->byte_order));
+ if (song == NULL) {
+ return -1;
+ }
+ song->artwork->artwork_size = get_gint32 (mhii->orig_img_size, ctx->byte_order);
+ 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 = get_gint32 (mhii->image_id, ctx->byte_order);
#endif
- cur_offset = ctx->header_len;
- mhod_ctx = db_parse_context_get_sub_context (ctx, cur_offset);
- num_children = get_gint32_db (db, mhii->num_children);
- while ((num_children > 0) && (mhod_ctx != NULL)) {
- parse_mhod (mhod_ctx, song, NULL);
- num_children--;
- cur_offset += mhod_ctx->total_len;
- g_free (mhod_ctx);
+ cur_offset = ctx->header_len;
mhod_ctx = db_parse_context_get_sub_context (ctx, cur_offset);
+ num_children = get_gint32 (mhii->num_children, ctx->byte_order);
+ while ((num_children > 0) && (mhod_ctx != NULL)) {
+ parse_mhod (mhod_ctx, song, NULL);
+ num_children--;
+ cur_offset += mhod_ctx->total_len;
+ g_free (mhod_ctx);
+ mhod_ctx = db_parse_context_get_sub_context (ctx, cur_offset);
+ }
+ break;
}
-
return 0;
}
-
static int
-parse_mhba (DBParseContext *ctx, Itdb_iTunesDB *db, GError *error)
+parse_mhba (DBParseContext *ctx, GError *error)
{
MhbaHeader *mhba;
+ ArtworkDB_MhodHeader *mhod;
DBParseContext *mhod_ctx;
DBParseContext *mhia_ctx;
+ Itdb_PhotoAlbum *photo_album;
int num_children;
off_t cur_offset;
@@ -294,36 +383,49 @@ parse_mhba (DBParseContext *ctx, Itdb_iTunesDB *db, GError *error)
if (mhba == NULL) {
return -1;
}
- db_parse_context_set_total_len (ctx, get_gint32_db (db, mhba->total_len));
+ db_parse_context_set_total_len (ctx, get_gint32 (mhba->total_len, ctx->byte_order));
dump_mhba (mhba);
+ photo_album = g_new0 (Itdb_PhotoAlbum, 1);
+ photo_album->num_images = get_gint32( mhba->num_mhias, ctx->byte_order);
+ photo_album->album_id = get_gint32( mhba->playlist_id, ctx->byte_order);
+ photo_album->master = get_gint32( mhba->master, ctx->byte_order);
+ photo_album->prev_album_id = get_gint32( mhba->prev_playlist_id, ctx->byte_order);
+
cur_offset = ctx->header_len;
mhod_ctx = db_parse_context_get_sub_context (ctx, cur_offset);
- num_children = get_gint32_db (db, mhba->num_mhods);
+ num_children = get_gint32 (mhba->num_mhods, ctx->byte_order);
while ((num_children > 0) && (mhod_ctx != NULL)) {
- parse_mhod (mhod_ctx, NULL, NULL);
- num_children--;
+ /* FIXME: First mhod is album name, whats the others for? */
+ mhod = db_parse_context_get_m_header (mhod_ctx, ArtworkDB_MhodHeader, "mhod");
+ if (mhod == NULL) {
+ return -1;
+ }
+ db_parse_context_set_total_len (mhod_ctx, get_gint32(mhod->total_len, ctx->byte_order));
+ photo_album->name = g_strdup( (char *)((MhodHeaderArtworkType1*)mhod)->string );
cur_offset += mhod_ctx->total_len;
+ dump_mhod_type_1 ((MhodHeaderArtworkType1*)mhod);
g_free (mhod_ctx);
- mhod_ctx = db_parse_context_get_sub_context (ctx, cur_offset);
+ num_children--;
}
+
mhia_ctx = db_parse_context_get_sub_context (ctx, cur_offset);
- num_children = get_gint32_db (db, mhba->num_mhias);
+ num_children = get_gint32 (mhba->num_mhias, ctx->byte_order);
while ((num_children > 0) && (mhia_ctx != NULL)) {
- parse_mhia (mhia_ctx, db, NULL);
+ parse_mhia (mhia_ctx, photo_album, NULL);
num_children--;
cur_offset += mhia_ctx->total_len;
g_free (mhia_ctx);
mhia_ctx = db_parse_context_get_sub_context (ctx, cur_offset);
}
-
+ ctx->db->db.photodb->photoalbums = g_list_append (ctx->db->db.photodb->photoalbums, photo_album);
return 0;
}
static int
-parse_mhl (DBParseContext *ctx, Itdb_iTunesDB *db, GError *error,
+parse_mhl (DBParseContext *ctx, GError *error,
const char *id, ParseListItem parse_child)
{
MhlHeader *mhl;
@@ -338,7 +440,7 @@ parse_mhl (DBParseContext *ctx, Itdb_iTunesDB *db, GError *error,
dump_mhl (mhl, id);
- num_children = get_gint32_db (db, mhl->num_children);
+ num_children = get_gint32 (mhl->num_children, ctx->byte_order);
if (num_children < 0) {
return -1;
}
@@ -347,7 +449,7 @@ parse_mhl (DBParseContext *ctx, Itdb_iTunesDB *db, GError *error,
mhi_ctx = db_parse_context_get_sub_context (ctx, cur_offset);
while ((num_children > 0) && (mhi_ctx != NULL)) {
if (parse_child != NULL) {
- parse_child (mhi_ctx, db, NULL);
+ parse_child (mhi_ctx, NULL);
}
num_children--;
cur_offset += mhi_ctx->total_len;
@@ -361,7 +463,7 @@ parse_mhl (DBParseContext *ctx, Itdb_iTunesDB *db, GError *error,
static int
-parse_mhsd (DBParseContext *ctx, Itdb_iTunesDB *db, GError **error)
+parse_mhsd (DBParseContext *ctx, GError **error)
{
ArtworkDB_MhsdHeader *mhsd;
@@ -370,33 +472,33 @@ parse_mhsd (DBParseContext *ctx, Itdb_iTunesDB *db, GError **error)
return -1;
}
- db_parse_context_set_total_len (ctx, get_gint32_db (db, mhsd->total_len));
+ db_parse_context_set_total_len (ctx, get_gint32 (mhsd->total_len, ctx->byte_order));
dump_mhsd (mhsd);
- switch (get_gint16_db (db, mhsd->index)) {
+ switch (get_gint16_db (ctx->db, mhsd->index)) {
case MHSD_IMAGE_LIST: {
DBParseContext *mhli_context;
mhli_context = db_parse_context_get_next_child (ctx);
- parse_mhl (mhli_context, db, NULL, "mhli", parse_mhii);
+ parse_mhl (mhli_context, NULL, "mhli", parse_mhii);
g_free (mhli_context);
break;
}
case MHSD_ALBUM_LIST: {
DBParseContext *mhla_context;
mhla_context = db_parse_context_get_next_child (ctx);
- parse_mhl (mhla_context, db, NULL, "mhla", parse_mhba);
+ parse_mhl (mhla_context, NULL, "mhla", parse_mhba);
g_free (mhla_context);
break;
}
case MHSD_FILE_LIST: {
DBParseContext *mhlf_context;
mhlf_context = db_parse_context_get_next_child (ctx);
- parse_mhl (mhlf_context, db, NULL, "mhlf", parse_mhif);
+ parse_mhl (mhlf_context, NULL, "mhlf", parse_mhif);
g_free (mhlf_context);
break;
}
default:
g_warning (_("Unexpected mhsd index: %d\n"),
- get_gint16_db (db, mhsd->index));
+ get_gint16_db (ctx->db, mhsd->index));
return -1;
break;
}
@@ -406,7 +508,7 @@ parse_mhsd (DBParseContext *ctx, Itdb_iTunesDB *db, GError **error)
/* Database Object */
static int
-parse_mhfd (DBParseContext *ctx, Itdb_iTunesDB *db, GError **error)
+parse_mhfd (DBParseContext *ctx, GError **error)
{
MhfdHeader *mhfd;
DBParseContext *mhsd_context;
@@ -419,7 +521,7 @@ parse_mhfd (DBParseContext *ctx, Itdb_iTunesDB *db, GError **error)
}
/* Sanity check */
- total_len = get_gint32_db (db, mhfd->total_len);
+ total_len = get_gint32_db (ctx->db, mhfd->total_len);
g_return_val_if_fail (total_len == ctx->total_len, -1);
dump_mhfd (mhfd);
cur_pos = ctx->header_len;
@@ -432,7 +534,7 @@ parse_mhfd (DBParseContext *ctx, Itdb_iTunesDB *db, GError **error)
if (mhsd_context == NULL) {
return -1;
}
- parse_mhsd (mhsd_context, db, NULL);
+ parse_mhsd (mhsd_context, NULL);
cur_pos += mhsd_context->total_len;
g_free (mhsd_context);
@@ -440,7 +542,7 @@ parse_mhfd (DBParseContext *ctx, Itdb_iTunesDB *db, GError **error)
if (mhsd_context == NULL) {
return -1;
}
- parse_mhsd (mhsd_context, db, NULL);
+ parse_mhsd (mhsd_context, NULL);
cur_pos += mhsd_context->total_len;
g_free (mhsd_context);
@@ -448,7 +550,7 @@ parse_mhfd (DBParseContext *ctx, Itdb_iTunesDB *db, GError **error)
if (mhsd_context == NULL) {
return -1;
}
- parse_mhsd (mhsd_context, db, NULL);
+ parse_mhsd (mhsd_context, NULL);
cur_pos += mhsd_context->total_len;
g_free (mhsd_context);
@@ -476,13 +578,13 @@ ipod_db_get_artwork_db_path (const char *mount_point)
{
/* attempt to create Artwork dir */
gchar *control_dir = itdb_get_control_dir (mount_point);
- gchar *dir;
if (control_dir)
{
- dir = g_build_filename (control_dir, "Artwork", NULL);
+ gchar *dir = g_build_filename (control_dir, "Artwork", NULL);
mkdir (dir, 0777);
- g_free (dir);
g_free (control_dir);
+ g_free (dir);
+ artwork_dir = itdb_get_artwork_dir (mount_point);
}
}
if (artwork_dir)
@@ -496,7 +598,6 @@ ipod_db_get_artwork_db_path (const char *mount_point)
return filename;
}
-
static gboolean
ipod_supports_cover_art (Itdb_Device *device)
{
@@ -523,19 +624,22 @@ ipod_supports_cover_art (Itdb_Device *device)
}
int
-ipod_parse_artwork_db (Itdb_iTunesDB *db)
+ipod_parse_artwork_db (Itdb_iTunesDB *itdb)
{
DBParseContext *ctx;
char *filename;
+ Itdb_DB db;
+
+ db.db.itdb = itdb;
+ db.db_type = DB_TYPE_ITUNES;
- g_return_val_if_fail (db, -1);
- g_return_val_if_fail (db->device, -1);
+ g_return_val_if_fail (itdb, -1);
- if (!ipod_supports_cover_art (db->device)) {
+ if (!ipod_supports_cover_art (db.db.itdb->device)) {
return -1;
}
ctx = NULL;
- filename = ipod_db_get_artwork_db_path (itdb_get_mountpoint (db));
+ filename = ipod_db_get_artwork_db_path (itdb_get_mountpoint (db.db.itdb));
if (filename == NULL) {
goto error;
}
@@ -544,14 +648,13 @@ ipod_parse_artwork_db (Itdb_iTunesDB *db)
goto error;
}
- ctx = db_parse_context_new_from_file (filename,
- db->device->byte_order);
+ ctx = db_parse_context_new_from_file (filename, &db);
g_free (filename);
if (ctx == NULL) {
goto error;
}
- parse_mhfd (ctx, db, NULL);
+ parse_mhfd (ctx, NULL);
db_parse_context_destroy (ctx, TRUE);
return 0;
@@ -562,35 +665,68 @@ ipod_parse_artwork_db (Itdb_iTunesDB *db)
return -1;
}
-#if 0
-static char *
-ipod_db_get_photo_db_path (const char *mount_point)
+
+G_GNUC_INTERNAL char *
+ipod_db_get_photos_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);
-
+ gchar *filename=NULL;
+
+ /* fail silently if no mount point given */
+ if (!mount_point) return NULL;
+
+ filename = itdb_get_photodb_path (mount_point);
+
+ /* itdb_resolve_path() only returns existing paths */
+ if (!filename)
+ {
+ gchar *photos_dir;
+
+ photos_dir = itdb_get_photos_dir (mount_point);
+ if (!photos_dir)
+ {
+ /* attempt to create Photos dir */
+ gchar *dir = g_build_filename (mount_point, "Photos", NULL);
+ mkdir (dir, 0777);
+ g_free (dir);
+ photos_dir = itdb_get_photos_dir (mount_point);
+ }
+ if (photos_dir)
+ {
+ filename = g_build_filename (photos_dir,
+ "Photo Database", NULL);
+ g_free (photos_dir);
+ }
+ }
+
+ return filename;
}
+
int
-ipod_parse_photo_db (const char *mount_point)
+ipod_parse_photo_db (Itdb_PhotoDB *photodb)
{
DBParseContext *ctx;
char *filename;
+ Itdb_DB db;
+
+ db.db.photodb = photodb;
+ db.db_type = DB_TYPE_PHOTO;
- filename = ipod_db_get_photo_db_path (mount_point);
+
+ filename = itdb_get_photodb_path (
+ itdb_photodb_get_mountpoint (photodb));
if (filename == NULL) {
return -1;
}
- ctx = db_parse_context_new_from_file (filename);
+
+ ctx = db_parse_context_new_from_file (filename, &db );
g_free (filename);
if (ctx == NULL) {
return -1;
}
-
- parse_mhfd (ctx, NULL, NULL);
+ parse_mhfd (ctx, NULL);
db_parse_context_destroy (ctx, TRUE);
return 0;
}
-#endif
+
diff --git a/src/db-artwork-parser.h b/src/db-artwork-parser.h
index c97ee17..eb84e8d 100644
--- a/src/db-artwork-parser.h
+++ b/src/db-artwork-parser.h
@@ -30,11 +30,10 @@
#define iPodSong Itdb_Track
-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);
-
-#if 0
-G_GNUC_INTERNAL int ipod_parse_photo_db (const char *filename);
-#endif
+G_GNUC_INTERNAL int ipod_write_artwork_db (Itdb_iTunesDB *itdb);
+G_GNUC_INTERNAL char *ipod_db_get_artwork_db_path (const char *mount_point);
+G_GNUC_INTERNAL char *ipod_db_get_photos_db_path (const char *mount_point);
+G_GNUC_INTERNAL int ipod_parse_photo_db (Itdb_PhotoDB *photodb);
+G_GNUC_INTERNAL int ipod_write_photo_db (Itdb_PhotoDB *db);
#endif
diff --git a/src/db-artwork-writer.c b/src/db-artwork-writer.c
index 2b8d91b..079644c 100644
--- a/src/db-artwork-writer.c
+++ b/src/db-artwork-writer.c
@@ -24,6 +24,7 @@
#include <config.h>
#include "itdb.h"
+#include "itdb_private.h"
#include "db-artwork-parser.h"
#if HAVE_GDKPIXBUF
@@ -59,6 +60,7 @@ struct _iPodBuffer {
struct iPodMmapBuffer *mmap;
off_t offset;
guint byte_order;
+ DbType db_type;
};
typedef struct _iPodBuffer iPodBuffer;
@@ -175,6 +177,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;
+ sub_buffer->db_type = buffer->db_type;
buffer->mmap->ref_count++;
@@ -182,7 +185,7 @@ ipod_buffer_get_sub_buffer (iPodBuffer *buffer, off_t offset)
}
static iPodBuffer *
-ipod_buffer_new (const char *filename, guint byte_order)
+ipod_buffer_new (const char *filename, guint byte_order, DbType db_type)
{
int fd;
struct iPodMmapBuffer *mmap_buf;
@@ -228,6 +231,7 @@ ipod_buffer_new (const char *filename, guint byte_order)
}
buffer->mmap = mmap_buf;
buffer->byte_order = byte_order;
+ buffer->db_type = db_type;
return buffer;
}
@@ -239,8 +243,10 @@ enum MhsdType {
};
enum iPodThumbnailType {
- IPOD_THUMBNAIL_FULL_SIZE,
- IPOD_THUMBNAIL_NOW_PLAYING
+ IPOD_THUMBNAIL_FULL_SIZE = 0,
+ IPOD_THUMBNAIL_NOW_PLAYING = 1,
+ IPOD_PHOTO_LITTLE = 3,
+ IPOD_PHOTO_FULL_SIZE = 4
};
@@ -262,6 +268,7 @@ get_padded_header_size (gchar header_id[4])
RETURN_SIZE_FOR ("mhla", 0x5c);
RETURN_SIZE_FOR ("mhlf", 0x5c);
RETURN_SIZE_FOR ("mhif", 0x7c);
+ RETURN_SIZE_FOR ("mhba", 0x94);
return 0;
}
@@ -297,15 +304,57 @@ init_header (iPodBuffer *buffer, gchar _header_id[4], guint header_len)
static int
-write_mhod_type_3 (Itdb_Thumb *thumb, iPodBuffer *buffer)
+write_mhod_type_1 (gchar *string, iPodBuffer *buffer)
+{
+ MhodHeaderArtworkType1 *mhod;
+ unsigned int total_bytes;
+ int len;
+ int padding;
+
+ g_assert (string != NULL);
+
+ mhod = (MhodHeaderArtworkType1 *)init_header (buffer, "mhod",
+ sizeof (MhodHeaderArtworkType1));
+ if (mhod == NULL) {
+ return -1;
+ }
+ total_bytes = sizeof (MhodHeaderArtworkType1);
+ 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 = get_gint32 (sizeof (ArtworkDB_MhodHeader), buffer->byte_order);
+ mhod->unknown3 = get_gint32 (0x01, buffer->byte_order);
+ len = strlen (string);
+ mhod->string_len = get_gint32 (len, buffer->byte_order);
+
+ padding = 4 - ( (total_bytes + len) % 4 );
+ mhod->padding = padding;
+ mhod->type = get_gint32 (0x0001, buffer->byte_order);
+
+ /* Make sure we have enough free space to write the string */
+ if (ipod_buffer_maybe_grow (buffer, total_bytes + len + padding ) != 0) {
+ return -1;
+ }
+ memcpy (mhod->string, string, len);
+ total_bytes += len + padding;
+ mhod->total_len = get_gint32 (total_bytes, buffer->byte_order);
+
+ dump_mhod_type_1 (mhod);
+
+ return total_bytes;
+}
+
+static int
+write_mhod_type_3 (gchar *string, iPodBuffer *buffer)
{
ArtworkDB_MhodHeaderArtworkType3 *mhod;
unsigned int total_bytes;
int len;
gunichar2 *utf16, *strp;
- int i, pad;
+ int i, padding;
- g_assert (thumb->filename != NULL);
+ g_assert (string != NULL);
mhod = (ArtworkDB_MhodHeaderArtworkType3 *)
init_header (buffer, "mhod",
@@ -322,26 +371,27 @@ write_mhod_type_3 (Itdb_Thumb *thumb, iPodBuffer *buffer)
buffer->byte_order);
mhod->type = get_gint16 (3, buffer->byte_order);
- len = strlen (thumb->filename);
-
- /* Make sure we have enough free space to write the string */
- if (ipod_buffer_maybe_grow (buffer, total_bytes + 2*len+2) != 0) {
- return -1;
- }
+ len = strlen (string);
+ /* FIXME: Tidy this up, combine cases more */
/* 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);
+ padding = 4 - ( (total_bytes + 2*len) % 4 );
+ mhod->padding = padding; /* high byte is padding length (0-3) */
- utf16 = g_utf8_to_utf16 (thumb->filename, -1, NULL, NULL, NULL);
+ /* Make sure we have enough free space to write the string */
+ if (ipod_buffer_maybe_grow (buffer, total_bytes + 2*len+padding) != 0) {
+ return -1;
+ }
+
+ utf16 = g_utf8_to_utf16 (string, -1, NULL, NULL, NULL);
if (utf16 == NULL) {
return -1;
}
@@ -351,25 +401,23 @@ write_mhod_type_3 (Itdb_Thumb *thumb, iPodBuffer *buffer)
for (i = 0; i < len; i++) {
strp[i] = get_gint16 (strp[i], buffer->byte_order);
}
- total_bytes += 2*len;
+ total_bytes += 2*len+padding;
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;
+ padding = 4 - ( (total_bytes + len) % 4 );
+ mhod->padding = padding; /* high byte is padding length (0-3) */
+ /* Make sure we have enough free space to write the string */
+ if (ipod_buffer_maybe_grow (buffer, total_bytes + 2*len+padding) != 0) {
+ return -1;
}
- mhod->padding = pad;
- total_bytes += (len+pad);
+ memcpy (mhod->string, string, len);
+ total_bytes += (len+padding);
}
-
mhod->total_len = get_gint32 (total_bytes, buffer->byte_order);
dump_mhod_type_3 (mhod);
@@ -378,12 +426,13 @@ write_mhod_type_3 (Itdb_Thumb *thumb, iPodBuffer *buffer)
}
static int
-write_mhni (Itdb_Thumb *thumb, int correlation_id, iPodBuffer *buffer)
+write_mhni (Itdb_DB *db, Itdb_Thumb *thumb, int correlation_id, iPodBuffer *buffer)
{
MhniHeader *mhni;
unsigned int total_bytes;
int bytes_written;
iPodBuffer *sub_buffer;
+ const Itdb_ArtworkFormat *format;
if (thumb == NULL) {
return -1;
@@ -397,17 +446,28 @@ write_mhni (Itdb_Thumb *thumb, int correlation_id, iPodBuffer *buffer)
total_bytes = get_gint32 (mhni->header_len, buffer->byte_order);
mhni->total_len = get_gint32 (total_bytes, buffer->byte_order);
- 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);
+ 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);
+
+ /* Work out the image padding */
+ format = itdb_device_get_artwork_formats (db->db.photodb->device);
+ while( format->type != thumb->type && format->type != -1 )
+ format++;
+ mhni->vertical_padding = get_gint16 (
+ (format->height - thumb->height)
+ , buffer->byte_order);
+ mhni->horizontal_padding = get_gint16 (
+ (format->width - thumb->width)
+ , buffer->byte_order);
sub_buffer = ipod_buffer_get_sub_buffer (buffer, total_bytes);
if (sub_buffer == NULL) {
return -1;
}
- bytes_written = write_mhod_type_3 (thumb, sub_buffer);
+ bytes_written = write_mhod_type_3 (thumb->filename, sub_buffer);
ipod_buffer_destroy (sub_buffer);
if (bytes_written == -1) {
return -1;
@@ -425,7 +485,7 @@ write_mhni (Itdb_Thumb *thumb, int correlation_id, iPodBuffer *buffer)
}
static int
-write_mhod (Itdb_Thumb *thumb, int correlation_id, iPodBuffer *buffer)
+write_mhod (Itdb_DB *db, Itdb_Thumb *thumb, int correlation_id, iPodBuffer *buffer)
{
ArtworkDB_MhodHeader *mhod;
unsigned int total_bytes;
@@ -449,7 +509,7 @@ write_mhod (Itdb_Thumb *thumb, int correlation_id, iPodBuffer *buffer)
if (sub_buffer == NULL) {
return -1;
}
- bytes_written = write_mhni (thumb, correlation_id, sub_buffer);
+ bytes_written = write_mhni (db, thumb, correlation_id, sub_buffer);
ipod_buffer_destroy (sub_buffer);
if (bytes_written == -1) {
return -1;
@@ -463,25 +523,44 @@ write_mhod (Itdb_Thumb *thumb, int correlation_id, iPodBuffer *buffer)
}
static int
-write_mhii (Itdb_Track *song, iPodBuffer *buffer)
+write_mhii (Itdb_DB *db, void *data, iPodBuffer *buffer)
{
MhiiHeader *mhii;
unsigned int total_bytes;
int bytes_written;
int num_children;
- GList *it;
+ GList *it = NULL;
+ Itdb_Track *song;
+ Itdb_Artwork *artwork;
mhii = (MhiiHeader *)init_header (buffer, "mhii", sizeof (MhiiHeader));
if (mhii == NULL) {
return -1;
}
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);
+
+ switch( buffer->db_type) {
+ case DB_TYPE_ITUNES:
+ song = (Itdb_Track *)data;
+ 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);
+ it = song->artwork->thumbnails;
+ break;
+ case DB_TYPE_PHOTO:
+ artwork = (Itdb_Artwork *)data;
+ mhii->song_id = get_gint64 (artwork->id + 2, buffer->byte_order);
+ mhii->image_id = get_guint32 (artwork->id, buffer->byte_order);
+ mhii->orig_date = get_guint32 (itdb_time_host_to_mac( artwork->creation_date )
+ , buffer->byte_order);
+ mhii->digitised_date = get_guint32 (itdb_time_host_to_mac( artwork->creation_date )
+ , buffer->byte_order);
+ it = artwork->thumbnails;
+ break;
+ }
num_children = 0;
- for (it = song->artwork->thumbnails; it != NULL; it = it->next) {
+ while (it != NULL) {
iPodBuffer *sub_buffer;
Itdb_Thumb *thumb;
const Itdb_ArtworkFormat *img_info;
@@ -495,14 +574,11 @@ write_mhii (Itdb_Track *song, iPodBuffer *buffer)
}
thumb = (Itdb_Thumb *)it->data;
img_info = itdb_get_artwork_info_from_type (
- song->itdb->device, thumb->type);
+ db_get_device(db), thumb->type);
if (img_info == NULL) {
return -1;
}
-/* printf("correlation id: %d, type: %d\n", */
-/* img_info->correlation_id, thumb->type); */
-/* printf("title: %s\n", song->title); */
- bytes_written = write_mhod (thumb, img_info->correlation_id,
+ bytes_written = write_mhod (db, thumb, img_info->correlation_id,
sub_buffer);
ipod_buffer_destroy (sub_buffer);
if (bytes_written == -1) {
@@ -510,6 +586,7 @@ write_mhii (Itdb_Track *song, iPodBuffer *buffer)
}
total_bytes += bytes_written;
num_children++;
+ it = it->next;
}
mhii->num_children = get_gint32 (num_children, buffer->byte_order);
@@ -521,9 +598,9 @@ write_mhii (Itdb_Track *song, iPodBuffer *buffer)
}
static int
-write_mhli (Itdb_iTunesDB *db, iPodBuffer *buffer)
+write_mhli (Itdb_DB *db, iPodBuffer *buffer )
{
- GList *it;
+ GList *it = NULL;
MhliHeader *mhli;
unsigned int total_bytes;
int num_thumbs;
@@ -535,53 +612,155 @@ write_mhli (Itdb_iTunesDB *db, iPodBuffer *buffer)
num_thumbs = 0;
total_bytes = get_gint32 (mhli->header_len, buffer->byte_order);
- for (it = db->tracks; it != NULL; it = it->next) {
+ switch (buffer->db_type) {
+ case DB_TYPE_PHOTO:
+ it = db->db.photodb->photos;
+ break;
+ case DB_TYPE_ITUNES:
+ it = db->db.itdb->tracks;
+ break;
+ }
+ while (it != NULL) {
Itdb_Track *song;
int bytes_written;
iPodBuffer *sub_buffer;
- song = (Itdb_Track*)it->data;
- if (song->artwork->id == 0) {
- continue;
+ if (buffer->db_type == DB_TYPE_ITUNES) {
+ song = (Itdb_Track*)it->data;
+ if (song->artwork->id == 0) {
+ it = it->next;
+ continue;
+ }
}
sub_buffer = ipod_buffer_get_sub_buffer (buffer, total_bytes);
if (sub_buffer == NULL) {
- continue;
+ break;
}
- bytes_written = write_mhii (song, sub_buffer);
+ bytes_written = write_mhii (db, it->data, sub_buffer);
ipod_buffer_destroy (sub_buffer);
if (bytes_written != -1) {
num_thumbs++;
total_bytes += bytes_written;
- }
+ }
+ it = it->next;
}
-
mhli->num_children = get_gint32 (num_thumbs, buffer->byte_order);
-
dump_mhl ((MhlHeader *)mhli, "mhli");
return total_bytes;
}
static int
-write_mhla (Itdb_iTunesDB *db, iPodBuffer *buffer)
+write_mhia (gint image_id, iPodBuffer *buffer)
{
+ MhiaHeader *mhia;
+ unsigned int total_bytes;
+
+
+ mhia = (MhiaHeader *)init_header (buffer, "mhia", 40);
+ if (mhia == NULL) {
+ return -1;
+ }
+
+ mhia->total_len = mhia->header_len;
+ mhia->image_id = get_gint32 (image_id, buffer->byte_order);
+ total_bytes = get_gint32 (mhia->header_len, buffer->byte_order);
+ dump_mhia( mhia );
+ return total_bytes;
+}
+
+static int
+write_mhba (Itdb_PhotoAlbum *photo_album, iPodBuffer *buffer)
+{
+ GList *it;
+ MhbaHeader *mhba;
+ iPodBuffer *sub_buffer;
+ unsigned int total_bytes;
+ unsigned int bytes_written;
+
+ mhba = (MhbaHeader *)init_header (buffer, "mhba", sizeof (MhbaHeader));
+ if (mhba == NULL) {
+ return -1;
+ }
+ mhba->num_mhods = get_gint32(1, buffer->byte_order);
+ mhba->playlist_id = get_gint32(photo_album->album_id, buffer->byte_order);
+ mhba->master = get_gint32(photo_album->master, buffer->byte_order);
+ mhba->prev_playlist_id = get_gint32(photo_album->prev_album_id, buffer->byte_order);
+ mhba->num_mhias = get_gint32(photo_album->num_images, buffer->byte_order);
+ total_bytes = get_gint32 (mhba->header_len, buffer->byte_order);
+
+ /* FIXME: Write other mhods */
+ /* Write album title */
+ sub_buffer = ipod_buffer_get_sub_buffer (buffer, total_bytes);
+ if (sub_buffer == NULL) {
+ return -1;
+ }
+ bytes_written = write_mhod_type_1 (photo_album->name, sub_buffer);
+ ipod_buffer_destroy (sub_buffer);
+ if (bytes_written == -1) {
+ return -1;
+ }
+ total_bytes += bytes_written;
+
+ for (it = photo_album->members; it != NULL; it = it->next) {
+ gint image_id = GPOINTER_TO_INT(it->data);
+
+ sub_buffer = ipod_buffer_get_sub_buffer (buffer, total_bytes);
+ if (sub_buffer == NULL) {
+ return -1;
+ }
+ bytes_written = write_mhia (image_id, sub_buffer);
+ ipod_buffer_destroy (sub_buffer);
+ if (bytes_written == -1) {
+ return -1;
+ }
+ total_bytes += bytes_written;
+ }
+ mhba->total_len = get_gint32( total_bytes, buffer->byte_order );
+ dump_mhba ( mhba );
+ return total_bytes;
+}
+
+static int
+write_mhla (Itdb_DB *db, iPodBuffer *buffer)
+{
+ GList *it;
MhlaHeader *mhla;
+ iPodBuffer *sub_buffer;
+ unsigned int total_bytes;
mhla = (MhlaHeader *)init_header (buffer, "mhla", sizeof (MhlaHeader));
if (mhla == NULL) {
return -1;
}
-
- dump_mhl ((MhlHeader *)mhla, "mhla");
+ total_bytes = get_gint32 (mhla->header_len, buffer->byte_order);
+ if (buffer->db_type == DB_TYPE_PHOTO) {
+ unsigned int bytes_written;
- return get_gint32 (mhla->header_len, buffer->byte_order);
-}
+ for (it = db->db.photodb->photoalbums; it != NULL; it = it->next) {
+ Itdb_PhotoAlbum *photo_album = (Itdb_PhotoAlbum *)it->data;
+ sub_buffer = ipod_buffer_get_sub_buffer (buffer, total_bytes);
+ if (sub_buffer == NULL) {
+ return -1;
+ }
+ bytes_written = write_mhba (photo_album, sub_buffer);
+ ipod_buffer_destroy (sub_buffer);
+ if (bytes_written == -1) {
+ return -1;
+ }
+ total_bytes += bytes_written;
+ mhla->num_children++;
+ }
+ }
+ dump_mhl ((MhlHeader *)mhla, "mhla");
+
+ return total_bytes;
+}
static int
-write_mhif (Itdb_iTunesDB *db, iPodBuffer *buffer, enum iPodThumbnailType type)
+write_mhif (Itdb_DB *db, iPodBuffer *buffer, enum iPodThumbnailType type)
{
MhifHeader *mhif;
const Itdb_ArtworkFormat *img_info;
@@ -592,11 +771,10 @@ write_mhif (Itdb_iTunesDB *db, iPodBuffer *buffer, enum iPodThumbnailType type)
}
mhif->total_len = mhif->header_len;
- img_info = itdb_get_artwork_info_from_type (db->device, type);
+ img_info = itdb_get_artwork_info_from_type (db_get_device(db), type);
if (img_info == NULL) {
return -1;
}
-
mhif->correlation_id = get_gint32 (img_info->correlation_id,
buffer->byte_order);
mhif->image_size = get_gint32 (img_info->height * img_info->width * 2,
@@ -607,14 +785,14 @@ write_mhif (Itdb_iTunesDB *db, iPodBuffer *buffer, enum iPodThumbnailType type)
return get_gint32 (mhif->header_len, buffer->byte_order);
}
-
static int
-write_mhlf (Itdb_iTunesDB *db, iPodBuffer *buffer)
+write_mhlf (Itdb_DB *db, iPodBuffer *buffer)
{
MhlfHeader *mhlf;
unsigned int total_bytes;
int bytes_written;
iPodBuffer *sub_buffer;
+ enum iPodThumbnailType thumb_type = IPOD_THUMBNAIL_FULL_SIZE;
mhlf = (MhlfHeader *)init_header (buffer, "mhlf", sizeof (MhlfHeader));
if (mhlf == NULL) {
@@ -627,7 +805,18 @@ write_mhlf (Itdb_iTunesDB *db, iPodBuffer *buffer)
if (sub_buffer == NULL) {
return -1;
}
- bytes_written = write_mhif (db, sub_buffer, IPOD_THUMBNAIL_FULL_SIZE);
+
+ switch (buffer->db_type) {
+ case DB_TYPE_ITUNES:
+ thumb_type = IPOD_THUMBNAIL_FULL_SIZE;
+ break;
+ case DB_TYPE_PHOTO:
+ thumb_type = IPOD_PHOTO_FULL_SIZE;
+ break;
+ }
+ bytes_written = write_mhif (db
+ , sub_buffer
+ , thumb_type);
ipod_buffer_destroy (sub_buffer);
if (bytes_written == -1) {
return -1;
@@ -647,7 +836,18 @@ write_mhlf (Itdb_iTunesDB *db, iPodBuffer *buffer)
if (sub_buffer == NULL) {
return -1;
}
- bytes_written = write_mhif (db, sub_buffer, IPOD_THUMBNAIL_NOW_PLAYING);
+
+ switch (buffer->db_type) {
+ case DB_TYPE_ITUNES:
+ thumb_type = IPOD_THUMBNAIL_NOW_PLAYING;
+ break;
+ case DB_TYPE_PHOTO:
+ thumb_type = IPOD_PHOTO_LITTLE;
+ break;
+ }
+ bytes_written = write_mhif (db
+ , sub_buffer
+ , thumb_type);
ipod_buffer_destroy (sub_buffer);
if (bytes_written == -1) {
return -1;
@@ -670,7 +870,7 @@ write_mhlf (Itdb_iTunesDB *db, iPodBuffer *buffer)
static int
-write_mhsd (Itdb_iTunesDB *db, iPodBuffer *buffer, enum MhsdType type)
+write_mhsd (Itdb_DB *db, iPodBuffer *buffer, enum MhsdType type)
{
ArtworkDB_MhsdHeader *mhsd;
unsigned int total_bytes;
@@ -717,7 +917,7 @@ write_mhsd (Itdb_iTunesDB *db, iPodBuffer *buffer, enum MhsdType type)
}
static int
-write_mhfd (Itdb_iTunesDB *db, iPodBuffer *buffer, int id_max)
+write_mhfd (Itdb_DB *db, iPodBuffer *buffer, int id_max)
{
MhfdHeader *mhfd;
unsigned int total_bytes;
@@ -730,8 +930,15 @@ write_mhfd (Itdb_iTunesDB *db, iPodBuffer *buffer, int id_max)
}
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);
+ switch (buffer->db_type) {
+ case DB_TYPE_PHOTO:
+ mhfd->unknown2 = get_gint32 (2, buffer->byte_order);
+ break;
+ case DB_TYPE_ITUNES:
+ mhfd->unknown2 = get_gint32 (1, buffer->byte_order);
+ break;
+ }
+ mhfd->next_id = get_gint32 (id_max, buffer->byte_order);
mhfd->unknown_flag1 = 2;
for (i = 1 ; i <= 3; i++) {
iPodBuffer *sub_buffer;
@@ -776,22 +983,26 @@ ipod_artwork_db_set_ids (Itdb_iTunesDB *db)
}
int
-ipod_write_artwork_db (Itdb_iTunesDB *db)
+ipod_write_artwork_db (Itdb_iTunesDB *itdb)
{
iPodBuffer *buf;
int bytes_written;
int result;
char *filename;
int id_max;
+ Itdb_DB db;
+
+ db.db_type = DB_TYPE_ITUNES;
+ db.db.itdb = itdb;
/* First, let's write the .ithmb files, this will create the
* various thumbnails as well */
- itdb_write_ithumb_files (db);
+ itdb_write_ithumb_files (&db);
/* Now we can update the ArtworkDB file */
- id_max = ipod_artwork_db_set_ids (db);
+ id_max = ipod_artwork_db_set_ids (itdb);
- filename = ipod_db_get_artwork_db_path (itdb_get_mountpoint (db));
+ filename = ipod_db_get_artwork_db_path (itdb_get_mountpoint (itdb));
if (filename == NULL) {
/* FIXME: the iTunesDB will be inconsistent wrt artwork_count
* it might be better to 0 out this field in all tracks
@@ -799,13 +1010,67 @@ ipod_write_artwork_db (Itdb_iTunesDB *db)
*/
return -1;
}
- buf = ipod_buffer_new (filename, db->device->byte_order);
+ buf = ipod_buffer_new (filename, itdb->device->byte_order, DB_TYPE_ITUNES);
+ if (buf == NULL) {
+ g_print ("Couldn't create %s\n", filename);
+ g_free (filename);
+ return -1;
+ }
+ bytes_written = write_mhfd (&db, buf, id_max);
+
+ /* Refcount of the mmap buffer should drop to 0 and this should
+ * sync buffered data to disk
+ * FIXME: it's probably less error-prone to add a ipod_buffer_mmap_sync
+ * call...
+ */
+ ipod_buffer_destroy (buf);
+
+ if (bytes_written == -1) {
+ g_print ("Failed to save %s\n", filename);
+ g_free (filename);
+ /* FIXME: maybe should unlink the file we may have created */
+ return -1;
+ }
+
+ result = truncate (filename, bytes_written);
+ if (result != 0) {
+ g_print ("Failed to truncate %s: %s\n",
+ filename, strerror (errno));
+ g_free (filename);
+ return -1;
+ }
+ g_free (filename);
+ return 0;
+}
+
+int
+ipod_write_photo_db (Itdb_PhotoDB *photodb)
+{
+ iPodBuffer *buf;
+ int bytes_written;
+ int result;
+ char *filename;
+ int id_max;
+ Itdb_DB db;
+
+ db.db_type = DB_TYPE_PHOTO;
+ db.db.photodb = photodb;
+
+ filename = ipod_db_get_photos_db_path (db_get_mountpoint (&db));
+
+ itdb_write_ithumb_files (&db);
+
+ if (filename == NULL) {
+ return -1;
+ }
+ buf = ipod_buffer_new (filename, photodb->device->byte_order, DB_TYPE_PHOTO);
if (buf == NULL) {
g_print ("Couldn't create %s\n", filename);
g_free (filename);
return -1;
}
- bytes_written = write_mhfd (db, buf, id_max);
+ id_max = itdb_get_free_photo_id( photodb );
+ bytes_written = write_mhfd (&db, buf, id_max);
/* Refcount of the mmap buffer should drop to 0 and this should
* sync buffered data to disk
@@ -833,7 +1098,13 @@ ipod_write_artwork_db (Itdb_iTunesDB *db)
}
#else
int
-ipod_write_artwork_db (Itdb_iTunesDB *db)
+ipod_write_artwork_db (Itdb_iTunesDB *itdb)
+{
+ return -1;
+}
+
+int
+ipod_write_photo_db (Itdb_PhotoDB *db)
{
return -1;
}
diff --git a/src/db-image-parser.c b/src/db-image-parser.c
index 0ae79ae..06f8f1e 100644
--- a/src/db-image-parser.c
+++ b/src/db-image-parser.c
@@ -87,10 +87,11 @@ 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)
+ipod_image_new_from_mhni (MhniHeader *mhni, Itdb_DB *db)
{
Itdb_Thumb *img;
gint16 corr_id;
+ Itdb_Device *device = NULL;
img = g_new0 (Itdb_Thumb, 1);
if (img == NULL) {
@@ -101,9 +102,25 @@ ipod_image_new_from_mhni (MhniHeader *mhni, Itdb_iTunesDB *db)
img->width = get_gint16_db (db, mhni->image_width);
img->height = get_gint16_db (db, mhni->image_height);
+ switch (db->db_type) {
+ case DB_TYPE_ITUNES:
+ device = db->db.itdb->device;
+ break;
+ case DB_TYPE_PHOTO:
+ device = db->db.photodb->device;
+ break;
+ }
+
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)) {
+ img->type = image_type_from_corr_id (device, corr_id);
+
+ if ( img->type != IPOD_COVER_SMALL
+ && img->type != IPOD_COVER_LARGE
+ && img->type != IPOD_PHOTO_SMALL
+ && img->type != IPOD_PHOTO_LARGE
+ && img->type != IPOD_PHOTO_FULL_SCREEN
+ && img->type != IPOD_PHOTO_TV_SCREEN)
+ {
g_warning ("Unexpected cover type in mhni: type %d, size: %ux%u (%d), offset: %d\n",
img->type, img->width, img->height,
corr_id, img->offset);
diff --git a/src/db-image-parser.h b/src/db-image-parser.h
index a8e2fe5..39f5fd4 100644
--- a/src/db-image-parser.h
+++ b/src/db-image-parser.h
@@ -42,9 +42,9 @@
#define BLUE_MASK (((1 << BLUE_BITS)-1) << BLUE_SHIFT)
G_GNUC_INTERNAL Itdb_Thumb *ipod_image_new_from_mhni (MhniHeader *mhni,
- Itdb_iTunesDB *db);
+ Itdb_DB *db);
-G_GNUC_INTERNAL int itdb_write_ithumb_files (Itdb_iTunesDB *db);
+G_GNUC_INTERNAL int itdb_write_ithumb_files (Itdb_DB *db);
G_GNUC_INTERNAL const Itdb_ArtworkFormat *itdb_get_artwork_info_from_type (
Itdb_Device *ipod, int image_type);
diff --git a/src/db-itunes-parser.h b/src/db-itunes-parser.h
index a126f87..344efa4 100644
--- a/src/db-itunes-parser.h
+++ b/src/db-itunes-parser.h
@@ -325,13 +325,13 @@ 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
+ /* 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;
+ gint16 unknown014;
gint32 unknown1;
gint32 unknown2;
};
@@ -361,13 +361,13 @@ 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) */
+ gint16 type;
+ gint8 unknown;
+ gint8 padding;
gint32 unknown1;
gint32 unknown2;
gint32 string_len;
@@ -380,7 +380,8 @@ struct _MhodHeaderArtworkType3 {
unsigned char header_id[4];
gint32 header_len;
gint32 total_len;
- gint32 type; /* 3 */
+ gint16 type; /* 3 */
+ gint16 padding; /* high byte is padding length (0-3) */
gint32 unknown1;
gint32 unknown2;
gint32 string_len;
@@ -543,13 +544,13 @@ struct _MhfdHeader {
gint32 unknown2;
gint32 num_children;
gint32 unknown3;
- gint32 unknown4;
+ gint32 next_id;
gint64 unknown5;
gint64 unknown6;
- gint8 unknown_flag1;
- gint8 unknown_flag2;
- gint8 unknown_flag3;
- gint8 unknown_flag4;
+ gint8 unknown_flag1;
+ gint8 unknown_flag2;
+ gint8 unknown_flag3;
+ gint8 unknown_flag4;
gint32 unknown8;
gint32 unknown9;
gint32 unknown10;
@@ -574,8 +575,8 @@ struct _MhiiHeader {
gint32 unknown4;
gint32 unknown5;
gint32 unknown6;
- gint32 unknown7;
- gint32 unknown8;
+ gint32 orig_date;
+ gint32 digitised_date;
gint32 orig_img_size;
unsigned char padding[];
} __attribute__((__packed__));
@@ -593,7 +594,8 @@ struct _MhniHeader {
gint32 correlation_id;
gint32 ithmb_offset;
gint32 image_size;
- gint32 unknown3;
+ gint16 vertical_padding;
+ gint16 horizontal_padding;
gint16 image_height;
gint16 image_width;
unsigned char padding[];
@@ -614,9 +616,19 @@ struct _MhbaHeader {
gint32 num_mhias; /* number of pictures in the album */
gint32 playlist_id; /* starts out at $64 and increments by 1 */
gint32 unknown2; /* unknown, seems to be always 0 */
- gint32 unknown3; /* unknown, but is 0x10000 for the Photo Library and 0x60000 for normal albums
- * (maybe not a 4 byte field?) */
- gint32 unknown[7]; /* more zeroes */
+ gint16 unknown3; /* unknown, seems to be always 0 */
+ gchar master;
+ /* FIXME: not sure if I have these right; iPod doesn't seem to listen to them */
+ guint8 playmusic;
+ guint8 repeat;
+ guint8 random;
+ guint8 show_titles;
+ guint8 transition_direction;
+ gint32 slide_duration;
+ gint32 transition_duration;
+ gint32 unknown4;
+ gint32 unknown5;
+ gint64 song_id;
gint32 prev_playlist_id; /* the id of the previous playlist */
unsigned char padding[];
};
diff --git a/src/db-parse-context.c b/src/db-parse-context.c
index 6268d21..0adbe30 100644
--- a/src/db-parse-context.c
+++ b/src/db-parse-context.c
@@ -104,12 +104,16 @@ db_parse_context_get_remaining_length (DBParseContext *ctx)
DBParseContext *
db_parse_context_get_sub_context (DBParseContext *ctx, off_t offset)
{
+ DBParseContext *sub_ctx;
+
if (offset >= ctx->total_len) {
return NULL;
}
- return db_parse_context_new (&ctx->buffer[offset],
+ sub_ctx = db_parse_context_new (&ctx->buffer[offset],
ctx->total_len - offset,
ctx->byte_order);
+ sub_ctx->db = ctx->db;
+ return sub_ctx;
}
@@ -163,17 +167,30 @@ db_parse_context_get_m_header_internal (DBParseContext *ctx, const char *id, off
}
DBParseContext *
-db_parse_context_new_from_file (const char *filename, guint byte_order)
+db_parse_context_new_from_file (const char *filename, Itdb_DB *db)
{
int fd;
struct stat stat_buf;
int result;
unsigned char *buffer;
DBParseContext *ctx;
+ Itdb_Device *device;
buffer = NULL;
ctx = NULL;
+ switch (db->db_type) {
+ case DB_TYPE_ITUNES:
+ device = db->db.itdb->device;
+ break;
+ case DB_TYPE_PHOTO:
+ device = db->db.photodb->device;
+ break;
+ default:
+ g_return_val_if_reached (NULL);
+ }
+ g_return_val_if_fail (device, NULL);
+
fd = open (filename, O_RDONLY);
if (fd == -1) {
g_print ("Failed to open %s: %s\n",
@@ -206,10 +223,17 @@ db_parse_context_new_from_file (const char *filename, guint byte_order)
goto error;
}
- ctx = db_parse_context_new (buffer, stat_buf.st_size, byte_order);
+ if (device->byte_order == 0)
+ itdb_device_autodetect_endianess (device);
+
+ ctx = db_parse_context_new (buffer,
+ stat_buf.st_size, device->byte_order);
+
if (ctx == NULL) {
munmap (buffer, stat_buf.st_size);
}
+ ctx->db = db;
+
error:
close (fd);
return ctx;
diff --git a/src/db-parse-context.h b/src/db-parse-context.h
index 8df157e..4e18baa 100644
--- a/src/db-parse-context.h
+++ b/src/db-parse-context.h
@@ -27,13 +27,14 @@
#define DB_PARSE_CONTEXT
#include <sys/types.h>
-
+#include "itdb.h"
struct _DBParseContext {
const unsigned char *buffer;
const unsigned char *cur_pos;
off_t header_len;
off_t total_len;
guint byte_order;
+ Itdb_DB *db;
};
typedef struct _DBParseContext DBParseContext;
@@ -64,7 +65,8 @@ 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);
+db_parse_context_new_from_file (const char *filename, Itdb_DB *db);
+
G_GNUC_INTERNAL void
db_parse_context_destroy (DBParseContext *ctx, gboolean unmap);
diff --git a/src/itdb.h b/src/itdb.h
index dec3296..d0fa65e 100644
--- a/src/itdb.h
+++ b/src/itdb.h
@@ -1,4 +1,4 @@
-/* Time-stamp: <2006-04-04 23:41:58 jcs>
+/* Time-stamp: <2006-05-30 21:59:40 jcs>
|
| Copyright (C) 2002-2005 Jorg Schuler <jcsjcs at users sourceforge net>
| Part of the gtkpod project.
@@ -61,7 +61,10 @@ typedef struct _SPLPref SPLPref;
typedef struct _SPLRule SPLRule;
typedef struct _SPLRules SPLRules;
typedef struct _Itdb_iTunesDB Itdb_iTunesDB;
+typedef struct _Itdb_PhotoDB Itdb_PhotoDB;
+typedef struct _Itdb_DB Itdb_DB;
typedef struct _Itdb_Playlist Itdb_Playlist;
+typedef struct _Itdb_PhotoAlbum Itdb_PhotoAlbum;
typedef struct _Itdb_Track Itdb_Track;
@@ -110,11 +113,25 @@ struct _Itdb_Thumb {
gint16 height;
};
+typedef enum {
+ ITDB_COVERART,
+ ITDB_PHOTO
+} ItdbArtworkType;
+
struct _Itdb_Artwork {
GList *thumbnails; /* list of Itdb_Thumbs */
guint32 artwork_size; /* Size in bytes of the original source image */
- guint id; /* some kind of ID, starting with
+ ItdbArtworkType type; /* Cover art or photo */
+ guint32 id; /* Artwork id used by photoalbums, starts at
* 0x40... libgpod will set this on sync. */
+ gint32 creation_date; /* Date the image was created */
+ /* below is for use by application */
+ guint64 usertype;
+ gpointer userdata;
+ /* function called to duplicate userdata */
+ ItdbUserDataDuplicateFunc userdata_duplicate;
+ /* function called to free userdata */
+ ItdbUserDataDestroyFunc userdata_destroy;
};
@@ -388,6 +405,35 @@ struct _SPLRules
/* one star is how much (track->rating) */
#define ITDB_RATING_STEP 20
+enum _DbType {
+ DB_TYPE_ITUNES,
+ DB_TYPE_PHOTO
+};
+
+typedef enum _DbType DbType;
+
+struct _Itdb_DB{
+ DbType db_type;
+ union {
+ Itdb_PhotoDB *photodb;
+ Itdb_iTunesDB *itdb;
+ } db;
+};
+
+struct _Itdb_PhotoDB
+{
+ GList *photos;
+ GList *photoalbums;
+ Itdb_Device *device;/* iPod device info */
+ /* below is for use by application */
+ guint64 usertype;
+ gpointer userdata;
+ /* function called to duplicate userdata */
+ ItdbUserDataDuplicateFunc userdata_duplicate;
+ /* function called to free userdata */
+ ItdbUserDataDestroyFunc userdata_destroy;
+};
+
struct _Itdb_iTunesDB
{
GList *tracks;
@@ -405,6 +451,22 @@ struct _Itdb_iTunesDB
ItdbUserDataDestroyFunc userdata_destroy;
};
+struct _Itdb_PhotoAlbum
+{
+ gchar *name; /* name of photoalbum in UTF8 */
+ GList *members; /* photos in album (Track *) */
+ gint num_images; /* number of photos in album */
+ gint master; /* 0x01 for master, 0x00 otherwise */
+ gint album_id;
+ gint prev_album_id;
+ /* below is for use by application */
+ guint64 usertype;
+ gpointer userdata;
+ /* function called to duplicate userdata */
+ ItdbUserDataDuplicateFunc userdata_duplicate;
+ /* function called to free userdata */
+ ItdbUserDataDestroyFunc userdata_destroy;
+};
struct _Itdb_Playlist
{
@@ -634,13 +696,14 @@ struct _Itdb_Track
guint8 has_artwork; /* 0x01: artwork is present. 0x02: no artwork is
present for this track (used by the iPod to
decide whether to display Artwork or not) */
- guint8 flag2; /* "Skip when shuffling" when set to 0x01, set
- to 0x00 otherwise. .m4b and .aa files always
- seem to be skipped when shuffling, however */
- guint8 flag3; /* "Remember playback position" when set to
+ guint8 skip_when_shuffling;/* "Skip when shuffling" when set to
0x01, set to 0x00 otherwise. .m4b and .aa
- files always seem to remember the playback
- position, however. */
+ files always seem to be skipped when
+ shuffling, however */
+ guint8 remember_playback_position;/* "Remember playback position"
+ when set to 0x01, set to 0x00 otherwise. .m4b
+ and .aa files always seem to remember the
+ playback position, however. */
guint8 flag4; /* Used for podcasts, 0x00 otherwise. If set to
0x01 the "Now Playing" page will show
Title/Album, when set to 0x00 it will also
@@ -720,7 +783,7 @@ GQuark itdb_file_error_quark (void);
/* functions for reading/writing database, general itdb functions */
Itdb_iTunesDB *itdb_parse (const gchar *mp, GError **error);
Itdb_iTunesDB *itdb_parse_file (const gchar *filename, GError **error);
-gboolean itdb_write (Itdb_iTunesDB *itdb, GError **error);
+gboolean itdb_write (Itdb_iTunesDB *db, GError **error);
gboolean itdb_write_file (Itdb_iTunesDB *itdb, const gchar *filename,
GError **error);
gboolean itdb_shuffle_write (Itdb_iTunesDB *itdb, GError **error);
@@ -751,9 +814,12 @@ gchar *itdb_get_control_dir (const gchar *mountpoint);
gchar *itdb_get_itunes_dir (const gchar *mountpoint);
gchar *itdb_get_music_dir (const gchar *mountpoint);
gchar *itdb_get_artwork_dir (const gchar *mountpoint);
+gchar *itdb_get_photos_dir (const gchar *mountpoint);
+gchar *itdb_get_photos_thumb_dir (const gchar *mountpoint);
gchar *itdb_get_device_dir (const gchar *mountpoint);
gchar *itdb_get_itunesdb_path (const gchar *mountpoint);
gchar *itdb_get_artworkdb_path (const gchar *mountpoint);
+gchar *itdb_get_photodb_path (const gchar *mountpoint);
gchar *itdb_get_path (const gchar *dir, const gchar *file);
/* itdb_device functions */
@@ -824,6 +890,21 @@ void itdb_spl_update_live (Itdb_iTunesDB *itdb);
gboolean itdb_track_set_thumbnails (Itdb_Track *track,
const gchar *filename);
void itdb_track_remove_thumbnails (Itdb_Track *track);
+
+/* photoalbum functions */
+Itdb_PhotoDB *itdb_photodb_parse (const gchar *mp, GError **error);
+gboolean itdb_photodb_add_photo (Itdb_PhotoDB *db,
+ const gchar *albumname,
+ const gchar *filename);
+Itdb_PhotoAlbum *itdb_photodb_photoalbum_new (Itdb_PhotoDB *db,
+ const gchar *album_name);
+Itdb_PhotoDB *itdb_photodb_new (void);
+void itdb_photodb_free (Itdb_PhotoDB *photodb);
+gboolean itdb_photodb_write (Itdb_PhotoDB *db, GError **error);
+void itdb_photodb_photoalbum_free (Itdb_PhotoAlbum *pa);
+gboolean itdb_photodb_remove_photo (Itdb_PhotoDB *db,
+ const gint photo_id );
+
/* itdb_artwork_... */
Itdb_Artwork *itdb_artwork_new (void);
Itdb_Artwork *itdb_artwork_duplicate (Itdb_Artwork *artwork);
@@ -846,12 +927,17 @@ void itdb_thumb_free (Itdb_Thumb *thumb);
Itdb_Thumb *itdb_thumb_new (void);
gchar *itdb_thumb_get_filename (Itdb_Device *device, Itdb_Thumb *thumb);
-
/* time functions */
guint64 itdb_time_get_mac_time (void);
time_t itdb_time_mac_to_host (guint64 mactime);
guint64 itdb_time_host_to_mac (time_t time);
+/* Initialise a blank ipod */
+gboolean itdb_init_ipod (const gchar *mountpoint,
+ const gchar *model_number,
+ const gchar *ipod_name,
+ GError **error);
+
G_END_DECLS
#endif
diff --git a/src/itdb_artwork.c b/src/itdb_artwork.c
index 3c7d9d9..7645e35 100644
--- a/src/itdb_artwork.c
+++ b/src/itdb_artwork.c
@@ -1,4 +1,4 @@
-/* Time-stamp: <2006-03-18 01:23:13 jcs>
+/* Time-stamp: <2006-05-26 20:49:27 jcs>
|
| Copyright (C) 2002-2005 Jorg Schuler <jcsjcs at users sourceforge net>
| Part of the gtkpod project.
@@ -64,6 +64,8 @@ void itdb_artwork_free (Itdb_Artwork *artwork)
{
g_return_if_fail (artwork);
itdb_artwork_remove_thumbnails (artwork);
+ if (artwork->userdata && artwork->userdata_destroy)
+ (*artwork->userdata_destroy) (artwork->userdata);
g_free (artwork);
}
@@ -184,7 +186,8 @@ itdb_artwork_add_thumbnail (Itdb_Artwork *artwork,
return FALSE;
}
- artwork->artwork_size = statbuf.st_size;
+ artwork->artwork_size = statbuf.st_size;
+ artwork->creation_date = statbuf.st_mtime;
thumb = itdb_thumb_new ();
thumb->filename = g_strdup (filename);
@@ -259,14 +262,23 @@ gchar *itdb_thumb_get_filename (Itdb_Device *device, Itdb_Thumb *thumb)
g_print (_("Mountpoint not set.\n"));
return NULL;
}
-
artwork_dir = itdb_get_artwork_dir (device->mountpoint);
if (artwork_dir)
{
filename = itdb_get_path (artwork_dir, thumb->filename+1);
g_free (artwork_dir);
}
+ /* FIXME: Hack */
+ if( !filename ) {
+ artwork_dir = itdb_get_photos_thumb_dir (device->mountpoint);
+ if (artwork_dir)
+ {
+ filename = itdb_get_path (artwork_dir, strchr( thumb->filename+1, ':') + 1);
+ g_free (artwork_dir);
+ }
+
+ }
return filename;
}
diff --git a/src/itdb_device.c b/src/itdb_device.c
index f475be3..dd2e2ad 100644
--- a/src/itdb_device.c
+++ b/src/itdb_device.c
@@ -1,4 +1,4 @@
-/* Time-stamp: <2006-04-05 22:53:35 jcs>
+/* Time-stamp: <2006-05-29 23:55:05 jcs>
|
| Copyright (C) 2002-2005 Jorg Schuler <jcsjcs at users sourceforge net>
| Part of the gtkpod project.
@@ -31,112 +31,116 @@
| $Id$
*/
+#include "itdb_device.h"
+#include <ctype.h>
+#include <fcntl.h>
#include <stdio.h>
#include <string.h>
-#include <ctype.h>
-#include "itdb_device.h"
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
#define GB 1024
static const Itdb_IpodModel ipod_model_table [] = {
- /* Handle idiots who hose their iPod file system, or
- lucky people with iPods we don't yet know about*/
- {"Invalid", 0, MODEL_TYPE_INVALID, UNKNOWN_GENERATION},
- {"Unknown", 0, MODEL_TYPE_UNKNOWN, UNKNOWN_GENERATION},
-
- /* First Generation */
- /* Mechanical buttons arranged around rotating "scroll wheel".
- 8513, 8541 and 8709 are Mac types, 8697 is PC */
- {"8513", 5 * GB, MODEL_TYPE_REGULAR, FIRST_GENERATION},
- {"8541", 5 * GB, MODEL_TYPE_REGULAR, FIRST_GENERATION},
- {"8697", 5 * GB, MODEL_TYPE_REGULAR, FIRST_GENERATION},
- {"8709", 10 * GB, MODEL_TYPE_REGULAR, FIRST_GENERATION},
-
- /* Second Generation */
- /* Same buttons as First Generation but around touch-sensitive
- * "touch wheel". 8737 and 8738 are Mac types, 8740 and 8741
- are PC */
- {"8737", 10 * GB, MODEL_TYPE_REGULAR, SECOND_GENERATION},
- {"8740", 10 * GB, MODEL_TYPE_REGULAR, SECOND_GENERATION},
- {"8738", 20 * GB, MODEL_TYPE_REGULAR, SECOND_GENERATION},
- {"8741", 20 * GB, MODEL_TYPE_REGULAR, SECOND_GENERATION},
-
- /* Third Generation */
- /* Touch sensitive buttons and arranged in a line above "touch
- wheel". Docking connector was introduced here, same models
- for Mac and PC from now on. */
- {"8976", 10 * GB, MODEL_TYPE_REGULAR, THIRD_GENERATION},
- {"8946", 15 * GB, MODEL_TYPE_REGULAR, THIRD_GENERATION},
- {"9460", 15 * GB, MODEL_TYPE_REGULAR, THIRD_GENERATION},
- {"9244", 20 * GB, MODEL_TYPE_REGULAR, THIRD_GENERATION},
- {"8948", 30 * GB, MODEL_TYPE_REGULAR, THIRD_GENERATION},
- {"9245", 40 * GB, MODEL_TYPE_REGULAR, THIRD_GENERATION},
-
- /* Fourth Generation */
- /* Buttons are now integrated into the "touch wheel". */
- {"9282", 20 * GB, MODEL_TYPE_REGULAR, FOURTH_GENERATION},
- {"9787", 25 * GB, MODEL_TYPE_REGULAR_U2, FOURTH_GENERATION},
- {"9268", 40 * GB, MODEL_TYPE_REGULAR, FOURTH_GENERATION},
- {"A079", 20 * GB, MODEL_TYPE_COLOR, FOURTH_GENERATION},
- {"A127", 20 * GB, MODEL_TYPE_COLOR_U2, FOURTH_GENERATION},
- {"9830", 60 * GB, MODEL_TYPE_COLOR, FOURTH_GENERATION},
-
- /* First Generation Mini */
- {"9160", 4 * GB, MODEL_TYPE_MINI, FIRST_GENERATION},
- {"9436", 4 * GB, MODEL_TYPE_MINI_BLUE, FIRST_GENERATION},
- {"9435", 4 * GB, MODEL_TYPE_MINI_PINK, FIRST_GENERATION},
- {"9434", 4 * GB, MODEL_TYPE_MINI_GREEN, FIRST_GENERATION},
- {"9437", 4 * GB, MODEL_TYPE_MINI_GOLD, FIRST_GENERATION},
-
- /* Second Generation Mini */
- {"9800", 4 * GB, MODEL_TYPE_MINI, SECOND_GENERATION},
- {"9802", 4 * GB, MODEL_TYPE_MINI_BLUE, SECOND_GENERATION},
- {"9804", 4 * GB, MODEL_TYPE_MINI_PINK, SECOND_GENERATION},
- {"9806", 4 * GB, MODEL_TYPE_MINI_GREEN, SECOND_GENERATION},
- {"9801", 6 * GB, MODEL_TYPE_MINI, SECOND_GENERATION},
- {"9803", 6 * GB, MODEL_TYPE_MINI_BLUE, SECOND_GENERATION},
- {"9805", 6 * GB, MODEL_TYPE_MINI_PINK, SECOND_GENERATION},
- {"9807", 6 * GB, MODEL_TYPE_MINI_GREEN, SECOND_GENERATION},
-
- /* Photo / Fourth Generation */
- /* Buttons are integrated into the "touch wheel". */
- {"9829", 30 * GB, MODEL_TYPE_COLOR, FOURTH_GENERATION},
- {"9585", 40 * GB, MODEL_TYPE_COLOR, FOURTH_GENERATION},
- {"9586", 60 * GB, MODEL_TYPE_COLOR, FOURTH_GENERATION},
- {"9830", 60 * GB, MODEL_TYPE_COLOR, FOURTH_GENERATION},
-
- /* Shuffle / Fourth Generation */
- {"9724", GB / 2, MODEL_TYPE_SHUFFLE, FOURTH_GENERATION},
- {"9725", GB, MODEL_TYPE_SHUFFLE, FOURTH_GENERATION},
-
- /* Nano / Fifth Generation */
- /* Buttons are integrated into the "touch wheel". */
- {"A350", GB * 1, MODEL_TYPE_NANO_WHITE, FIFTH_GENERATION},
- {"A352", GB * 1, MODEL_TYPE_NANO_BLACK, FIFTH_GENERATION},
- {"A004", GB * 2, MODEL_TYPE_NANO_WHITE, FIFTH_GENERATION},
- {"A099", GB * 2, MODEL_TYPE_NANO_BLACK, FIFTH_GENERATION},
- {"A005", GB * 4, MODEL_TYPE_NANO_WHITE, FIFTH_GENERATION},
- {"A107", GB * 4, MODEL_TYPE_NANO_BLACK, FIFTH_GENERATION},
-
- /* Video / Fifth Generation */
- /* Buttons are integrated into the "touch wheel". */
- {"A002", GB * 30, MODEL_TYPE_VIDEO_WHITE, FIFTH_GENERATION},
- {"A146", GB * 30, MODEL_TYPE_VIDEO_BLACK, FIFTH_GENERATION},
- {"A003", GB * 60, MODEL_TYPE_VIDEO_WHITE, FIFTH_GENERATION},
- {"A147", GB * 60, MODEL_TYPE_VIDEO_BLACK, FIFTH_GENERATION},
-
- /* HP iPods, need contributions for this table */
- /* Buttons are integrated into the "touch wheel". */
- {"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}
+ /* Handle idiots who hose their iPod file system, or lucky people
+ with iPods we don't yet know about*/
+ {"Invalid", 0, MODEL_TYPE_INVALID, UNKNOWN_GENERATION, 0},
+ {"Unknown", 0, MODEL_TYPE_UNKNOWN, UNKNOWN_GENERATION, 0},
+
+ /* First Generation */
+ /* Mechanical buttons arranged around rotating "scroll wheel".
+ 8513, 8541 and 8709 are Mac types, 8697 is PC */
+ {"8513", 5*GB, MODEL_TYPE_REGULAR, FIRST_GENERATION, 20},
+ {"8541", 5*GB, MODEL_TYPE_REGULAR, FIRST_GENERATION, 20},
+ {"8697", 5*GB, MODEL_TYPE_REGULAR, FIRST_GENERATION, 20},
+ {"8709", 10*GB, MODEL_TYPE_REGULAR, FIRST_GENERATION, 20},
+
+ /* Second Generation */
+ /* Same buttons as First Generation but around touch-sensitive
+ "touch wheel". 8737 and 8738 are Mac types, 8740 and 8741 * are
+ PC */
+ {"8737", 10*GB, MODEL_TYPE_REGULAR, SECOND_GENERATION, 20},
+ {"8740", 10*GB, MODEL_TYPE_REGULAR, SECOND_GENERATION, 20},
+ {"8738", 20*GB, MODEL_TYPE_REGULAR, SECOND_GENERATION, 50},
+ {"8741", 20*GB, MODEL_TYPE_REGULAR, SECOND_GENERATION, 50},
+
+ /* Third Generation */
+ /* Touch sensitive buttons and arranged in a line above "touch
+ wheel". Docking connector was introduced here, same models for
+ Mac and PC from now on. */
+ {"8976", 10*GB, MODEL_TYPE_REGULAR, THIRD_GENERATION, 20},
+ {"8946", 15*GB, MODEL_TYPE_REGULAR, THIRD_GENERATION, 50},
+ {"9460", 15*GB, MODEL_TYPE_REGULAR, THIRD_GENERATION, 50},
+ {"9244", 20*GB, MODEL_TYPE_REGULAR, THIRD_GENERATION, 50},
+ {"8948", 30*GB, MODEL_TYPE_REGULAR, THIRD_GENERATION, 50},
+ {"9245", 40*GB, MODEL_TYPE_REGULAR, THIRD_GENERATION, 50},
+
+ /* Fourth Generation */
+ /* Buttons are now integrated into the "touch wheel". */
+ {"9282", 20*GB, MODEL_TYPE_REGULAR, FOURTH_GENERATION, 50},
+ {"9787", 25*GB, MODEL_TYPE_REGULAR_U2, FOURTH_GENERATION, 50},
+ {"9268", 40*GB, MODEL_TYPE_REGULAR, FOURTH_GENERATION, 50},
+ {"A079", 20*GB, MODEL_TYPE_COLOR, FOURTH_GENERATION, 50},
+ {"A127", 20*GB, MODEL_TYPE_COLOR_U2, FOURTH_GENERATION, 50},
+ {"9830", 60*GB, MODEL_TYPE_COLOR, FOURTH_GENERATION, 50},
+
+ /* First Generation Mini */
+ {"9160", 4*GB, MODEL_TYPE_MINI, FIRST_GENERATION, 6},
+ {"9436", 4*GB, MODEL_TYPE_MINI_BLUE, FIRST_GENERATION, 6},
+ {"9435", 4*GB, MODEL_TYPE_MINI_PINK, FIRST_GENERATION, 6},
+ {"9434", 4*GB, MODEL_TYPE_MINI_GREEN, FIRST_GENERATION, 6},
+ {"9437", 4*GB, MODEL_TYPE_MINI_GOLD, FIRST_GENERATION, 6},
+
+ /* Second Generation Mini */
+ {"9800", 4*GB, MODEL_TYPE_MINI, SECOND_GENERATION, 6},
+ {"9802", 4*GB, MODEL_TYPE_MINI_BLUE, SECOND_GENERATION, 6},
+ {"9804", 4*GB, MODEL_TYPE_MINI_PINK, SECOND_GENERATION, 6},
+ {"9806", 4*GB, MODEL_TYPE_MINI_GREEN, SECOND_GENERATION, 6},
+ {"9801", 6*GB, MODEL_TYPE_MINI, SECOND_GENERATION, 20},
+ {"9803", 6*GB, MODEL_TYPE_MINI_BLUE, SECOND_GENERATION, 20},
+ {"9805", 6*GB, MODEL_TYPE_MINI_PINK, SECOND_GENERATION, 20},
+ {"9807", 6*GB, MODEL_TYPE_MINI_GREEN, SECOND_GENERATION, 20},
+
+ /* Photo / Fourth Generation */
+ /* Buttons are integrated into the "touch wheel". */
+ {"9829", 30*GB, MODEL_TYPE_COLOR, FOURTH_GENERATION, 50},
+ {"9585", 40*GB, MODEL_TYPE_COLOR, FOURTH_GENERATION, 50},
+ {"9586", 60*GB, MODEL_TYPE_COLOR, FOURTH_GENERATION, 50},
+ {"9830", 60*GB, MODEL_TYPE_COLOR, FOURTH_GENERATION, 50},
+
+ /* Shuffle / Fourth Generation */
+ {"9724", GB/2, MODEL_TYPE_SHUFFLE, FOURTH_GENERATION, 3},
+ {"9725", GB, MODEL_TYPE_SHUFFLE, FOURTH_GENERATION, 3},
+
+ /* Nano / Fifth Generation */
+ /* Buttons are integrated into the "touch wheel". */
+ {"A350", 1*GB, MODEL_TYPE_NANO_WHITE, FIFTH_GENERATION, 3},
+ {"A352", 1*GB, MODEL_TYPE_NANO_BLACK, FIFTH_GENERATION, 3},
+ {"A004", 2*GB, MODEL_TYPE_NANO_WHITE, FIFTH_GENERATION, 3},
+ {"A099", 2*GB, MODEL_TYPE_NANO_BLACK, FIFTH_GENERATION, 3},
+ {"A005", 4*GB, MODEL_TYPE_NANO_WHITE, FIFTH_GENERATION, 6},
+ {"A107", 4*GB, MODEL_TYPE_NANO_BLACK, FIFTH_GENERATION, 6},
+
+ /* Video / Fifth Generation */
+ /* Buttons are integrated into the "touch wheel". */
+ {"A002", 30*GB, MODEL_TYPE_VIDEO_WHITE, FIFTH_GENERATION, 50},
+ {"A146", 30*GB, MODEL_TYPE_VIDEO_BLACK, FIFTH_GENERATION, 50},
+ {"A003", 60*GB, MODEL_TYPE_VIDEO_WHITE, FIFTH_GENERATION, 50},
+ {"A147", 60*GB, MODEL_TYPE_VIDEO_BLACK, FIFTH_GENERATION, 50},
+
+ /* HP iPods, need contributions for this table */
+ /* Buttons are integrated into the "touch wheel". */
+ {"E436", 40*GB, MODEL_TYPE_REGULAR, FOURTH_GENERATION, 50},
+ {"S492", 30*GB, MODEL_TYPE_COLOR, FOURTH_GENERATION, 50},
+
+ /* 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, 0}
};
#if 0
@@ -450,6 +454,50 @@ itdb_device_musicdirs_number (Itdb_Device *device)
return device->musicdirs;
}
+/**
+ * endianess_check_path:
+ *
+ * Check if endianess can be determined by looking at header of @path.
+ *
+ * @path: the file to look at.
+ * @hdr: the header string (4 bytes) in case of LITTLE_ENDIAN
+ *
+ * Return value:
+ * G_LITTLE_ENDIAN, G_BIG_ENDIAN or 0 if endianess could not be
+ * determined.
+ */
+static guint endianess_check_path (const gchar *path, const gchar *hdr)
+{
+ guint byte_order = 0;
+
+ if (path)
+ {
+ int fd = open (path, O_RDONLY);
+ if (fd != -1)
+ {
+ gchar buf[4];
+ if (read (fd, buf, 4) == 4)
+ {
+ if (strncmp (buf, hdr, 4) == 0)
+ {
+ byte_order = G_LITTLE_ENDIAN;
+ }
+ else
+ {
+ if ((buf[0] == hdr[3]) &&
+ (buf[1] == hdr[2]) &&
+ (buf[2] == hdr[1]) &&
+ (buf[3] == hdr[0]))
+ {
+ byte_order = G_LITTLE_ENDIAN;
+ }
+ }
+ }
+ close (fd);
+ }
+ }
+ return byte_order;
+}
/* Attempt to guess the endianess used by this iPod.
*
@@ -460,25 +508,54 @@ itdb_device_musicdirs_number (Itdb_Device *device)
G_GNUC_INTERNAL void
itdb_device_autodetect_endianess (Itdb_Device *device)
{
- g_return_if_fail (device);
+ guint byte_order = 0;
- /* default: non-reversed */
- device->byte_order = G_LITTLE_ENDIAN;
+ g_return_if_fail (device);
if (device->mountpoint)
{
- gchar *control_dir = itdb_get_control_dir (device->mountpoint);
-
- if (control_dir)
+ gchar *path;
+ if (byte_order == 0)
{
- gchar *cd_l = g_ascii_strdown (control_dir, -1);
- if (strstr (cd_l, "itunes/itunes_control") ==
- (cd_l + strlen (cd_l) - strlen ("itunes/itunes_control")))
+ /* First try reading the iTunesDB */
+ path = itdb_get_itunesdb_path (device->mountpoint);
+ byte_order = endianess_check_path (path, "mhbd");
+ g_free (path);
+ }
+ if (byte_order == 0)
+ {
+ /* Try reading the ArtworkDB */
+ path = itdb_get_artworkdb_path (device->mountpoint);
+ byte_order = endianess_check_path (path, "mhfd");
+ g_free (path);
+ }
+ if (byte_order == 0)
+ {
+ /* Try reading the Photos Database */
+ path = itdb_get_photodb_path (device->mountpoint);
+ byte_order = endianess_check_path (path, "mhfd");
+ g_free (path);
+ }
+ if (byte_order == 0)
+ {
+ gchar *control_dir = itdb_get_control_dir (device->mountpoint);
+ if (control_dir)
{
- device->byte_order = G_BIG_ENDIAN;
+ gchar *cd_l = g_ascii_strdown (control_dir, -1);
+ if (strstr (cd_l, "itunes/itunes_control") ==
+ (cd_l + strlen (cd_l) - strlen ("itunes/itunes_control")))
+ {
+ device->byte_order = G_BIG_ENDIAN;
+ }
+ g_free (cd_l);
+ g_free (control_dir);
}
- g_free (cd_l);
- g_free (control_dir);
}
}
+
+ /* default: non-reversed */
+ if (byte_order == 0)
+ byte_order = G_LITTLE_ENDIAN;
+
+ device->byte_order = byte_order;
}
diff --git a/src/itdb_device.h b/src/itdb_device.h
index bb02880..115e08e 100644
--- a/src/itdb_device.h
+++ b/src/itdb_device.h
@@ -1,4 +1,4 @@
-/* Time-stamp: <2006-03-21 17:22:34 jcs>
+/* Time-stamp: <2006-05-30 21:53:34 jcs>
|
| Copyright (C) 2002-2005 Jorg Schuler <jcsjcs at users sourceforge net>
| Part of the gtkpod project.
@@ -74,6 +74,11 @@ struct _Itdb_IpodModel {
const guint64 capacity;
guint model_type;
guint generation;
+ /* number of music (Fnn) dirs created by iTunes. The exact
+ number seems to be version dependent. Therefore, the
+ numbers here represent a mixture of reported values and
+ common sense. */
+ guint musicdirs;
};
typedef enum {
@@ -120,8 +125,6 @@ G_GNUC_INTERNAL const Itdb_ArtworkFormat *itdb_device_get_artwork_formats (Itdb_
G_GNUC_INTERNAL const Itdb_IpodModel *itdb_device_get_ipod_model (Itdb_Device *device);
G_GNUC_INTERNAL gint itdb_device_musicdirs_number (Itdb_Device *device);
G_GNUC_INTERNAL void itdb_device_autodetect_endianess (Itdb_Device *device);
-
-
G_END_DECLS
#endif
diff --git a/src/itdb_endianness.h b/src/itdb_endianness.h
index 9cbf692..3eb129c 100644
--- a/src/itdb_endianness.h
+++ b/src/itdb_endianness.h
@@ -41,7 +41,7 @@
} \
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 \
@@ -50,7 +50,23 @@
g_assert (db->device != NULL); \
return get_##lower_case_type (val, db->device->byte_order); \
}
+*/
+#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_DB *db, lower_case_type val) \
+ { \
+ switch (db->db_type) { \
+ case DB_TYPE_ITUNES: \
+ g_assert (db->db.itdb->device != NULL); \
+ return get_##lower_case_type (val, db->db.itdb->device->byte_order); \
+ case DB_TYPE_PHOTO: \
+ g_assert (db->db.photodb->device != NULL); \
+ return get_##lower_case_type (val, db->db.photodb->device->byte_order); \
+ } \
+ return 0; \
+}
DB_TO_CPU_GET_DB(guint32, GUINT32)
DB_TO_CPU_GET_DB(gint32, GINT32)
diff --git a/src/itdb_itunesdb.c b/src/itdb_itunesdb.c
index 821f756..0ca21d3 100644
--- a/src/itdb_itunesdb.c
+++ b/src/itdb_itunesdb.c
@@ -1,4 +1,4 @@
-/* Time-stamp: <2006-05-05 01:07:19 jcs>
+/* Time-stamp: <2006-05-30 21:59:40 jcs>
|
| Copyright (C) 2002-2005 Jorg Schuler <jcsjcs at users sourceforge net>
| Part of the gtkpod project.
@@ -111,19 +111,20 @@
# include <config.h>
#endif
-#include <time.h>
+#include "db-artwork-parser.h"
+#include "itdb_device.h"
+#include "itdb_private.h"
+#include <errno.h>
+#include <fcntl.h>
+#include <glib-object.h>
+#include <glib/gi18n-lib.h>
+#include <stdio.h>
#include <string.h>
-#include <sys/types.h>
#include <sys/stat.h>
-#include <fcntl.h>
+#include <sys/statvfs.h>
+#include <sys/types.h>
+#include <time.h>
#include <unistd.h>
-#include <errno.h>
-#include <stdio.h>
-#include "itdb_private.h"
-#include "itdb_device.h"
-#include "db-artwork-parser.h"
-#include <glib/gi18n-lib.h>
-#include <glib-object.h>
#define ITUNESDB_DEBUG 0
#define ITUNESDB_MHIT_DEBUG 0
@@ -191,6 +192,9 @@ struct _MHODData
typedef struct _MHODData MHODData;
+/* Declarations */
+static gboolean itdb_create_directories (Itdb_Device *device, GError **error);
+
/* ID for error domain */
GQuark itdb_file_error_quark (void)
@@ -1863,9 +1867,9 @@ static glong get_playlist (FImport *fimp, glong mhyp_seek)
/* Some Playlists have added 256 to their type -- I don't know what
it's for, so we just ignore it for now -> & 0xff */
plitem->type = get8int (cts, mhyp_seek+20);
- plitem->flag1 = get8int (cts, mhyp_seek+20);
- plitem->flag2 = get8int (cts, mhyp_seek+20);
- plitem->flag3 = get8int (cts, mhyp_seek+20);
+ plitem->flag1 = get8int (cts, mhyp_seek+21);
+ plitem->flag2 = get8int (cts, mhyp_seek+22);
+ plitem->flag3 = get8int (cts, mhyp_seek+23);
plitem->timestamp = get32lint (cts, mhyp_seek+24);
plitem->id = get64lint (cts, mhyp_seek+28);
plitem->mhodcount = get32lint (cts, mhyp_seek+36);
@@ -2112,8 +2116,8 @@ static glong get_mhit (FImport *fimp, glong mhit_seek)
track->unk156 = get32lint (cts, seek+156);
track->unk160 = get32lint (cts, seek+160);
track->has_artwork = get8int (cts, seek+164);
- track->flag2 = get8int (cts, seek+165);
- track->flag3 = get8int (cts, seek+166);
+ track->skip_when_shuffling = get8int (cts, seek+165);
+ track->remember_playback_position = get8int (cts, seek+166);
track->flag4 = get8int (cts, seek+167);
track->dbid2 = get64lint (cts, seek+168);
track->lyrics_flag = get8int (cts, seek+176);
@@ -2740,7 +2744,6 @@ Itdb_iTunesDB *itdb_parse (const gchar *mp, GError **error)
return itdb;
}
-
/**
* itdb_parse_file:
* @filename: path to a file in iTunesDB format
@@ -3300,8 +3303,8 @@ static void mk_mhit (WContents *cts, Itdb_Track *track)
put32lint (cts, track->unk156);
put32lint (cts, track->unk160);
put8int (cts, track->has_artwork);
- put8int (cts, track->flag2);
- put8int (cts, track->flag3);
+ put8int (cts, track->skip_when_shuffling);
+ put8int (cts, track->remember_playback_position);
put8int (cts, track->flag4);
put64lint (cts, track->dbid2);
put8int (cts, track->lyrics_flag);
@@ -4212,8 +4215,8 @@ gboolean itdb_write_file (Itdb_iTunesDB *itdb, const gchar *filename,
FIXME: figure out a way to store the artwork data when storing
to local directories. At the moment it's the application's task
to handle this. */
- if (itdb->device)
- ipod_write_artwork_db (itdb);
+ if (itdb->device && itdb_device_get_artwork_formats(itdb->device))
+ ipod_write_artwork_db (itdb);
#endif
fexp = g_new0 (FExport, 1);
@@ -4788,6 +4791,45 @@ const gchar *itdb_get_mountpoint (Itdb_iTunesDB *itdb)
return itdb->device->mountpoint;
}
+/* Retrieve a reference to the mountpoint */
+const gchar *itdb_photodb_get_mountpoint (Itdb_PhotoDB *photodb)
+{
+ g_return_val_if_fail (photodb, NULL);
+ g_return_val_if_fail (photodb->device, NULL);
+ return photodb->device->mountpoint;
+}
+
+/* Retrieve a reference to the mountpoint */
+gchar *db_get_mountpoint(Itdb_DB *db)
+{
+ g_return_val_if_fail (db, NULL);
+
+ switch (db->db_type) {
+ case DB_TYPE_ITUNES:
+ g_return_val_if_fail (db->db.itdb->device, NULL);
+ return db->db.itdb->device->mountpoint;
+ case DB_TYPE_PHOTO:
+ g_return_val_if_fail (db->db.photodb->device, NULL);
+ return db->db.photodb->device->mountpoint;
+ }
+ return NULL;
+}
+
+Itdb_Device *db_get_device(Itdb_DB *db)
+{
+ g_return_val_if_fail (db, NULL);
+
+ switch (db->db_type) {
+ case DB_TYPE_ITUNES:
+ g_return_val_if_fail (db->db.itdb->device, NULL);
+ return db->db.itdb->device;
+ case DB_TYPE_PHOTO:
+ g_return_val_if_fail (db->db.photodb->device, NULL);
+ return db->db.photodb->device;
+ }
+ return NULL;
+}
+
/**
* itdb_musicdirs_number:
@@ -5191,8 +5233,8 @@ gchar *itdb_get_control_dir (const gchar *mountpoint)
/**
* itdb_get_dir:
- * mountpoint: the iPod mountpoint
- * dir: a directory
+ * @mountpoint: the iPod mountpoint
+ * @dir: a directory
*
* Retrieve the directory @dir by first calling itdb_get_control_dir()
* and then adding @dir
@@ -5416,3 +5458,380 @@ guint64 itdb_time_host_to_mac (time_t time)
{
return (guint64)(((gint64)time) + 2082844800);
}
+
+
+/**
+ * itdb_init_ipod:
+ * @mountpoint: the iPod mountpoint
+ * @model_number: the iPod model number
+ * @model_type: the type of iPod, eg. regular, shuffle
+ * @ipod_name: the name to give to the iPod. Will be displayed in
+ * gtkpod or itunes
+ *
+ * Initialise an iPod device from scratch. The function attempts to
+ * create a blank database, complete with master playlist and device
+ * information as well as the directory structure required for the
+ * type of iPod.
+ *
+ * Return value: TRUE when successful, FALSE if a failure has occurred.
+ *
+ **/
+gboolean itdb_init_ipod (const gchar *mountpoint,
+ const gchar *model_number,
+ const gchar *ipod_name,
+ GError **error)
+{
+ gboolean writeok;
+ Itdb_iTunesDB *itdb = NULL;
+ Itdb_Playlist *mpl = NULL;
+
+ g_return_val_if_fail (mountpoint, FALSE);
+
+ /* Create new blank itdb database for writing to iPod */
+ itdb = itdb_new();
+
+ /* Assign iPod device reference to new database */
+ itdb_set_mountpoint(itdb, mountpoint);
+
+ /* Rather than reread sysinfo file (that may not exist if
+ * shuffle, use parameter to load into the sysinfo hash.
+ * The model number can be extracted in a couple of ways:
+ * - use the read_sysinfo_file function
+ * - use libipoddevice and hal to get the model
+ * (as far as I know, libipoddevice will also
+ * read the sysinfo file, complemented by some
+ * guessing).
+ */
+ g_hash_table_insert (itdb->device->sysinfo,
+ g_strdup ("ModelNumStr"),
+ g_strdup (model_number));
+
+ /* Create the remaining directories resident on blank ipod */
+ writeok = itdb_create_directories(itdb->device, error);
+ if(! writeok)
+ {
+ return FALSE;
+ }
+
+ /* Create a new playlist with the desired name of the ipod
+ * and set it as the mpl */
+ if (ipod_name == NULL)
+ {
+ mpl = itdb_playlist_new(_("iPod"), FALSE);
+ }
+ else
+ {
+ mpl = itdb_playlist_new(ipod_name, FALSE);
+ }
+ itdb_playlist_set_mpl(mpl);
+ itdb_playlist_add(itdb, mpl, -1);
+
+ /* Write both the iTunesDB and iTunesSD files to the new ipod */
+ writeok = itdb_write(itdb, error);
+ if(! writeok)
+ {
+ itdb_free (itdb);
+ return FALSE;
+ }
+
+ writeok = itdb_shuffle_write(itdb, error);
+ if(! writeok)
+ {
+ itdb_free (itdb);
+ return FALSE;
+ }
+
+ itdb_free (itdb);
+ return TRUE;
+}
+
+/*------------------------------------------------------------------*\
+ * *
+ * Create iPod directory hierarchy *
+ * *
+\*------------------------------------------------------------------*/
+
+/* mkdir_with_parents is copied from GLIB2.8 (gfileutils.c, V1.78), as
+ * it is new to V2.8. May be replaced with g_mkdir_with_parents() in a
+ * couple of years. */
+
+/**
+ * mkdir_with_parents:
+ * @pathname: a pathname in the GLib file name encoding
+ * @mode: permissions to use for newly created directories
+ *
+ * Create a directory if it doesn't already exist. Create intermediate
+ * parent directories as needed, too.
+ *
+ * Returns: 0 if the directory already exists, or was successfully
+ * created. Returns -1 if an error occurred, with errno set.
+ *
+ */
+static int
+mkdir_with_parents (const gchar *pathname,
+ int mode)
+{
+ gchar *fn, *p;
+
+ if (pathname == NULL || *pathname == '\0')
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ fn = g_strdup (pathname);
+
+ if (g_path_is_absolute (fn))
+ p = (gchar *) g_path_skip_root (fn);
+ else
+ p = fn;
+
+ do
+ {
+ while (*p && !G_IS_DIR_SEPARATOR (*p))
+ p++;
+
+ if (!*p)
+ p = NULL;
+ else
+ *p = '\0';
+
+ if (!g_file_test (fn, G_FILE_TEST_EXISTS))
+ {
+ if (g_mkdir (fn, mode) == -1)
+ {
+ int errno_save = errno;
+ g_free (fn);
+ errno = errno_save;
+ return -1;
+ }
+ }
+ else if (!g_file_test (fn, G_FILE_TEST_IS_DIR))
+ {
+ g_free (fn);
+ errno = ENOTDIR;
+ return -1;
+ }
+ if (p)
+ {
+ *p++ = G_DIR_SEPARATOR;
+ while (*p && G_IS_DIR_SEPARATOR (*p))
+ p++;
+ }
+ }
+ while (p);
+
+ g_free (fn);
+
+ return 0;
+}
+
+
+static gboolean itdb_create_directories (Itdb_Device *device, GError **error)
+{
+ const gchar *mp;
+ gboolean result;
+ gchar *pbuf;
+ gint i, dirnum;
+ FILE *sysinfo = NULL;
+ Itdb_IpodModel const *model = NULL;
+ gboolean calconnotes, devicefile;
+ gchar *podpath;
+
+ g_return_val_if_fail (device, FALSE);
+
+ mp = device->mountpoint;
+ g_return_val_if_fail (mp, FALSE);
+
+ /* Retrieve the model from the device information */
+ model = itdb_device_get_ipod_model(device);
+
+ /* Set up special treatment for shuffle and mobile */
+ switch(model->model_type)
+ {
+ case MODEL_TYPE_SHUFFLE:
+ podpath = g_strdup ("iPod_Control");
+ calconnotes = FALSE;
+ devicefile = TRUE;
+ break;
+ case MODEL_TYPE_MOBILE_1:
+ podpath = g_build_filename ("iTunes", "iTunes_Control", NULL);
+ calconnotes = FALSE;
+ devicefile = TRUE;
+ break;
+ case MODEL_TYPE_UNKNOWN:
+ podpath = g_strdup ("iPod_Control");
+ calconnotes = TRUE;
+ devicefile = TRUE;
+ break;
+ default:
+ podpath = g_strdup ("iPod_Control");
+ calconnotes = TRUE;
+ devicefile = TRUE;
+ break;
+ }
+
+ /* Construct the Control directory */
+ pbuf = g_build_filename (mp, podpath, NULL);
+ if (!g_file_test (pbuf, G_FILE_TEST_EXISTS))
+ {
+ if (mkdir_with_parents(pbuf, 0777) != 0)
+ {
+ goto error_dir;
+ }
+ }
+ g_free (pbuf);
+
+ /* Construct the Music directory inside the Control directory */
+ pbuf = g_build_filename (mp, podpath, "Music", NULL);
+ if (!g_file_test (pbuf, G_FILE_TEST_EXISTS))
+ {
+ if((mkdir(pbuf, 0777) != 0))
+ {
+ goto error_dir;
+ }
+ }
+ g_free (pbuf);
+
+ /* Construct the iTunes directory inside the Control directory */
+ pbuf = g_build_filename (mp, podpath, "iTunes", NULL);
+ if (!g_file_test (pbuf, G_FILE_TEST_EXISTS))
+ {
+ if((mkdir(pbuf, 0777) != 0))
+ {
+ goto error_dir;
+ }
+ }
+ g_free (pbuf);
+
+ /* Build Artwork directory only for devices requiring artwork
+ * (assume that 'unknown models' are new and will support
+ * artwork) */
+ if (itdb_device_get_artwork_formats(device) ||
+ (model->model_type == MODEL_TYPE_UNKNOWN))
+ {
+ pbuf = g_build_filename (mp, podpath, "Artwork", NULL);
+ if (!g_file_test (pbuf, G_FILE_TEST_EXISTS))
+ {
+ if((mkdir(pbuf, 0777) != 0)) {
+ goto error_dir;
+ }
+ }
+ g_free (pbuf);
+ }
+
+ /* Build the directories that hold the music files */
+ dirnum = model->musicdirs;
+ if (dirnum == 0)
+ { /* do a guess */
+ struct statvfs stat;
+ if (statvfs (mp, &stat) != 0)
+ { /* why should this fail !? */
+ dirnum = 20;
+ }
+ else
+ {
+ gdouble size = ((gdouble)stat.f_blocks * stat.f_frsize) / 1073741824;
+ if (size < 20) dirnum = 20;
+ else dirnum = 50;
+ }
+ }
+
+ for(i = 0; i < dirnum; i++)
+ {
+ gchar *num = g_strdup_printf ("F%02d", i);
+ pbuf = g_build_filename (mp, podpath, "Music", num, NULL);
+ g_free (num);
+ if (!g_file_test (pbuf, G_FILE_TEST_EXISTS))
+ {
+ if((mkdir(pbuf, 0777) != 0))
+ {
+ goto error_dir;
+ }
+ }
+ g_free (pbuf);
+ }
+
+ /* Build Calendar directory for models requiring it */
+ if (calconnotes)
+ {
+ pbuf = g_build_filename (mp, "Calendars", NULL);
+ if (!g_file_test (pbuf, G_FILE_TEST_EXISTS))
+ {
+ if((mkdir(pbuf, 0777) != 0))
+ {
+ goto error_dir;
+ }
+ }
+ g_free (pbuf);
+
+ /* Build Contacts directory for models requiring it */
+ pbuf = g_build_filename (mp, "Contacts", NULL);
+ if (!g_file_test (pbuf, G_FILE_TEST_EXISTS))
+ {
+ if((mkdir(pbuf, 0777) != 0))
+ {
+ goto error_dir;
+ }
+ }
+ g_free (pbuf);
+
+ pbuf = g_build_filename (mp, "Notes", NULL);
+ if (!g_file_test (pbuf, G_FILE_TEST_EXISTS))
+ {
+ if((mkdir(pbuf, 0777) != 0))
+ {
+ goto error_dir;
+ }
+ }
+ g_free (pbuf);
+ }
+
+ /* Construct a Device directory file for special models */
+ if (devicefile)
+ {
+ pbuf = g_build_filename (mp, podpath, "Device", NULL);
+ if (!g_file_test (pbuf, G_FILE_TEST_EXISTS))
+ {
+ if((mkdir(pbuf, 0777) != 0))
+ {
+ goto error_dir;
+ }
+ }
+ g_free (pbuf);
+
+ /* Construct a SysInfo file */
+ pbuf = g_build_filename (mp, podpath, "Device", "SysInfo", NULL);
+ if (!g_file_test (pbuf, G_FILE_TEST_EXISTS))
+ {
+ sysinfo = fopen(pbuf, "w");
+ if(sysinfo != NULL)
+ {
+ fprintf(sysinfo, "ModelNumStr:%s",
+ model->model_number);
+ fclose(sysinfo);
+ }
+ else
+ {
+ goto error_dir;
+ }
+ }
+ g_free (pbuf);
+ }
+ pbuf = NULL;
+
+ error_dir:
+ if (pbuf)
+ {
+ g_set_error (error, 0, -1,
+ _("Problem creating iPod directory or file: '%s'."),
+ pbuf);
+ result = FALSE;
+ } else
+ {
+ result = TRUE;
+ }
+ g_free (pbuf);
+ g_free (podpath);
+ return result;
+}
diff --git a/src/itdb_photoalbum.c b/src/itdb_photoalbum.c
new file mode 100644
index 0000000..3351da0
--- /dev/null
+++ b/src/itdb_photoalbum.c
@@ -0,0 +1,375 @@
+#include <config.h>
+
+#include "itdb_private.h"
+#include "itdb_device.h"
+#include "db-artwork-parser.h"
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <glib/gi18n-lib.h>
+
+
+/* Set @error with standard error message */
+static void error_no_photos_dir (const gchar *mp, GError **error)
+{
+ gchar *str;
+
+ g_return_if_fail (mp);
+
+ if (error)
+ {
+ str = g_build_filename (mp, "iPod_Control", "Photos", NULL);
+ g_set_error (error,
+ ITDB_FILE_ERROR,
+ ITDB_FILE_ERROR_NOTFOUND,
+ _("Photos directory not found: '%s' (or similar)."),
+ str);
+ g_free (str);
+ }
+}
+
+
+/**
+ * itdb_get_photos_dir:
+ * @mountpoint: mountpoint of iPod
+ *
+ * Retrieve the Photo directory by
+ * first calling itdb_get_control_dir() and then adding 'Photos'
+ *
+ * Return value: path to the Artwork directory or NULL of
+ * non-existent. Must g_free() after use.
+ */
+gchar *itdb_get_photos_dir (const gchar *mountpoint)
+{
+ gchar *p_ipod[] = {"Photos", NULL};
+ /* Use an array with all possibilities, so further extension will
+ be easy */
+ gchar **paths[] = {p_ipod, NULL};
+ gchar ***ptr;
+ gchar *result = NULL;
+
+ g_return_val_if_fail (mountpoint, NULL);
+
+ for (ptr=paths; *ptr && !result; ++ptr)
+ {
+ result = itdb_resolve_path (mountpoint, (const gchar **)*ptr);
+ }
+ return result;
+}
+
+/**
+ * itdb_get_photodb_path:
+ * @mountpoint: the iPod mountpoint
+ *
+ * Retrieve a path to the Photo DB
+ *
+ * Return value: path to the PhotoDB or NULL if non-existent. Must
+ * g_free() after use.
+ **/
+gchar *itdb_get_photodb_path (const gchar *mountpoint)
+{
+ gchar *photo_dir, *path=NULL;
+
+ g_return_val_if_fail (mountpoint, NULL);
+
+ photo_dir = itdb_get_photos_dir (mountpoint);
+
+ if (photo_dir)
+ {
+ path = itdb_get_path (photo_dir, "Photo Database");
+ g_free (photo_dir);
+ }
+
+ return path;
+}
+
+/**
+ * itdb_get_photos_thumb_dir:
+ * @mountpoint: the iPod mountpoint
+ *
+ * Retrieve the Photo Thumbnail directory by
+ * first calling itdb_get_control_dir() and then adding 'Photos/Thumbs'
+ *
+ * Return value: path to the Artwork directory or NULL of
+ * non-existent. Must g_free() after use.
+ */
+gchar *itdb_get_photos_thumb_dir (const gchar *mountpoint)
+{
+ gchar *control_dir;
+ gchar *result = NULL;
+ gchar *dir = "Thumbs";
+
+ g_return_val_if_fail (mountpoint, NULL);
+ g_return_val_if_fail (dir, NULL);
+
+ control_dir = itdb_get_photos_dir (mountpoint);
+ if (control_dir)
+ {
+ const gchar *p_dir[] = {NULL, NULL};
+ p_dir[0] = dir;
+ result = itdb_resolve_path (control_dir, p_dir);
+ g_free (control_dir);
+ }
+ return result;
+}
+
+
+/**
+ * itdb_photodb_parse:
+ *
+ * Parses the photo database of an iPod mounted at @mp.
+ *
+ * @mp: mountpoint of the iPod
+ * @error: will contain the error description when an error occured.
+ *
+ * Return value: the imported PhotoDB or NULL in case of an error.
+ **/
+Itdb_PhotoDB *itdb_photodb_parse (const gchar *mp, GError **error)
+{
+ gchar *photos_dir;
+ Itdb_PhotoDB *photodb = NULL;
+
+ photos_dir = itdb_get_photos_dir (mp);
+
+ if (!photos_dir)
+ {
+ error_no_photos_dir (mp, error);
+ return NULL;
+ }
+ g_free (photos_dir);
+
+ photodb = itdb_photodb_new ();
+ itdb_device_set_mountpoint (photodb->device, mp);
+ ipod_parse_photo_db (photodb);
+ return photodb;
+}
+
+
+/**
+ * itdb_photodb_new:
+ *
+ * Creates a new Itdb_PhotoDB
+ *
+ * Return value: a newly created Itdb_PhotoDB to be freed with
+ * itdb_photodb_free() when it's no longer needed
+ **/
+Itdb_PhotoDB *itdb_photodb_new (void)
+{
+ Itdb_PhotoDB *photodb;
+
+ photodb = g_new0 (Itdb_PhotoDB, 1);
+ photodb->device = itdb_device_new ();
+
+ return photodb;
+}
+
+
+/**
+ * itdb_photodb_free:
+ * @photodb: an #Itdb_PhotoDB
+ *
+ * Free the memory taken by @photodb.
+ **/
+void itdb_photodb_free (Itdb_PhotoDB *photodb)
+{
+ if (photodb)
+ {
+ g_list_foreach (photodb->photoalbums,
+ (GFunc)(itdb_photodb_photoalbum_free), NULL);
+ g_list_free (photodb->photoalbums);
+ g_list_foreach (photodb->photos,
+ (GFunc)(itdb_artwork_free), NULL);
+ g_list_free (photodb->photos);
+ itdb_device_free (photodb->device);
+
+ if (photodb->userdata && photodb->userdata_destroy)
+ (*photodb->userdata_destroy) (photodb->userdata);
+
+ g_free (photodb);
+ }
+}
+
+
+
+
+G_GNUC_INTERNAL gint itdb_get_free_photo_id ( Itdb_PhotoDB *db )
+{
+ gint photo_id = 0;
+ GList *it;
+
+ for (it = db->photos; it != NULL; it = it->next) {
+ Itdb_Artwork *artwork;
+
+ artwork = (Itdb_Artwork *)it->data;
+ if( artwork->id > photo_id )
+ photo_id = artwork->id;
+ }
+ return photo_id + 1;
+}
+
+static gint itdb_get_free_photoalbum_id ( Itdb_PhotoDB *db )
+{
+ gint album_id = 0;
+ GList *it;
+
+ for (it = db->photoalbums; it != NULL; it = it->next) {
+ Itdb_PhotoAlbum *album;
+
+ album = (Itdb_PhotoAlbum *)it->data;
+ if( album->album_id > album_id )
+ album_id = album->album_id;
+ }
+ return album_id + 1;
+}
+
+static Itdb_PhotoAlbum *itdb_get_photoalbum ( Itdb_PhotoDB *db, const gchar *albumname )
+{
+ GList *it;
+
+ if( strcmp( albumname, "master" ) == 0 )
+ return g_list_nth_data (db->photoalbums, 0);
+
+ for (it = db->photoalbums; it != NULL; it = it->next) {
+ Itdb_PhotoAlbum *album;
+
+ album = (Itdb_PhotoAlbum *)it->data;
+ if( strcmp(album->name, albumname) == 0 )
+ return album;
+ }
+ return (Itdb_PhotoAlbum *)NULL;
+}
+
+
+void itdb_photodb_photoalbum_free (Itdb_PhotoAlbum *pa)
+{
+ if (pa)
+ {
+ g_free (pa->name);
+ g_list_free (pa->members);
+
+ if (pa->userdata && pa->userdata_destroy)
+ (*pa->userdata_destroy) (pa->userdata);
+
+ g_free (pa);
+ }
+}
+
+gboolean itdb_photodb_add_photo (Itdb_PhotoDB *db,
+ const gchar *albumname,
+ const gchar *filename)
+{
+ gboolean result;
+ Itdb_Artwork *artwork;
+ Itdb_PhotoAlbum *photoalbum;
+ const Itdb_ArtworkFormat *format;
+ gint photo_id;
+
+ g_return_val_if_fail (db, FALSE);
+ g_return_val_if_fail (filename, FALSE);
+ artwork = itdb_artwork_new ();
+
+ photo_id = itdb_get_free_photo_id( db );
+ artwork->id = photo_id;
+ /* Add a thumbnail for every supported format */
+ format = itdb_device_get_artwork_formats(db->device);
+ for( result = TRUE; format->type != -1 && result == TRUE; format++) {
+ if( format->type == IPOD_COVER_SMALL
+ || format->type == IPOD_COVER_LARGE )
+ continue;
+ result = itdb_artwork_add_thumbnail (artwork,
+ format->type,
+ filename);
+ }
+
+ if (result != TRUE)
+ {
+ itdb_artwork_remove_thumbnails (artwork);
+ return result;
+ }
+ db->photos = g_list_append (db->photos, artwork);
+
+ photoalbum = itdb_get_photoalbum( db, albumname );
+ if( photoalbum == NULL )
+ photoalbum = itdb_photodb_photoalbum_new( db, albumname );
+ photoalbum->num_images++;
+ photoalbum->members = g_list_append (photoalbum->members, GINT_TO_POINTER(photo_id));
+
+ return result;
+}
+
+gboolean itdb_photodb_remove_photo (Itdb_PhotoDB *db,
+ const gint photo_id )
+{
+ gboolean result = TRUE;
+ GList *it;
+
+ g_return_val_if_fail (db, FALSE);
+
+ /* Remove the photo from the image list */
+ for (it = db->photos; it != NULL; it = it->next) {
+ Itdb_Artwork *artwork;
+
+ artwork = (Itdb_Artwork *)it->data;
+ if( artwork->id == photo_id ) {
+ db->photos = g_list_remove (db->photos, artwork);
+ break;
+ }
+ }
+
+ /* Remove the photo from any albums containing it */
+ for (it = db->photoalbums; it != NULL; it = it->next) {
+ Itdb_PhotoAlbum *album;
+
+ album = (Itdb_PhotoAlbum *)it->data;
+ album->members = g_list_remove (album->members, GINT_TO_POINTER(photo_id));
+ album->num_images = g_list_length( album->members );
+ }
+ return result;
+}
+
+Itdb_PhotoAlbum *itdb_photodb_photoalbum_new (Itdb_PhotoDB *db,
+ const gchar *album_name)
+{
+ Itdb_PhotoAlbum *photoalbum;
+
+ g_return_val_if_fail (db, FALSE);
+ g_return_val_if_fail (album_name, FALSE);
+
+ photoalbum = g_new0 (Itdb_PhotoAlbum, 1);
+ photoalbum->album_id = itdb_get_free_photoalbum_id( db );
+ photoalbum->prev_album_id = photoalbum->album_id - 1;
+ photoalbum->name = g_strdup( album_name );
+ db->photoalbums = g_list_append (db->photoalbums, photoalbum);
+
+ return photoalbum;
+}
+
+/**
+ * itdb_photodb_write:
+ * @photodb: the #Itdb_PhotoDB to write to disk
+ * @error: return location for a #GError or NULL
+ *
+ * Write out a PhotoDB.
+ *
+ * FIXME: error is not set yet.
+ *
+ * Return value: TRUE on success, FALSE on error, in which case @error is
+ * set accordingly.
+ **/
+gboolean itdb_photodb_write (Itdb_PhotoDB *photodb, GError **error)
+{
+ gboolean result;
+
+ g_return_val_if_fail (photodb, FALSE);
+ g_return_val_if_fail (photodb->device, FALSE);
+
+ if (photodb->device->byte_order == 0)
+ itdb_device_autodetect_endianess (photodb->device);
+
+ result = ipod_write_photo_db (photodb);
+
+ if (result == -1)
+ return FALSE;
+ else
+ return TRUE;
+}
diff --git a/src/itdb_playlist.c b/src/itdb_playlist.c
index f9e7be1..fcd099f 100644
--- a/src/itdb_playlist.c
+++ b/src/itdb_playlist.c
@@ -1,4 +1,4 @@
-/* Time-stamp: <2005-11-19 16:24:56 jcs>
+/* Time-stamp: <2006-05-30 00:29:18 jcs>
|
| Copyright (C) 2002-2005 Jorg Schuler <jcsjcs at users sourceforge net>
| Part of the gtkpod project.
@@ -40,7 +40,7 @@
/**
* itdb_spl_action_known:
- * action: an #SPLAction
+ * @action: an #SPLAction
*
* Checks if @action is a known (to libgpod) smart playlist action.
*
diff --git a/src/itdb_private.h b/src/itdb_private.h
index c67647e..e13e79e 100644
--- a/src/itdb_private.h
+++ b/src/itdb_private.h
@@ -1,4 +1,4 @@
-/* Time-stamp: <2006-03-15 00:11:00 jcs>
+/* Time-stamp: <2006-05-28 01:11:35 jcs>
|
| Copyright (C) 2002-2005 Jorg Schuler <jcsjcs at users sourceforge net>
| Part of the gtkpod project.
@@ -125,5 +125,9 @@ typedef struct
G_GNUC_INTERNAL gboolean itdb_spl_action_known (SPLAction action);
G_GNUC_INTERNAL void itdb_splr_free (SPLRule *splr);
+G_GNUC_INTERNAL const gchar *itdb_photodb_get_mountpoint (Itdb_PhotoDB *photodb);
+G_GNUC_INTERNAL gchar *db_get_mountpoint (Itdb_DB *db);
+G_GNUC_INTERNAL Itdb_Device *db_get_device(Itdb_DB *db);
+G_GNUC_INTERNAL gint itdb_get_free_photo_id ( Itdb_PhotoDB *db );
#endif
diff --git a/src/ithumb-writer.c b/src/ithumb-writer.c
index 4cf2523..a94c289 100644
--- a/src/ithumb-writer.c
+++ b/src/ithumb-writer.c
@@ -58,7 +58,7 @@ typedef struct _iThumbWriter iThumbWriter;
* square
*/
static guint16 *
-pack_RGB_565 (GdkPixbuf *pixbuf, int dst_width, int dst_height, guint byte_order)
+pack_RGB_565 (GdkPixbuf *pixbuf, iThumbWriter *writer )
{
guchar *pixels;
guint16 *result;
@@ -68,18 +68,32 @@ pack_RGB_565 (GdkPixbuf *pixbuf, int dst_width, int dst_height, guint byte_order
gint height;
gint w;
gint h;
+ gint horizontal_padding;
+ gint vertical_padding;
+ gint byte_order;
g_object_get (G_OBJECT (pixbuf),
"rowstride", &row_stride, "n-channels", &channels,
"height", &height, "width", &width,
"pixels", &pixels, NULL);
- g_return_val_if_fail ((width <= dst_width) && (height <= dst_height), NULL);
+ g_return_val_if_fail ((width <= writer->img_info->width) && (height <= writer->img_info->height), NULL);
/* dst_width and dst_height come from a width/height database
* hardcoded in libipoddevice code, so dst_width * dst_height * 2 can't
* overflow, even on an iPod containing malicious data
*/
- result = g_malloc0 (dst_width * dst_height * 2);
+ result = g_malloc0 ( writer->img_info->width * writer->img_info->height * 2);
+
+ /* Swap the byte order on full screen nano photos */
+ byte_order = writer->byte_order;
+ if ( writer->img_info->correlation_id == 1023) {
+ if (byte_order == G_LITTLE_ENDIAN)
+ byte_order = G_BIG_ENDIAN;
+ else
+ byte_order = G_LITTLE_ENDIAN;
+ }
+ horizontal_padding = (writer->img_info->width - width)/2;
+ vertical_padding = (writer->img_info->height - height)/2;
for (h = 0; h < height; h++) {
for (w = 0; w < width; w++) {
gint r;
@@ -89,49 +103,75 @@ pack_RGB_565 (GdkPixbuf *pixbuf, int dst_width, int dst_height, guint byte_order
r = pixels[h*row_stride + w*channels];
g = pixels[h*row_stride + w*channels + 1];
b = pixels[h*row_stride + w*channels + 2];
+
r >>= (8 - RED_BITS);
g >>= (8 - GREEN_BITS);
b >>= (8 - BLUE_BITS);
r = (r << RED_SHIFT) & RED_MASK;
g = (g << GREEN_SHIFT) & GREEN_MASK;
b = (b << BLUE_SHIFT) & BLUE_MASK;
- result[h*dst_width + w] = get_gint16 (r | g | b,
- byte_order);
+ result[(h+vertical_padding)*writer->img_info->width + w + horizontal_padding]
+ = get_gint16 (r | g | b, byte_order);
}
}
return result;
}
-
-
static char *
-ipod_image_get_ithmb_filename (const char *mount_point, gint correlation_id, gint index)
+ipod_image_get_ithmb_filename (const char *mount_point, gint correlation_id, gint index, DbType db_type )
{
- gchar *artwork_dir, *filename, *buf;
+ gchar *artwork_dir = NULL, *filename, *buf;
g_return_val_if_fail (mount_point, NULL);
+ switch( db_type ) {
+ case DB_TYPE_PHOTO:
+ artwork_dir = itdb_get_photos_thumb_dir (mount_point);
+ if (!artwork_dir)
+ {
+ /* attempt to create Thumbs dir */
+ gchar *photos_dir = itdb_get_photos_dir (mount_point);
+ gchar *dir;
+ if (!photos_dir)
+ { /* give up */
+ return NULL;
+ }
+ dir = g_build_filename (photos_dir, "Thumbs", NULL);
+ mkdir (dir, 0777);
+ g_free (dir);
+ g_free (photos_dir);
+
+ /* try again */
+ artwork_dir = itdb_get_photos_thumb_dir (mount_point);
+ if (!artwork_dir)
+ { /* give up */
+ return NULL;
+ }
+ }
+ break;
+ case DB_TYPE_ITUNES:
artwork_dir = itdb_get_artwork_dir (mount_point);
if (!artwork_dir)
{
- /* attempt to create Artwork dir */
- gchar *control_dir = itdb_get_control_dir (mount_point);
- gchar *dir;
- if (!control_dir)
- { /* give up */
- return NULL;
- }
- dir = g_build_filename (control_dir, "Artwork", NULL);
- mkdir (dir, 0777);
- g_free (dir);
- g_free (control_dir);
-
- /* try again */
- artwork_dir = itdb_get_artwork_dir (mount_point);
- if (!artwork_dir)
- { /* give up */
- return NULL;
- }
+ /* attempt to create Artwork dir */
+ gchar *control_dir = itdb_get_control_dir (mount_point);
+ gchar *dir;
+ if (!control_dir)
+ { /* give up */
+ return NULL;
+ }
+ dir = g_build_filename (control_dir, "Artwork", NULL);
+ mkdir (dir, 0777);
+ g_free (dir);
+ g_free (control_dir);
+
+ /* try again */
+ artwork_dir = itdb_get_artwork_dir (mount_point);
+ if (!artwork_dir)
+ { /* give up */
+ return NULL;
+ }
+ }
}
buf = g_strdup_printf ("F%04u_%d.ithmb", correlation_id, index);
@@ -199,17 +239,24 @@ ithumb_writer_write_thumbnail (iThumbWriter *writer,
thumb->height = height;
thumb->offset = writer->cur_offset;
thumb->size = writer->img_info->width * writer->img_info->height * 2;
-/* printf("offset: %d type: %d, size: %d\n", thumb->offset, thumb->type, thumb->size); */
+
/* FIXME: under certain conditions (probably related to
* writer->offset getting too big), this should be :F%04u_2.ithmb
* and so on
*/
- 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->byte_order);
- g_object_unref (G_OBJECT (pixbuf));
+ if( thumb->type == ITDB_THUMB_PHOTO_LARGE
+ || thumb->type == ITDB_THUMB_PHOTO_SMALL
+ || thumb->type == ITDB_THUMB_PHOTO_FULL_SCREEN )
+ {
+ thumb->filename = g_strdup_printf (":Thumbs:F%04u_1.ithmb",
+ writer->img_info->correlation_id);
+
+ } else {
+ thumb->filename = g_strdup_printf (":F%04u_1.ithmb",
+ writer->img_info->correlation_id);
+ }
+ pixels = pack_RGB_565 (pixbuf, writer );
+ g_object_unref (G_OBJECT (pixbuf));
if (pixels == NULL)
{
@@ -250,8 +297,9 @@ write_thumbnail (gpointer _writer, gpointer _artwork)
static iThumbWriter *
ithumb_writer_new (const char *mount_point,
- const Itdb_ArtworkFormat *info,
- guint byte_order)
+ const Itdb_ArtworkFormat *info,
+ DbType db_type,
+ guint byte_order)
{
char *filename;
iThumbWriter *writer;
@@ -267,7 +315,8 @@ ithumb_writer_new (const char *mount_point,
filename = ipod_image_get_ithmb_filename (mount_point,
info->correlation_id,
- 1);
+ 1,
+ db_type);
if (filename == NULL) {
g_hash_table_destroy (writer->cache);
g_free (writer->img_info);
@@ -512,7 +561,7 @@ static gboolean ithumb_rearrange_thumbnail_file (gpointer _key,
slots are filled, the file is truncated to the new length.
*/
static gboolean
-ithmb_rearrange_existing_thumbnails (Itdb_iTunesDB *itdb,
+ithmb_rearrange_existing_thumbnails (Itdb_DB *db,
const Itdb_ArtworkFormat *info)
{
GList *gl;
@@ -523,11 +572,11 @@ ithmb_rearrange_existing_thumbnails (Itdb_iTunesDB *itdb,
gchar *filename;
const gchar *mountpoint;
- g_return_val_if_fail (itdb, FALSE);
+ g_return_val_if_fail (db, FALSE);
g_return_val_if_fail (info, FALSE);
- g_return_val_if_fail (itdb->device, FALSE);
+ g_return_val_if_fail (db_get_device(db), FALSE);
- mountpoint = itdb_get_mountpoint (itdb);
+ mountpoint = db_get_mountpoint (db);
g_return_val_if_fail (mountpoint, FALSE);
@@ -538,24 +587,47 @@ ithmb_rearrange_existing_thumbnails (Itdb_iTunesDB *itdb,
This will usually be a number of "F%04d_%d.ithmb" files. A
GList is kept with pointers to all images in a given file which
allows to adjust the offset pointers */
- for (gl=itdb->tracks; gl; gl=gl->next)
- {
- Itdb_Thumb *thumb;
- Itdb_Track *track = gl->data;
- g_return_val_if_fail (track, FALSE);
-
- thumb = itdb_artwork_get_thumb_by_type (track->artwork,
- info->type);
- if (thumb && thumb->filename && (thumb->size != 0))
- {
- filename = itdb_thumb_get_filename (itdb->device,
+ switch (db->db_type) {
+ case DB_TYPE_ITUNES:
+ for (gl=db->db.itdb->tracks; gl; gl=gl->next)
+ {
+ Itdb_Thumb *thumb;
+ Itdb_Track *track = gl->data;
+ g_return_val_if_fail (track, FALSE);
+
+ thumb = itdb_artwork_get_thumb_by_type (track->artwork,
+ info->type);
+ if (thumb && thumb->filename && (thumb->size != 0))
+ {
+ filename = itdb_thumb_get_filename (db->db.itdb->device,
thumb);
- if (filename)
- {
- thumbs = g_hash_table_lookup (filenamehash, filename);
- thumbs = g_list_append (thumbs, thumb);
- g_hash_table_insert (filenamehash, filename, thumbs);
- }
+ if (filename)
+ {
+ thumbs = g_hash_table_lookup (filenamehash, filename);
+ thumbs = g_list_append (thumbs, thumb);
+ g_hash_table_insert (filenamehash, filename, thumbs);
+ }
+ }
+ }
+ case DB_TYPE_PHOTO:
+ for (gl=db->db.photodb->photos; gl; gl=gl->next)
+ {
+ Itdb_Thumb *thumb;
+ Itdb_Artwork *artwork = gl->data;
+
+ thumb = itdb_artwork_get_thumb_by_type (artwork,
+ info->type);
+ if (thumb && thumb->filename && (thumb->size != 0))
+ {
+ filename = itdb_thumb_get_filename (db->db.photodb->device,
+ thumb);
+ if (filename)
+ {
+ thumbs = g_hash_table_lookup (filenamehash, filename);
+ thumbs = g_list_append (thumbs, thumb);
+ g_hash_table_insert (filenamehash, filename, thumbs);
+ }
+ }
}
}
@@ -566,7 +638,8 @@ ithmb_rearrange_existing_thumbnails (Itdb_iTunesDB *itdb,
{
filename = ipod_image_get_ithmb_filename (mountpoint,
info->correlation_id,
- i);
+ i,
+ db->db_type);
if (g_file_test (filename, G_FILE_TEST_EXISTS))
{
if (g_hash_table_lookup (filenamehash, filename) == NULL)
@@ -588,32 +661,29 @@ ithmb_rearrange_existing_thumbnails (Itdb_iTunesDB *itdb,
#endif
G_GNUC_INTERNAL int
-itdb_write_ithumb_files (Itdb_iTunesDB *db)
+itdb_write_ithumb_files (Itdb_DB *db)
{
#ifdef HAVE_GDKPIXBUF
GList *writers;
GList *it;
- const gchar *mount_point;
+ Itdb_Device *device;
const Itdb_ArtworkFormat *format;
+ const gchar *mount_point;
g_return_val_if_fail (db, -1);
- g_return_val_if_fail (db->device, -1);
+ device = db_get_device(db);
+ g_return_val_if_fail (device, -1);
- mount_point = itdb_get_mountpoint (db);
+ mount_point = db_get_mountpoint (db);
/* FIXME: support writing to directory rather than writing to
iPod */
if (mount_point == NULL)
return -1;
- if (db->device == NULL) {
- return -1;
- }
-
- format = itdb_device_get_artwork_formats (db->device);
+ format = itdb_device_get_artwork_formats (device);
if (format == NULL) {
return -1;
}
-
writers = NULL;
while (format->type != -1) {
iThumbWriter *writer;
@@ -621,10 +691,15 @@ itdb_write_ithumb_files (Itdb_iTunesDB *db)
switch (format->type) {
case IPOD_COVER_SMALL:
case IPOD_COVER_LARGE:
- ithmb_rearrange_existing_thumbnails (db,
- format);
- writer = ithumb_writer_new (mount_point, format,
- db->device->byte_order);
+ case IPOD_PHOTO_SMALL:
+ case IPOD_PHOTO_LARGE:
+ case IPOD_PHOTO_FULL_SCREEN:
+ ithmb_rearrange_existing_thumbnails (db,
+ format );
+ writer = ithumb_writer_new (mount_point,
+ format,
+ db->db_type,
+ device->byte_order);
if (writer != NULL) {
writers = g_list_prepend (writers, writer);
}
@@ -634,20 +709,32 @@ itdb_write_ithumb_files (Itdb_iTunesDB *db)
}
format++;
}
-
if (writers == NULL) {
return -1;
}
+ switch (db->db_type) {
+ case DB_TYPE_ITUNES:
+ for (it = db->db.itdb->tracks; it != NULL; it = it->next) {
+ Itdb_Track *track;
- for (it = db->tracks; it != NULL; it = it->next) {
- Itdb_Track *track;
+ track = it->data;
+ g_return_val_if_fail (track, -1);
- track = it->data;
- g_return_val_if_fail (track, -1);
+ g_list_foreach (writers, write_thumbnail, track->artwork);
+ }
+ break;
+ case DB_TYPE_PHOTO:
+ for (it = db->db.photodb->photos; it != NULL; it = it->next) {
+ Itdb_Artwork *photo;
- g_list_foreach (writers, write_thumbnail, track->artwork);
- }
+ photo = it->data;
+ g_return_val_if_fail (photo, -1);
+ g_list_foreach (writers, write_thumbnail, photo);
+ }
+ break;
+ }
+
g_list_foreach (writers, (GFunc)ithumb_writer_free, NULL);
g_list_free (writers);