commit 0c286ccec5d66365471381689ee38ddba6f6e902
Author: Christophe Fergeau <[email protected]>
Date: Sun Aug 23 15:17:01 2009 +0200
only write compressed iTunesDB on devices supporting it
src/itdb.h | 1 +
src/itdb_itunesdb.c | 126 +++++++++++++++++++++++++++++++++++++-------------
src/itdb_zlib.c | 108 +++++++++++++++++++++-----------------------
3 files changed, 145 insertions(+), 90 deletions(-)
---
diff --git a/src/itdb.h b/src/itdb.h
index 3084778..3be92ba 100644
--- a/src/itdb.h
+++ b/src/itdb.h
@@ -1749,6 +1749,7 @@ 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_itunescdb_path (const gchar *mountpoint);
gchar *itdb_get_itunessd_path (const gchar *mountpoint);
gchar *itdb_get_artworkdb_path (const gchar *mountpoint);
gchar *itdb_get_photodb_path (const gchar *mountpoint);
diff --git a/src/itdb_itunesdb.c b/src/itdb_itunesdb.c
index d11322c..af9e221 100644
--- a/src/itdb_itunesdb.c
+++ b/src/itdb_itunesdb.c
@@ -2809,7 +2809,7 @@ static gboolean looks_like_itunesdb (FImport *fimp)
return TRUE;
}
-static gboolean parse_fimp (FImport *fimp)
+static gboolean parse_fimp (FImport *fimp, gboolean compressed)
{
glong seek=0;
FContents *cts;
@@ -2820,12 +2820,13 @@ static gboolean parse_fimp (FImport *fimp)
g_return_val_if_fail (fimp->fcontents, FALSE);
g_return_val_if_fail (fimp->fcontents->filename, FALSE);
-
if (!looks_like_itunesdb (fimp)) {
return FALSE;
}
- itdb_zlib_check_decompress_fimp (fimp);
+ if (compressed) {
+ itdb_zlib_check_decompress_fimp (fimp);
+ }
cts = fimp->fcontents;
@@ -2970,7 +2971,7 @@ static void error_no_control_dir (const gchar *mp, GError
**error)
static gboolean
-itdb_parse_internal (Itdb_iTunesDB *itdb, GError **error)
+itdb_parse_internal (Itdb_iTunesDB *itdb, gboolean compressed, GError **error)
{
FImport *fimp;
gboolean success = FALSE;
@@ -2986,7 +2987,7 @@ itdb_parse_internal (Itdb_iTunesDB *itdb, GError **error)
{
if (playcounts_init (fimp))
{
- if (parse_fimp (fimp))
+ if (parse_fimp (fimp, compressed))
{
if (read_OTG_playlists (fimp))
{
@@ -3020,8 +3021,14 @@ Itdb_iTunesDB *itdb_parse (const gchar *mp, GError
**error)
{
gchar *filename;
Itdb_iTunesDB *itdb = NULL;
+ gboolean compressed = FALSE;
- filename = itdb_get_itunesdb_path (mp);
+ filename = itdb_get_itunescdb_path (mp);
+ if (!filename) {
+ filename = itdb_get_itunesdb_path (mp);
+ } else {
+ compressed = TRUE;
+ }
if (filename)
{
itdb = itdb_new ();
@@ -3032,7 +3039,7 @@ Itdb_iTunesDB *itdb_parse (const gchar *mp, GError
**error)
itdb_set_mountpoint (itdb, mp);
itdb->filename = g_strdup (filename);
- success = itdb_parse_internal (itdb, error);
+ success = itdb_parse_internal (itdb, compressed, error);
if (success)
{
/* We don't test the return value of ipod_parse_artwork_db
@@ -3099,7 +3106,7 @@ Itdb_iTunesDB *itdb_parse_file (const gchar *filename,
GError **error)
itdb = itdb_new ();
itdb->filename = g_strdup (filename);
- success = itdb_parse_internal (itdb, error);
+ success = itdb_parse_internal (itdb, FALSE, error);
if (!success)
{
itdb_free (itdb);
@@ -5319,20 +5326,10 @@ static void prepare_itdb_for_write (FExport *fexp)
}
}
-
-/**
- * itdb_write_file:
- * @itdb: the #Itdb_iTunesDB to save
- * @filename: filename to save @itdb to
- * @error: return location for a #GError or NULL
- *
- * Write the content of @itdb to @filename. If @filename is NULL, it attempts
- * to write to @itdb->filename.
- *
- * Returns: TRUE if all went well, FALSE otherwise
- */
-gboolean itdb_write_file (Itdb_iTunesDB *itdb, const gchar *filename,
- GError **error)
+static gboolean itdb_write_file_internal (Itdb_iTunesDB *itdb,
+ const gchar *filename,
+ const gchar *compressed_filename,
+ GError **error)
{
FExport *fexp;
gulong mhbd_seek = 0;
@@ -5382,15 +5379,27 @@ gboolean itdb_write_file (Itdb_iTunesDB *itdb, const
gchar *filename,
{
if (write_mhsd_albums (fexp)) {
fix_header (cts, mhbd_seek);
- if (itdb_zlib_check_compress_fexp (fexp)) {
- /* Set checksum (ipods require it starting from
- * iPod Classic and fat Nanos)
+ if (compressed_filename) {
+ /* If we were asked to write a compressed file, starts
by writing
+ * an uncompressed copy of the iTunesDB
*/
itdb_device_write_checksum (itdb->device,
(unsigned char
*)fexp->wcontents->contents,
fexp->wcontents->pos,
- &fexp->error);
+ NULL);
+ wcontents_write (cts);
+ if (!itdb_zlib_check_compress_fexp (fexp)) {
+ goto err;
+ }
+ g_free (cts->filename);
+ cts->filename = g_strdup (compressed_filename);
}
+
+ /* Set checksum (ipods require it starting from Classic and
Nano Video) */
+ itdb_device_write_checksum (itdb->device,
+ (unsigned char
*)fexp->wcontents->contents,
+ fexp->wcontents->pos,
+ &fexp->error);
}
}
}
@@ -5401,6 +5410,7 @@ gboolean itdb_write_file (Itdb_iTunesDB *itdb, const
gchar *filename,
if (!wcontents_write (cts))
g_propagate_error (&fexp->error, cts->error);
}
+err:
if (fexp->error)
{
g_propagate_error (error, fexp->error);
@@ -5426,6 +5436,24 @@ gboolean itdb_write_file (Itdb_iTunesDB *itdb, const
gchar *filename,
}
/**
+ * itdb_write_file:
+ * @itdb: the #Itdb_iTunesDB to save
+ * @filename: filename to save @itdb to
+ * @error: return location for a #GError or NULL
+ *
+ * Write the content of @itdb to @filename. If @filename is NULL, it attempts
+ * to write to @itdb->filename.
+ *
+ * Returns: TRUE if all went well, FALSE otherwise
+ */
+
+gboolean itdb_write_file (Itdb_iTunesDB *itdb, const gchar *filename,
+ GError **error)
+{
+ return itdb_write_file_internal (itdb, filename, NULL, error);
+}
+
+/**
* itdb_write:
* @itdb: the #Itdb_iTunesDB to write to disk
* @error: return location for a #GError or NULL
@@ -5442,6 +5470,7 @@ gboolean itdb_write_file (Itdb_iTunesDB *itdb, const
gchar *filename,
gboolean itdb_write (Itdb_iTunesDB *itdb, GError **error)
{
gchar *itunes_filename, *itunes_path;
+ gchar *itunescdb_filename;
gboolean result = FALSE;
g_return_val_if_fail (itdb, FALSE);
@@ -5463,15 +5492,19 @@ gboolean itdb_write (Itdb_iTunesDB *itdb, GError
**error)
return FALSE;
}
- if (itdb->version >= 0x28) {
- itunes_filename = g_build_filename (itunes_path, "iTunesCDB", NULL);
+ itunes_filename = g_build_filename (itunes_path, "iTunesDB", NULL);
+ if (itdb_device_supports_compressed_itunesdb (itdb->device)) {
+ itunescdb_filename = g_build_filename (itunes_path, "iTunesCDB", NULL);
} else {
- itunes_filename = g_build_filename (itunes_path, "iTunesDB", NULL);
+ itunescdb_filename = NULL;
}
- result = itdb_write_file (itdb, itunes_filename, error);
+ result = itdb_write_file_internal (itdb, itunes_filename,
+ itunescdb_filename,
+ error);
g_free (itunes_filename);
+ g_free (itunescdb_filename);
g_free (itunes_path);
if (result != FALSE)
@@ -6761,10 +6794,37 @@ gchar *itdb_get_itunesdb_path (const gchar *mountpoint)
if (itunes_dir)
{
+ path = itdb_get_path (itunes_dir, "iTunesDB");
+ g_free (itunes_dir);
+ }
+
+ return path;
+}
+
+/**
+ * itdb_get_itunescdb_path:
+ * @mountpoint: the iPod mountpoint
+ *
+ * Retrieve a path to the iTunesCDB. The iTunesCDB is a compressed version
+ * of the iTunesDB which can be found on iPhones/iPod Touch with firmware 3.0
+ *
+ *
+ * Returns: path to the iTunesCDB or NULL if non-existent. Must g_free()
+ * after use.
+ *
+ * Since: 0.4.0
+ */
+gchar *itdb_get_itunescdb_path (const gchar *mountpoint)
+{
+ gchar *itunes_dir, *path=NULL;
+
+ g_return_val_if_fail (mountpoint, NULL);
+
+ itunes_dir = itdb_get_itunes_dir (mountpoint);
+
+ if (itunes_dir)
+ {
path = itdb_get_path (itunes_dir, "iTunesCDB");
- if (!path) {
- path = itdb_get_path (itunes_dir, "iTunesDB");
- }
g_free (itunes_dir);
}
diff --git a/src/itdb_zlib.c b/src/itdb_zlib.c
index 888ec10..2ddde2b 100644
--- a/src/itdb_zlib.c
+++ b/src/itdb_zlib.c
@@ -102,6 +102,9 @@ static int zlib_inflate(gchar *outbuf, gchar *zdata, gsize
compressed_size, gsiz
gboolean itdb_zlib_check_decompress_fimp (FImport *fimp)
{
FContents *cts;
+ guint32 headerSize;
+ guint32 cSize;
+ size_t uSize;
g_return_val_if_fail (fimp, FALSE);
g_return_val_if_fail (fimp->itdb, FALSE);
@@ -110,34 +113,30 @@ gboolean itdb_zlib_check_decompress_fimp (FImport *fimp)
cts = fimp->fcontents;
- /* only proceed with decompression if it's a compressed file */
- if ((*(guint32*)(cts->contents+12) == 2) && (*(guint32*)(cts->contents+16)
>= 0x28)) {
- /* get some values */
- guint32 headerSize = *(guint32*)(cts->contents+4);
- guint32 cSize = *(guint32*)(cts->contents+8);
- size_t uSize = 0;
-
- if (zlib_inflate(NULL, cts->contents+headerSize, cSize-headerSize,
&uSize) == 0) {
- gchar *new_contents;
- g_print("allocating %"G_GSIZE_FORMAT"\n", uSize+headerSize);
- new_contents = (gchar*)g_malloc(uSize+headerSize);
- memcpy(new_contents, cts->contents, headerSize);
- g_print("decompressing\n");
- if (zlib_inflate(new_contents+headerSize, cts->contents+headerSize,
cSize-headerSize, &uSize) == 0) {
- /* update FContents structure */
- g_free(cts->contents);
- cts->contents = new_contents;
- cts->length = uSize+headerSize;
- g_print("uncompressed size: %"G_GSIZE_FORMAT"\n", cts->length);
- }
- } else {
- g_set_error (&fimp->error,
+ cSize = *(guint32*)(cts->contents+8);
+ headerSize = *(guint32*)(cts->contents+4);
+ uSize = 0;
+
+ if (zlib_inflate(NULL, cts->contents+headerSize, cSize-headerSize, &uSize)
== 0) {
+ gchar *new_contents;
+ g_print("allocating %"G_GSIZE_FORMAT"\n", uSize+headerSize);
+ new_contents = (gchar*)g_malloc(uSize+headerSize);
+ memcpy(new_contents, cts->contents, headerSize);
+ g_print("decompressing\n");
+ if (zlib_inflate(new_contents+headerSize, cts->contents+headerSize,
cSize-headerSize, &uSize) == 0) {
+ /* update FContents structure */
+ g_free(cts->contents);
+ cts->contents = new_contents;
+ cts->length = uSize+headerSize;
+ g_print("uncompressed size: %"G_GSIZE_FORMAT"\n", cts->length);
+ }
+ } else {
+ g_set_error (&fimp->error,
ITDB_FILE_ERROR,
ITDB_FILE_ERROR_CORRUPT,
_("iTunesCDB '%s' could not be decompressed"),
cts->filename);
- return FALSE;
- }
+ return FALSE;
}
return TRUE;
@@ -145,45 +144,40 @@ gboolean itdb_zlib_check_decompress_fimp (FImport *fimp)
gboolean itdb_zlib_check_compress_fexp (FExport *fexp)
{
- Itdb_iTunesDB *itdb;
WContents *cts;
+ guint32 header_len;
+ uLongf compressed_len;
+ guint32 uncompressed_len;
+ gchar *new_contents;
+ int status;
- itdb = fexp->itdb;
cts = fexp->wcontents;
- if (itdb->version < 0x28) {
- guint32 header_len;
- uLongf compressed_len;
- guint32 uncompressed_len;
- gchar *new_contents;
- int status;
-
- g_print("target DB needs compression\n");
-
- header_len = *(guint32*)(cts->contents+4);
- uncompressed_len = *(guint32*)(cts->contents+8) - header_len;
- compressed_len = compressBound (uncompressed_len);
-
- new_contents = g_malloc (header_len + compressed_len);
- memcpy (new_contents, cts->contents, header_len);
- status = compress2 ((guchar*)new_contents + header_len, &compressed_len,
- (guchar*)cts->contents + header_len,
uncompressed_len, 1);
- if (status != Z_OK) {
- g_free (new_contents);
- g_set_error (&fexp->error,
- ITDB_FILE_ERROR,
- ITDB_FILE_ERROR_ITDB_CORRUPT,
- _("Error compressing iTunesCDB file!\n"));
- return FALSE;
- }
+ g_print("target DB needs compression\n");
+
+ header_len = *(guint32*)(cts->contents+4);
+ uncompressed_len = *(guint32*)(cts->contents+8) - header_len;
+ compressed_len = compressBound (uncompressed_len);
- g_free(cts->contents);
- /* update mhbd size */
- *(guint32*)(new_contents+8) = compressed_len + header_len;
- cts->contents = new_contents;
- cts->pos = compressed_len + header_len;
- g_print("compressed size: %ld\n", cts->pos);
+ new_contents = g_malloc (header_len + compressed_len);
+ memcpy (new_contents, cts->contents, header_len);
+ status = compress2 ((guchar*)new_contents + header_len, &compressed_len,
+ (guchar*)cts->contents + header_len, uncompressed_len,
1);
+ if (status != Z_OK) {
+ g_free (new_contents);
+ g_set_error (&fexp->error,
+ ITDB_FILE_ERROR,
+ ITDB_FILE_ERROR_ITDB_CORRUPT,
+ _("Error compressing iTunesCDB file!\n"));
+ return FALSE;
}
+ g_free(cts->contents);
+ /* update mhbd size */
+ *(guint32*)(new_contents+8) = compressed_len + header_len;
+ cts->contents = new_contents;
+ cts->pos = compressed_len + header_len;
+ g_print("compressed size: %ld\n", cts->pos);
+
return TRUE;
}
------------------------------------------------------------------------------
Return on Information:
Google Enterprise Search pays you back
Get the facts.
http://p.sf.net/sfu/google-dev2dev
_______________________________________________
gtkpod-cvs2 mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/gtkpod-cvs2