summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog8
-rw-r--r--src/Makefile.am1
-rw-r--r--src/itdb.h47
-rw-r--r--src/itdb_itunesdb.c138
-rw-r--r--src/itdb_track.c10
5 files changed, 164 insertions, 40 deletions
diff --git a/ChangeLog b/ChangeLog
index c4421e4..c3275d7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2007-11-17 Jorg Schuler <jcsjcs at users.sourceforge.net>
+
+ * src/itdb_track.c
+ * src/itdb_itunesdb.c
+ * src/itdb_chapterdata
+ * src/itdb.h
+ * src/Makefile.am: applied chapterdata patch by Michael Tiffany.
+
2008-01-02 Christophe Fergeau <teuf@gnome.org>
* src/itdb_device.c: fix ITDB_THUMB_PHOTO_FULL_SCREEN format on
diff --git a/src/Makefile.am b/src/Makefile.am
index 0d7d58e..1e5315b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -7,6 +7,7 @@ libgpod_la_SOURCES = \
db-image-parser.c \
db-parse-context.c \
itdb_artwork.c \
+ itdb_chapterdata.c \
itdb_device.c \
itdb_itunesdb.c \
itdb_photoalbum.c \
diff --git a/src/itdb.h b/src/itdb.h
index d8b66cc..92c5eb1 100644
--- a/src/itdb.h
+++ b/src/itdb.h
@@ -66,6 +66,8 @@ typedef struct _Itdb_PhotoDB Itdb_PhotoDB;
typedef struct _Itdb_Playlist Itdb_Playlist;
typedef struct _Itdb_PhotoAlbum Itdb_PhotoAlbum;
typedef struct _Itdb_Track Itdb_Track;
+typedef struct _Itdb_Chapter Itdb_Chapter;
+typedef struct _Itdb_Chapterdata Itdb_Chapterdata;
/* ------------------------------------------------------------ *\
@@ -435,6 +437,37 @@ struct _Itdb_SPLRules
};
+/* ------------------------------------------------------------ *\
+ *
+ * Chapters
+ *
+\* ------------------------------------------------------------ */
+
+struct _Itdb_Chapter
+{
+ guint32 startpos;
+ gchar *chaptertitle; /* data in UTF8 */
+ /* reserved for future use */
+ gint32 reserved_int1;
+ gint32 reserved_int2;
+ gpointer reserved1;
+ gpointer reserved2;
+};
+
+
+struct _Itdb_Chapterdata
+{
+ GList *chapters;
+ guint32 unk024;
+ guint32 unk028;
+ guint32 unk032;
+ /* reserved for future use */
+ gint32 reserved_int1;
+ gint32 reserved_int2;
+ gpointer reserved1;
+ gpointer reserved2;
+};
+
/* ------------------------------------------------------------ *\
*
@@ -741,7 +774,7 @@ struct _Itdb_Track
gchar *description; /* see note for MHOD_ID in itdb_itunesdb.c */
gchar *podcasturl; /* see note for MHOD_ID in itdb_itunesdb.c */
gchar *podcastrss; /* see note for MHOD_ID in itdb_itunesdb.c */
- gpointer chapterdata; /* not yet supported. Help welcome. */
+ Itdb_Chapterdata *chapterdata; /* see note for MHOD_ID in itdb_itunesdb.c */
gchar *subtitle; /* see note for MHOD_ID in itdb_itunesdb.c */
/* the following 6 are new in libgpod 0.4.2... */
gchar *tvshow; /* see note for MHOD_ID in itdb_itunesdb.c */
@@ -1225,6 +1258,18 @@ Itdb_Thumb *itdb_thumb_duplicate (Itdb_Thumb *thumb);
void itdb_thumb_free (Itdb_Thumb *thumb);
Itdb_Thumb *itdb_thumb_new (void);
gchar *itdb_thumb_get_filename (Itdb_Device *device, Itdb_Thumb *thumb);
+/* itdb_chapterdata_... */
+Itdb_Chapterdata *itdb_chapterdata_new (void);
+void itdb_chapterdata_free (Itdb_Chapterdata *chapterdata);
+Itdb_Chapterdata *itdb_chapterdata_duplicate (Itdb_Chapterdata *chapterdata);
+void itdb_chapterdata_remove_chapter (Itdb_Chapterdata *chapterdata, Itdb_Chapter *chapter);
+void itdb_chapterdata_remove_chapters (Itdb_Chapterdata *chapterdata);
+Itdb_Chapter *itdb_chapter_new (void);
+void itdb_chapter_free (Itdb_Chapter *chapter);
+Itdb_Chapter *itdb_chapter_duplicate (Itdb_Chapter *chapter);
+gboolean itdb_chapterdata_add_chapter (Itdb_Chapterdata *chapterdata,
+ gint32 startpos,
+ gchar *chaptertitle);
#ifndef LIBGPOD_DISABLE_DEPRECATED
/* time functions */
diff --git a/src/itdb_itunesdb.c b/src/itdb_itunesdb.c
index 42749f3..cbd4cc9 100644
--- a/src/itdb_itunesdb.c
+++ b/src/itdb_itunesdb.c
@@ -258,8 +258,7 @@ struct _MHODData
{
gint32 track_pos;
gchar *string;
- gchar *chapterdata_raw;
- Itdb_Track *chapterdata_track; /* for writing chapterdata */
+ Itdb_Chapterdata *chapterdata;
Itdb_SPLPref *splpref;
Itdb_SPLRules *splrules;
GList *mhod52coltracks;
@@ -766,7 +765,6 @@ static guint64 get64lint (FContents *cts, glong seek)
Reversed Endian Sensitive (big endian)
------------------------------------------------------------ */
-#if 0
static guint16 get16bint (FContents *cts, glong seek)
{
g_return_val_if_fail (cts, 0);
@@ -775,7 +773,7 @@ static guint16 get16bint (FContents *cts, glong seek)
else
return raw_get16lint (cts, seek);
}
-#endif
+
static guint32 get32bint (FContents *cts, glong seek)
{
g_return_val_if_fail (cts, 0);
@@ -827,7 +825,7 @@ static gunichar2 *fixup_little_utf16 (gunichar2 *utf16_string)
}
/* Fix big endian UTF16 String to correct byteorder if necessary (only
- * strings in smart playlists are big endian) */
+ * strings in smart playlists and chapter data are big endian) */
static gunichar2 *fixup_big_utf16 (gunichar2 *utf16_string)
{
# if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
@@ -1419,14 +1417,52 @@ static MHODData get_mhod (FImport *fimp, glong mhod_seek, guint32 *ml)
return result; /* *ml==-1, result.valid==FALSE */
}
break;
- case MHOD_ID_CHAPTERDATA:
- /* we'll just copy the entire data section */
- xl = mhod_len - header_length;
- result.data.chapterdata_raw = g_new0 (gchar, xl);
- if (!seek_get_n_bytes (cts, result.data.chapterdata_raw, seek, xl))
+ case MHOD_ID_CHAPTERDATA:
+ result.data.chapterdata = itdb_chapterdata_new();
+ result.data.chapterdata->unk024 = get32lint (cts, seek);
+ result.data.chapterdata->unk028 = get32lint (cts, seek+4);
+ result.data.chapterdata->unk032 = get32lint (cts, seek+8);
+ seek += 12; /* get past unks */
+ if (check_header_seek (cts, "sean", seek+4))
{
- g_free (result.data.chapterdata_raw);
- return result; /* *ml==-1, result.valid==FALSE */
+ gint i;
+ guint32 numchapters;
+ numchapters = get32bint (cts, seek+12) - 1; /* minus 1 for hedr atom */
+ seek += 20; /* move to atom data */
+ for (i=0; i<numchapters; ++i)
+ {
+ if (check_header_seek (cts, "chap", seek+4))
+ {
+ guint32 length;
+ guint32 startpos;
+ gunichar2 *string_utf16;
+ startpos = get32bint (cts, seek+8);
+ seek += 20;
+ if (check_header_seek (cts, "name", seek+4))
+ {
+ length = get16bint (cts, seek+20);
+ string_utf16 = g_new0 (gunichar2, (length+1));
+ if (!seek_get_n_bytes (cts, (gchar *)string_utf16,
+ seek+22, length*2))
+ {
+ g_free (string_utf16);
+ itdb_chapterdata_free (result.data.chapterdata);
+ return result; /* *ml==-1, result.valid==FALSE */
+ }
+ fixup_big_utf16 (string_utf16);
+ itdb_chapterdata_add_chapter(result.data.chapterdata,startpos,g_utf16_to_utf8 (
+ string_utf16, -1, NULL, NULL, NULL));
+ g_free (string_utf16);
+ seek += length * 2 + 22;
+ }
+ }
+ }
+ if (check_header_seek (cts, "hedr", seek+4))
+ {
+ guint32 hedrlength = get32bint(cts, seek);
+ seek += hedrlength;
+ }
+
}
break;
case MHOD_ID_SPLPREF: /* Settings for smart playlist */
@@ -2406,14 +2442,10 @@ static glong get_mhit (FImport *fimp, glong mhit_seek)
switch (type)
{
case MHOD_ID_CHAPTERDATA:
- /* we just read the entire chapterdata info until we
- have a better way to parse and represent it */
mhod = get_mhod (fimp, seek, &zip);
- if (mhod.valid && mhod.data.chapterdata_raw)
+ if (mhod.valid && mhod.data.chapterdata)
{
- track->chapterdata_raw = mhod.data.chapterdata_raw;
- track->chapterdata_raw_length =
- zip - get32lint (cts, seek+4);
+ track->chapterdata = mhod.data.chapterdata;
mhod.valid = FALSE;
}
break;
@@ -3347,7 +3379,6 @@ static void put64lint (WContents *cts, guint64 n)
/* ------------------------------------------------------------
Reversed Endian Sensitive (big endian)
------------------------------------------------------------ */
-#if 0
static void put16bint (WContents *cts, guint16 n)
{
if (cts->reversed)
@@ -3355,7 +3386,7 @@ static void put16bint (WContents *cts, guint16 n)
else
raw_put16bint (cts, n);
}
-#endif
+
static void put24bint (WContents *cts, guint32 n)
{
if (cts->reversed)
@@ -3379,6 +3410,7 @@ static void put32bfloat (WContents *cts, float f)
else
raw_put32bfloat (cts, f);
}
+#endif
static void put32bint_seek (WContents *cts, guint32 n, gulong seek)
{
@@ -3387,7 +3419,7 @@ static void put32bint_seek (WContents *cts, guint32 n, gulong seek)
else
raw_put32bint_seek (cts, n, seek);
}
-#endif
+
static void put64bint (WContents *cts, guint64 n)
{
if (cts->reversed)
@@ -3934,16 +3966,58 @@ static void mk_mhod (FExport *fexp, MHODData *mhod)
put32_n0 (cts, 4); /* unknown */
break;
case MHOD_ID_CHAPTERDATA:
- g_return_if_fail (mhod->data.chapterdata_track);
+ g_return_if_fail (mhod->data.chapterdata);
{
- Itdb_Track *track = mhod->data.chapterdata_track;
- put_header (cts, "mhod"); /* header */
- put32lint (cts, 24); /* size of header */
- put32lint (cts, 24+track->chapterdata_raw_length); /*size */
- put32lint (cts, mhod->type); /* type of the entry */
- put32_n0 (cts, 2); /* unknown */
- put_data (cts, track->chapterdata_raw,
- track->chapterdata_raw_length);
+ gulong header_seek = cts->pos; /* needed to fix length */
+ GList *gl;
+ gint numchapters = g_list_length (mhod->data.chapterdata->chapters);
+ put_header (cts, "mhod"); /* header */
+ put32lint (cts, 24); /* header size */
+ put32lint (cts, -1); /* total length, fix later */
+ put32lint (cts, mhod->type); /* entry type */
+ put32_n0 (cts, 2); /* unknown */
+ put32lint (cts, mhod->data.chapterdata->unk024); /* unknown */
+ put32lint (cts, mhod->data.chapterdata->unk028); /* unknown */
+ put32lint (cts, mhod->data.chapterdata->unk032); /* unknown */
+ put32bint (cts, -1); /* total length of sean atom, fix later */
+ put_header (cts, "sean");
+ put32bint (cts, 1); /* unknown */
+ put32bint (cts, numchapters+1); /* children */
+ put32bint (cts, 0); /* unknown */
+ for (gl=mhod->data.chapterdata->chapters; gl; gl=gl->next)
+ {
+ gunichar2 *title_utf16;
+ Itdb_Chapter *chapter = gl->data;
+/* gint len = strlen(chapter->chaptertitle); */
+ glong len;
+ title_utf16 = NULL;
+ title_utf16 = g_utf8_to_utf16 (chapter->chaptertitle,
+ -1,NULL,&len,NULL);
+ fixup_big_utf16 (title_utf16);
+ put32bint (cts, 42+2*len); /* total length */
+ put_header (cts, "chap");
+ put32bint (cts, chapter->startpos); /* should we check if startpos=0 here? */
+ put32bint (cts, 1); /* children */
+ put32bint (cts, 0); /* unknown */
+ put32bint (cts, 22+2*len); /* length */
+ put_header (cts, "name");
+ put32bint (cts, 1); /* unknown */
+ put32_n0 (cts, 2); /* unknown */
+ put16bint (cts, len);
+ put_data (cts, (gchar *)title_utf16, 2*len);
+ g_free (title_utf16);
+
+ }
+ put32bint (cts, 28); /* size */
+ put_header (cts, "hedr");
+ put32bint (cts, 1); /* unknown */
+ put32bint (cts, 0); /* children */
+ put32_n0 (cts, 2); /* unknown */
+ put32bint (cts, 1); /* unknown */
+
+
+ put32bint_seek (cts, cts->pos-(header_seek+36), header_seek+36); /* fix length of sean atom */
+ fix_header (cts, header_seek);
}
break;
case MHOD_ID_SPLPREF:
@@ -4427,10 +4501,10 @@ static gboolean write_mhsd_tracks (FExport *fexp)
mk_mhod (fexp, &mhod);
++mhod_num;
}
- if (track->chapterdata_raw && track->chapterdata_raw_length)
+ if (track->chapterdata && track->chapterdata->chapters)
{
mhod.type = MHOD_ID_CHAPTERDATA;
- mhod.data.chapterdata_track = track;
+ mhod.data.chapterdata = track->chapterdata;
mk_mhod (fexp, &mhod);
++mhod_num;
}
diff --git a/src/itdb_track.c b/src/itdb_track.c
index 976a714..470f92d 100644
--- a/src/itdb_track.c
+++ b/src/itdb_track.c
@@ -63,6 +63,7 @@ Itdb_Track *itdb_track_new (void)
Itdb_Track *track = g_new0 (Itdb_Track, 1);
track->artwork = itdb_artwork_new ();
+ track->chapterdata = itdb_chapterdata_new ();
track->visible = 1;
return track;
@@ -272,7 +273,7 @@ void itdb_track_free (Itdb_Track *track)
g_free (track->sort_composer);
g_free (track->sort_tvshow);
- g_free (track->chapterdata_raw);
+ itdb_chapterdata_free (track->chapterdata);
itdb_artwork_free (track->artwork);
@@ -372,12 +373,7 @@ Itdb_Track *itdb_track_duplicate (Itdb_Track *tr)
/* Copy chapterdata */
- if (tr->chapterdata_raw)
- {
- tr_dup->chapterdata_raw = g_new (gchar, tr->chapterdata_raw_length);
- memcpy (tr_dup->chapterdata_raw, tr->chapterdata_raw,
- tr->chapterdata_raw_length);
- }
+ tr_dup->chapterdata = itdb_chapterdata_duplicate (tr->chapterdata);
/* Copy thumbnail data */
tr_dup->artwork = itdb_artwork_duplicate (tr->artwork);