summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJorg Schuler <jcsjcs@users.sourceforge.net>2005-11-28 16:20:40 +0000
committerJorg Schuler <jcsjcs@users.sourceforge.net>2005-11-28 16:20:40 +0000
commitd1b17206d01ebd9c94aa20778cac4b0eed6bfa4a (patch)
tree1a6daa9453d7e9fe171fdf680c66d63a0eaabc27
parent93cfd1639a324a3a168b0438ad852b5d6c864e4d (diff)
downloadlibgpod-d1b17206d01ebd9c94aa20778cac4b0eed6bfa4a.tar.gz
libgpod-d1b17206d01ebd9c94aa20778cac4b0eed6bfa4a.tar.xz
libgpod-d1b17206d01ebd9c94aa20778cac4b0eed6bfa4a.zip
New API for thumbnail support: see src/itdb.h for details.
* src/itdb.h: Introduced Itdb_Artwork and ItdbThumbType and changed Itdb_Image to Itdb_Thumb throughout the source. * src/itdb_artwork.c: new file as backend for Itdb_Artwork support (new, free, duplicate, get_thumb_by_type, add_thumbnail, remove_thumbnail, remove_thumbnails), as well as for the Itdb_Thumb support (new, free, duplicate, get_gdk_pixbuf, get_filename) * src/itdb_track.c: new functions for artwork support (set_thumbnails, remove_thumbnails) * src/ithumb-writer.c: added support to write thumbnails in addition to existing thumbnails * src/db-artwork-parcer.c: (mhod3_get_ithmb_filename) * src/itdb_itunesdb.c: (update_artwork_info) * tests/test-covers.c: updated to new API. * tests/test-write-covers.c: updated to new API. Known issues: iTunes wipes off our thumbnails. git-svn-id: https://gtkpod.svn.sf.net/svnroot/gtkpod/libgpod/trunk@1180 f01d2545-417e-4e96-918e-98f8d0dbbcb6
-rw-r--r--ChangeLog29
-rw-r--r--src/Makefile.am1
-rw-r--r--src/db-artwork-parser.c24
-rw-r--r--src/db-artwork-writer.c50
-rw-r--r--src/db-image-parser.c157
-rw-r--r--src/db-image-parser.h5
-rw-r--r--src/itdb.h190
-rw-r--r--src/itdb_artwork.c429
-rw-r--r--src/itdb_itunesdb.c29
-rw-r--r--src/itdb_track.c122
-rw-r--r--src/ithumb-writer.c456
-rw-r--r--tests/test-covers.c24
-rw-r--r--tests/test-write-covers.c4
13 files changed, 1054 insertions, 466 deletions
diff --git a/ChangeLog b/ChangeLog
index 17f7a6c..2c2ff0a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,32 @@
+2005-11-28 Jorg Schuler <jcsjcs at users.sourceforge.net>
+
+ New API for thumbnail support: see src/itdb.h for details.
+
+ * src/itdb.h: Introduced Itdb_Artwork and ItdbThumbType and
+ changed Itdb_Image to Itdb_Thumb throughout the source.
+
+ * src/itdb_artwork.c: new file as backend for Itdb_Artwork support
+ (new, free, duplicate, get_thumb_by_type, add_thumbnail,
+ remove_thumbnail, remove_thumbnails), as well as for the
+ Itdb_Thumb support (new, free, duplicate, get_gdk_pixbuf,
+ get_filename)
+
+ * src/itdb_track.c: new functions for artwork support
+ (set_thumbnails, remove_thumbnails)
+
+ * src/ithumb-writer.c: added support to write thumbnails in
+ addition to existing thumbnails
+
+ * src/db-artwork-parcer.c: (mhod3_get_ithmb_filename)
+
+ * src/itdb_itunesdb.c: (update_artwork_info)
+
+ * tests/test-covers.c: updated to new API.
+
+ * tests/test-write-covers.c: updated to new API.
+
+ Known issues: iTunes wipes off our thumbnails.
+
2005-11-24 Jorg Schuler <jcsjcs at users.sourceforge.net>
* overall changes to support itdb_image_get_gdk_pixbuf(). Run
diff --git a/src/Makefile.am b/src/Makefile.am
index 29378ea..dfc0a66 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -2,6 +2,7 @@ lib_LTLIBRARIES = libgpod.la
libgpod_la_SOURCES = \
itdb.h \
+ itdb_artwork.c \
itdb_itunesdb.c \
itdb_playlist.c \
itdb_private.h \
diff --git a/src/db-artwork-parser.c b/src/db-artwork-parser.c
index 8be8be7..fe88b7e 100644
--- a/src/db-artwork-parser.c
+++ b/src/db-artwork-parser.c
@@ -108,28 +108,19 @@ static char *
mhod3_get_ithmb_filename (MhodHeaderArtworkType3 *mhod3,
Itdb_iTunesDB *db)
{
- char *paths[] = {"iPod_Control", "Artwork", NULL, NULL};
char *filename;
- char *result;
g_assert (mhod3 != NULL);
g_assert (db != NULL);
filename = get_utf16_string (mhod3->string, mhod3->string_len);
- if ((filename == NULL) || (strlen (filename) < 2)) {
- return NULL;
- }
-
- paths[2] = filename+1;
- result = itdb_resolve_path (db->mountpoint, (const char **)paths);
- g_free (filename);
- return result;
+ return filename;
}
static int
parse_mhod_3 (DBParseContext *ctx, Itdb_iTunesDB *db,
- Itdb_Image *image, GError *error)
+ Itdb_Thumb *thumb, GError *error)
{
MhodHeader *mhod;
MhodHeaderArtworkType3 *mhod3;
@@ -147,7 +138,7 @@ parse_mhod_3 (DBParseContext *ctx, Itdb_iTunesDB *db,
if ((GINT_FROM_LE (mhod3->type) & 0x00FFFFFF) != MHOD_ARTWORK_TYPE_FILE_NAME) {
return -1;
}
- image->filename = mhod3_get_ithmb_filename (mhod3, db);
+ thumb->filename = mhod3_get_ithmb_filename (mhod3, db);
dump_mhod_type_3 (mhod3);
return 0;
}
@@ -157,7 +148,7 @@ parse_mhni (DBParseContext *ctx, iPodSong *song, GError *error)
{
MhniHeader *mhni;
DBParseContext *mhod_ctx;
- Itdb_Image *thumb;
+ Itdb_Thumb *thumb;
mhni = db_parse_context_get_m_header (ctx, MhniHeader, "mhni");
if (mhni == NULL) {
@@ -168,7 +159,8 @@ parse_mhni (DBParseContext *ctx, iPodSong *song, GError *error)
thumb = ipod_image_new_from_mhni (mhni, song->itdb);
if (thumb != NULL) {
- song->thumbnails = g_list_append (song->thumbnails, thumb);
+ song->artwork->thumbnails =
+ g_list_append (song->artwork->thumbnails, thumb);
}
mhod_ctx = db_parse_context_get_sub_context (ctx, ctx->header_len);
@@ -249,8 +241,8 @@ parse_mhii (DBParseContext *ctx, Itdb_iTunesDB *db, GError *error)
g_warning ("iTunesDB and ArtworkDB artwork sizes don't match (%d %d)", song->artwork_size , GINT_FROM_LE (mhii->orig_img_size));
}
- song->artwork_size = GINT_FROM_LE (mhii->orig_img_size)-1;
- song->image_id = GINT_FROM_LE (mhii->image_id);
+ song->artwork->artwork_size = GINT_FROM_LE (mhii->orig_img_size)-1;
+ song->artwork->id = GINT_FROM_LE (mhii->image_id);
#endif
cur_offset = ctx->header_len;
diff --git a/src/db-artwork-writer.c b/src/db-artwork-writer.c
index 9a6924c..280c2b7 100644
--- a/src/db-artwork-writer.c
+++ b/src/db-artwork-writer.c
@@ -38,6 +38,7 @@
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>
+#include <stdio.h>
#include <sys/types.h>
#define IPOD_MMAP_SIZE 2 * 1024 * 1024
@@ -284,7 +285,7 @@ init_header (iPodBuffer *buffer, gchar header_id[4], guint header_len)
static int
-write_mhod_type_3 (Itdb_Image *image, iPodBuffer *buffer)
+write_mhod_type_3 (Itdb_Thumb *thumb, iPodBuffer *buffer)
{
MhodHeaderArtworkType3 *mhod;
unsigned int total_bytes;
@@ -292,7 +293,7 @@ write_mhod_type_3 (Itdb_Image *image, iPodBuffer *buffer)
gunichar2 *utf16;
int i;
- g_assert (image->filename != NULL);
+ g_assert (thumb->filename != NULL);
mhod = (MhodHeaderArtworkType3 *)init_header (buffer, "mhod",
sizeof (MhodHeaderArtworkType3));
@@ -308,7 +309,7 @@ write_mhod_type_3 (Itdb_Image *image, iPodBuffer *buffer)
mhod->type = GINT_TO_LE (3);
mhod->mhod_version = GINT_TO_LE (2);
- len = strlen (image->filename);
+ len = strlen (thumb->filename);
/* number of bytes of the string encoded in UTF-16 */
mhod->string_len = GINT_TO_LE (2*len);
@@ -317,7 +318,7 @@ write_mhod_type_3 (Itdb_Image *image, iPodBuffer *buffer)
if (ipod_buffer_maybe_grow (buffer, total_bytes + 2*len) != 0) {
return -1;
}
- utf16 = g_utf8_to_utf16 (image->filename, -1, NULL, NULL, NULL);
+ utf16 = g_utf8_to_utf16 (thumb->filename, -1, NULL, NULL, NULL);
if (utf16 == NULL) {
return -1;
}
@@ -335,14 +336,14 @@ write_mhod_type_3 (Itdb_Image *image, iPodBuffer *buffer)
}
static int
-write_mhni (Itdb_Image *image, int correlation_id, iPodBuffer *buffer)
+write_mhni (Itdb_Thumb *thumb, int correlation_id, iPodBuffer *buffer)
{
MhniHeader *mhni;
unsigned int total_bytes;
int bytes_written;
iPodBuffer *sub_buffer;
- if (image == NULL) {
+ if (thumb == NULL) {
return -1;
}
@@ -355,16 +356,16 @@ write_mhni (Itdb_Image *image, int correlation_id, iPodBuffer *buffer)
mhni->total_len = GINT_TO_LE (total_bytes);
mhni->correlation_id = GINT_TO_LE (correlation_id);
- mhni->image_width = GINT16_TO_LE (image->width);
- mhni->image_height = GINT16_TO_LE (image->height);
- mhni->image_size = GINT32_TO_LE (image->size);
- mhni->ithmb_offset = GINT32_TO_LE (image->offset);
+ mhni->image_width = GINT16_TO_LE (thumb->width);
+ mhni->image_height = GINT16_TO_LE (thumb->height);
+ mhni->image_size = GINT32_TO_LE (thumb->size);
+ mhni->ithmb_offset = GINT32_TO_LE (thumb->offset);
sub_buffer = ipod_buffer_get_sub_buffer (buffer, total_bytes);
if (sub_buffer == NULL) {
return -1;
}
- bytes_written = write_mhod_type_3 (image, sub_buffer);
+ bytes_written = write_mhod_type_3 (thumb, sub_buffer);
ipod_buffer_destroy (sub_buffer);
if (bytes_written == -1) {
return -1;
@@ -382,14 +383,14 @@ write_mhni (Itdb_Image *image, int correlation_id, iPodBuffer *buffer)
}
static int
-write_mhod (Itdb_Image *image, int correlation_id, iPodBuffer *buffer)
+write_mhod (Itdb_Thumb *thumb, int correlation_id, iPodBuffer *buffer)
{
MhodHeader *mhod;
unsigned int total_bytes;
int bytes_written;
iPodBuffer *sub_buffer;
- if (image == NULL) {
+ if (thumb == NULL) {
return -1;
}
@@ -405,7 +406,7 @@ write_mhod (Itdb_Image *image, int correlation_id, iPodBuffer *buffer)
if (sub_buffer == NULL) {
return -1;
}
- bytes_written = write_mhni (image, correlation_id, sub_buffer);
+ bytes_written = write_mhni (thumb, correlation_id, sub_buffer);
ipod_buffer_destroy (sub_buffer);
if (bytes_written == -1) {
return -1;
@@ -433,16 +434,16 @@ write_mhii (Itdb_Track *song, iPodBuffer *buffer)
}
total_bytes = GINT_FROM_LE (mhii->header_len);
mhii->song_id = GINT64_TO_LE (song->dbid);
- mhii->image_id = GUINT_TO_LE (song->image_id);
+ mhii->image_id = GUINT_TO_LE (song->artwork->id);
/* Adding 1 to artwork_size since this is what iTunes 4.9 does (there
* is a 1 difference between the artwork size in iTunesDB and the
* artwork size in ArtworkDB)
*/
mhii->orig_img_size = GINT_TO_LE (song->artwork_size)+1;
num_children = 0;
- for (it = song->thumbnails; it != NULL; it = it->next) {
+ for (it = song->artwork->thumbnails; it != NULL; it = it->next) {
iPodBuffer *sub_buffer;
- Itdb_Image *thumb;
+ Itdb_Thumb *thumb;
const IpodArtworkFormat *img_info;
mhii->num_children = GINT_TO_LE (num_children);
@@ -451,12 +452,15 @@ write_mhii (Itdb_Track *song, iPodBuffer *buffer)
if (sub_buffer == NULL) {
return -1;
}
- thumb = (Itdb_Image *)it->data;
+ thumb = (Itdb_Thumb *)it->data;
img_info = ipod_get_artwork_info_from_type (
song->itdb->device, 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,
sub_buffer);
ipod_buffer_destroy (sub_buffer);
@@ -496,7 +500,7 @@ write_mhli (Itdb_iTunesDB *db, iPodBuffer *buffer)
iPodBuffer *sub_buffer;
song = (Itdb_Track*)it->data;
- if (song->image_id == 0) {
+ if (song->artwork->id == 0) {
continue;
}
sub_buffer = ipod_buffer_get_sub_buffer (buffer, total_bytes);
@@ -719,8 +723,8 @@ ipod_artwork_db_set_ids (Itdb_iTunesDB *db)
Itdb_Track *song;
song = (Itdb_Track *)it->data;
- if (song->thumbnails != NULL) {
- song->image_id = id;
+ if (song->artwork->thumbnails != NULL) {
+ song->artwork->id = id;
id++;
}
}
@@ -740,9 +744,9 @@ ipod_write_artwork_db (Itdb_iTunesDB *db)
/* First, let's write the .ithmb files, this will create the various
* thumbnails as well, and update the Itdb_Track items contained in
* the database appropriately (ie set the 'artwork_count' and
- * 'artwork_size' fields, as well as the 2 Itdb_Image fields
+ * 'artwork_size' fields, as well as the 2 Itdb_Thumb fields
*/
- itdb_write_ithumb_files (db, db->mountpoint);
+ itdb_write_ithumb_files (db);
/* Now we can update the ArtworkDB file */
id_max = ipod_artwork_db_set_ids (db);
diff --git a/src/db-image-parser.c b/src/db-image-parser.c
index 372013c..ba4cda5 100644
--- a/src/db-image-parser.c
+++ b/src/db-image-parser.c
@@ -31,155 +31,8 @@
#include "db-artwork-parser.h"
#include "db-image-parser.h"
-#if HAVE_GDKPIXBUF
-#include <gdk-pixbuf/gdk-pixbuf.h>
-#endif
#include <glib/gi18n-lib.h>
-static unsigned char *
-unpack_RGB_565 (gushort *pixels, unsigned int bytes_len)
-{
- unsigned char *result;
- unsigned int i;
-
- result = g_malloc ((bytes_len/2) * 3);
- if (result == NULL) {
- return NULL;
- }
- for (i = 0; i < bytes_len/2; i++) {
- gushort cur_pixel;
-
- cur_pixel = GINT16_FROM_LE (pixels[i]);
- /* Unpack pixels */
- result[3*i] = (cur_pixel & RED_MASK) >> RED_SHIFT;
- result[3*i+1] = (cur_pixel & GREEN_MASK) >> GREEN_SHIFT;
- result[3*i+2] = (cur_pixel & BLUE_MASK) >> BLUE_SHIFT;
-
- /* Normalize color values so that they use a [0..255] range */
- result[3*i] <<= (8 - RED_BITS);
- result[3*i+1] <<= (8 - GREEN_BITS);
- result[3*i+2] <<= (8 - BLUE_BITS);
- }
-
- return result;
-}
-
-
-static unsigned char *
-get_pixel_data (Itdb_Image *image)
-{
- unsigned char *result;
- FILE *f;
- int res;
-
- f = NULL;
- result = g_malloc (image->size);
- if (result == NULL) {
- return NULL;
- }
-
- f = fopen (image->filename, "r");
- if (f == NULL) {
- g_print ("Failed to open %s: %s\n",
- image->filename, strerror (errno));
- goto end;
- }
-
- res = fseek (f, image->offset, SEEK_SET);
- if (res != 0) {
- g_print ("Seek to %d failed on %s: %s\n",
- image->offset, image->filename, strerror (errno));
- goto end;
- }
-
- res = fread (result, image->size, 1, f);
- if (res != 1) {
- g_print ("Failed to read %u bytes from %s: %s\n",
- image->size, image->filename, strerror (errno));
- goto end;
- }
- fclose (f);
-
- return result;
-
- end:
- if (f != NULL) {
- fclose (f);
- }
- g_free (result);
-
- return NULL;
-}
-
-unsigned char *
-itdb_image_get_rgb_data (Itdb_Image *image)
-{
- void *pixels565;
- void *pixels;
-
- pixels565 = get_pixel_data (image);
- if (pixels565 == NULL) {
- return NULL;
- }
-
- pixels = unpack_RGB_565 (pixels565, image->size);
- g_free (pixels565);
-
- return pixels;
-
-}
-
-/* Convert the pixeldata in @image to a GdkPixbuf.
- Since we want to have gdk-pixbuf dependency optional, a generic
- gpointer is returned which you have to cast to (GdkPixbuf *)
- yourself. If gdk-pixbuf is not installed the NULL pointer is
- returned.
- The returned GdkPixbuf must be freed with gdk_pixbuf_unref() after
- use. */
-gpointer
-itdb_image_get_gdk_pixbuf (Itdb_iTunesDB *itdb, Itdb_Image *image)
-{
-#if HAVE_GDKPIXBUF
- GdkPixbuf *result;
- guchar *pixels;
- const IpodArtworkFormat *img_info;
-
- g_return_val_if_fail (itdb, NULL);
- g_return_val_if_fail (image, NULL);
-
- pixels = itdb_image_get_rgb_data (image);
- if (pixels == NULL)
- {
- return NULL;
- }
-
- img_info = ipod_get_artwork_info_from_type (itdb->device,
- image->type);
-
- if (img_info == NULL)
- {
- g_print (_("Unable to obtain image info on image (type: %d, filename: '%s'\n)"), image->type, image->filename);
- g_free (pixels);
- return NULL;
- }
-
- result = gdk_pixbuf_new_from_data (pixels, GDK_COLORSPACE_RGB, FALSE,
- 8, image->width, image->height,
- img_info->width*3,
- (GdkPixbufDestroyNotify)g_free,
- NULL);
-
- /* !! do not g_free(pixels) here: it will be freed when doing a
- * gdk_pixbuf_unref() on the GdkPixbuf !! */
-
- return result;
-#else
- return NULL;
-#endif
-}
-
-
-
static int
image_type_from_corr_id (IpodDevice *ipod, int corr_id)
{
@@ -230,12 +83,12 @@ ipod_get_artwork_info_from_type (IpodDevice *ipod, int image_type)
return formats;
}
-G_GNUC_INTERNAL Itdb_Image *
+G_GNUC_INTERNAL Itdb_Thumb *
ipod_image_new_from_mhni (MhniHeader *mhni, Itdb_iTunesDB *db)
{
- Itdb_Image *img;
- img = g_new0 (Itdb_Image, 1);
+ Itdb_Thumb *img;
+ img = g_new0 (Itdb_Thumb, 1);
if (img == NULL) {
return NULL;
}
@@ -246,8 +99,8 @@ ipod_image_new_from_mhni (MhniHeader *mhni, Itdb_iTunesDB *db)
img->type = image_type_from_corr_id (db->device, mhni->correlation_id);
if ((img->type != IPOD_COVER_SMALL) && (img->type != IPOD_COVER_LARGE)) {
- g_warning ("Unexpected cover type in mhni: %ux%u (%d)\n",
- img->width, img->height, mhni->correlation_id);
+ g_warning ("Unexpected cover type in mhni: type %d, size: %ux%u (%d), offset: %d\n",
+ img->type, img->width, img->height, mhni->correlation_id, img->offset);
g_free (img);
return NULL;
}
diff --git a/src/db-image-parser.h b/src/db-image-parser.h
index 8f3ef1c..3e42c62 100644
--- a/src/db-image-parser.h
+++ b/src/db-image-parser.h
@@ -40,11 +40,10 @@
#define BLUE_SHIFT 0
#define BLUE_MASK (((1 << BLUE_BITS)-1) << BLUE_SHIFT)
-G_GNUC_INTERNAL Itdb_Image *ipod_image_new_from_mhni (MhniHeader *mhni,
+G_GNUC_INTERNAL Itdb_Thumb *ipod_image_new_from_mhni (MhniHeader *mhni,
Itdb_iTunesDB *db);
-G_GNUC_INTERNAL int itdb_write_ithumb_files (Itdb_iTunesDB *db,
- const char *mount_point);
+G_GNUC_INTERNAL int itdb_write_ithumb_files (Itdb_iTunesDB *db);
G_GNUC_INTERNAL const IpodArtworkFormat *ipod_get_artwork_info_from_type (
IpodDevice *ipod, int image_type);
diff --git a/src/itdb.h b/src/itdb.h
index f1a7e61..d91aae0 100644
--- a/src/itdb.h
+++ b/src/itdb.h
@@ -1,4 +1,4 @@
-/* Time-stamp: <2005-11-24 21:34:51 jcs>
+/* Time-stamp: <2005-11-29 00:56:25 jcs>
|
| Copyright (C) 2002-2005 Jorg Schuler <jcsjcs at users sourceforge net>
| Part of the gtkpod project.
@@ -53,9 +53,78 @@ G_BEGIN_DECLS
#define G_GNUC_INTERNAL
#endif
+typedef void (* ItdbUserDataDestroyFunc) (gpointer userdata);
+typedef gpointer (* ItdbUserDataDuplicateFunc) (gpointer userdata);
+
+typedef struct _Itdb_Artwork Itdb_Artwork;
+typedef struct _Itdb_Thumb Itdb_Thumb;
+typedef struct _SPLPref SPLPref;
+typedef struct _SPLRule SPLRule;
+typedef struct _SPLRules SPLRules;
+typedef struct _Itdb_iTunesDB Itdb_iTunesDB;
+typedef struct _Itdb_Playlist Itdb_Playlist;
+typedef struct _Itdb_Track Itdb_Track;
+
+
+/* ------------------------------------------------------------ *\
+ *
+ * Thumbnail-relevant definitions
+ *
+\* ------------------------------------------------------------ */
+
+/* Types of thumbnails in Itdb_Image */
+typedef enum {
+ ITDB_THUMB_COVER_SMALL,
+ ITDB_THUMB_COVER_LARGE,
+ ITDB_THUMB_PHOTO_SMALL,
+ ITDB_THUMB_PHOTO_LARGE,
+ ITDB_THUMB_PHOTO_FULL_SCREEN,
+ ITDB_THUMB_PHOTO_TV_SCREEN
+} ItdbThumbType;
+
+
+/* The Itdb_Thumb structure can represent two slightly different
+ thumbnails:
+
+ - a thumbnail before it's transferred to the iPod.
+
+ offset and size are 0
+
+ width and height, if unequal 0, will indicate the size on the
+ iPod. width and height are set the first time a pixbuf is
+ requested for this thumbnail.
+
+ type is set according to the type this thumbnail represents
+
+ filename point to a 'real' image file.
+
+ - a thumbnail (big or small) stored on a database in the iPod. In
+ these cases, id corresponds to the ID originally used in the
+ database, filename points to a .ithmb file on the iPod
+ */
+struct _Itdb_Thumb {
+ ItdbThumbType type;
+ gchar *filename;
+ guint32 offset;
+ guint32 size;
+ gint16 width;
+ gint16 height;
+};
+
+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
+ * 0x40... libgpod will set this on sync. */
+};
+
+
+/* ------------------------------------------------------------ *\
+ *
+ * Smart Playlists (Rules)
+ *
+\* ------------------------------------------------------------ */
-/* one star is how much (track->rating) */
-#define ITDB_RATING_STEP 20
/* Most of the knowledge about smart playlists has been provided by
Samuel "Otto" Wood (sam dot wood at gmail dot com) who let me dig
@@ -258,7 +327,7 @@ typedef enum {
/* Maximum string length that iTunes writes to the database */
#define SPL_MAXSTRINGLENGTH 255
-typedef struct SPLPref
+struct _SPLPref
{
guint8 liveupdate; /* "live Updating" check box */
guint8 checkrules; /* "Match X of the following
@@ -270,9 +339,9 @@ typedef struct SPLPref
type" */
guint8 matchcheckedonly; /* "Match only checked songs" check
box */
-} SPLPref;
+};
-typedef struct SPLRule
+struct _SPLRule
{
guint32 field;
guint32 action;
@@ -298,47 +367,29 @@ typedef struct SPLRule
guint32 unk060;
guint32 unk064;
guint32 unk068;
-} SPLRule;
+};
-typedef struct SPLRules
+struct _SPLRules
{
guint32 unk004;
guint32 match_operator; /* "All" (logical AND): SPLMATCH_AND,
"Any" (logical OR): SPLMATCH_OR */
GList *rules;
-} SPLRules;
+};
-/* This structure can represent two slightly different images:
+/* ------------------------------------------------------------ *\
+ *
+ * iTunesDB, Playlists, Tracks
+ *
+\* ------------------------------------------------------------ */
- - an image before it's transferred to the iPod (it will then be
- scaled as necessary to generate the 2 thumbnails needed by the
- iPod), for such images, filename points to a 'real' image file,
- offset is not significant, size, width and height may or may not
- be set and id corresponds to the image id to write in mhii
- records of the photo database
-
- - a thumbnail (big or small) stored on a database in the iPod. For
- such images, id isn't significant, filename point to a .ithmb
- file on the iPod
- */
-struct _Itdb_Image {
- int type;
- char *filename;
- guint32 offset;
- guint32 size;
- gint16 width;
- gint16 height;
-};
-
-typedef struct _Itdb_Image Itdb_Image;
-
-typedef void (* ItdbUserDataDestroyFunc) (gpointer userdata);
-typedef gpointer (* ItdbUserDataDuplicateFunc) (gpointer userdata);
+/* one star is how much (track->rating) */
+#define ITDB_RATING_STEP 20
-typedef struct
+struct _Itdb_iTunesDB
{
GList *tracks;
GList *playlists;
@@ -355,10 +406,10 @@ typedef struct
ItdbUserDataDuplicateFunc userdata_duplicate;
/* function called to free userdata */
ItdbUserDataDestroyFunc userdata_destroy;
-} Itdb_iTunesDB;
+};
-typedef struct
+struct _Itdb_Playlist
{
Itdb_iTunesDB *itdb; /* pointer to iTunesDB (for convenience) */
gchar *name; /* name of playlist in UTF8 */
@@ -395,7 +446,7 @@ typedef struct
ItdbUserDataDuplicateFunc userdata_duplicate;
/* function called to free userdata */
ItdbUserDataDestroyFunc userdata_destroy;
-} Itdb_Playlist;
+};
/*
@@ -468,7 +519,7 @@ typedef enum
http://ipodlinux.org/ITunesDB.
http://ipodlinux.org/ITunesDB is the best source for information
about the iTunesDB and related files. */
-typedef struct
+struct _Itdb_Track
{
Itdb_iTunesDB *itdb; /* pointer to iTunesDB (for convenience) */
gchar *title; /* title (utf8) */
@@ -539,13 +590,15 @@ typedef struct
0x4d503320 -> 0x4d = 'M', 0x50 = 'P',
0x33 = '3', 0x20 = <space>. (always
left set to 0 by itdb)*/
- guint16 artwork_count; /* The number of album artwork items
- associated with this song. */
+ guint16 artwork_count; /* The number of album artwork items
+ associated with this song. libgpod
+ updates this value when syncing */
guint32 artwork_size; /* The total size of artwork (in bytes)
attached to this song, when it is
converted to JPEG format. Observed in
iPodDB version 0x0b and with an iPod
- Photo. */
+ Photo. libgpod updates this value when
+ syncing */
float samplerate2; /* The sample rate of the song expressed
as an IEEE 32 bit floating point
number. It's uncertain why this is
@@ -614,9 +667,7 @@ typedef struct
guint32 chapterdata_raw_length;
/* This is for Cover Art support */
- GList *thumbnails;
- unsigned int image_id;
- char *orig_image_filename;
+ struct _Itdb_Artwork *artwork;
/* below is for use by application */
guint64 usertype;
@@ -625,11 +676,16 @@ typedef struct
ItdbUserDataDuplicateFunc userdata_duplicate;
/* function called to free userdata */
ItdbUserDataDestroyFunc userdata_destroy;
-} Itdb_Track;
+};
/* (gtkpod note: don't forget to add fields read from the file to
* copy_new_info() in file.c!) */
-/* Error codes */
+
+/* ------------------------------------------------------------ *\
+ *
+ * Error codes
+ *
+\* ------------------------------------------------------------ */
typedef enum
{
ITDB_FILE_ERROR_SEEK, /* file corrupt: illegal seek occured */
@@ -639,10 +695,18 @@ typedef enum
ITDB_FILE_ERROR_ITDB_CORRUPT /* iTunesDB in memory corrupt */
} ItdbFileError;
+
/* Error domain */
#define ITDB_FILE_ERROR itdb_file_error_quark ()
GQuark itdb_file_error_quark (void);
+
+/* ------------------------------------------------------------ *\
+ *
+ * Public functions
+ *
+\* ------------------------------------------------------------ */
+
/* 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);
@@ -710,7 +774,7 @@ Itdb_Playlist *itdb_playlist_mpl (Itdb_iTunesDB *itdb);
gboolean itdb_playlist_is_mpl (Itdb_Playlist *pl);
void itdb_playlist_set_mpl (Itdb_Playlist *pl);
-/* playlist functions for podcast playlist */
+/* playlist functions for podcasts playlist */
Itdb_Playlist *itdb_playlist_podcasts (Itdb_iTunesDB *itdb);
gboolean itdb_playlist_is_podcasts (Itdb_Playlist *pl);
void itdb_playlist_set_podcasts (Itdb_Playlist *pl);
@@ -730,13 +794,33 @@ void itdb_spl_update_all (Itdb_iTunesDB *itdb);
void itdb_spl_update_live (Itdb_iTunesDB *itdb);
/* thumbnails functions */
-unsigned char *itdb_image_get_rgb_data (Itdb_Image *image);
-int itdb_track_set_thumbnail (Itdb_Track *song, const char *filename);
-void itdb_track_remove_thumbnail (Itdb_Track *song);
-void itdb_track_free_generated_thumbnails (Itdb_Track *track);
+/* itdb_track_... */
+gboolean itdb_track_set_thumbnails (Itdb_Track *track,
+ const gchar *filename);
+void itdb_track_remove_thumbnails (Itdb_Track *track);
+/* itdb_artwork_... */
+Itdb_Artwork *itdb_artwork_new (void);
+Itdb_Artwork *itdb_artwork_duplicate (Itdb_Artwork *artwork);
+void itdb_artwork_free (Itdb_Artwork *artwork);
+Itdb_Thumb *itdb_artwork_get_thumb_by_type (Itdb_Artwork *artwork,
+ ItdbThumbType type);
+gboolean itdb_artwork_add_thumbnail (Itdb_Artwork *artwork,
+ ItdbThumbType type,
+ const gchar *filename);
+void itdb_artwork_remove_thumbnail (Itdb_Artwork *artwork,
+ Itdb_Thumb *thumb);
+void itdb_artwork_remove_thumbnails (Itdb_Artwork *artwork);
+/* itdb_thumb_... */
/* the following funciton returns a pointer to a GdkPixbuf if
gdk-pixbuf is installed -- a NULL pointer otherwise. */
-gpointer itdb_image_get_gdk_pixbuf (Itdb_iTunesDB *itdb, Itdb_Image *image);
+gpointer itdb_thumb_get_gdk_pixbuf (IpodDevice *device,
+ Itdb_Thumb *thumb);
+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 (IpodDevice *device, Itdb_Thumb *thumb);
+
+
/* time functions */
guint64 itdb_time_get_mac_time (void);
time_t itdb_time_mac_to_host (guint64 mactime);
diff --git a/src/itdb_artwork.c b/src/itdb_artwork.c
new file mode 100644
index 0000000..69b432a
--- /dev/null
+++ b/src/itdb_artwork.c
@@ -0,0 +1,429 @@
+/* Time-stamp: <2005-11-29 00:56:32 jcs>
+|
+| Copyright (C) 2002-2005 Jorg Schuler <jcsjcs at users sourceforge net>
+| Part of the gtkpod project.
+|
+| URL: http://www.gtkpod.org/
+| URL: http://gtkpod.sourceforge.net/
+|
+| The code contained in this file is free software; you can redistribute
+| it and/or modify it under the terms of the GNU Lesser General Public
+| License as published by the Free Software Foundation; either version
+| 2.1 of the License, or (at your option) any later version.
+|
+| This file is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+| Lesser General Public License for more details.
+|
+| You should have received a copy of the GNU Lesser General Public
+| License along with this code; if not, write to the Free Software
+| Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+|
+| iTunes and iPod are trademarks of Apple
+|
+| This product is not supported/written/published by Apple!
+|
+| $Id$
+*/
+
+#include <config.h>
+
+#include "itdb_private.h"
+#include "db-image-parser.h"
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#if HAVE_GDKPIXBUF
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#endif
+#include <glib/gi18n-lib.h>
+
+
+Itdb_Artwork *itdb_artwork_new (void)
+{
+ Itdb_Artwork *artwork = g_new0 (Itdb_Artwork, 1);
+ return artwork;
+}
+
+
+void itdb_artwork_free (Itdb_Artwork *artwork)
+{
+ g_return_if_fail (artwork);
+ itdb_artwork_remove_thumbnails (artwork);
+ g_free (artwork);
+}
+
+
+static GList *dup_thumbnails (GList *thumbnails)
+{
+ GList *it;
+ GList *result;
+
+ result = NULL;
+ for (it = thumbnails; it != NULL; it = it->next)
+ {
+ Itdb_Thumb *new_thumb;
+ Itdb_Thumb *thumb;
+
+ thumb = (Itdb_Thumb *)it->data;
+ g_return_val_if_fail (thumb, NULL);
+
+ new_thumb = itdb_thumb_duplicate (thumb);
+
+ result = g_list_prepend (result, new_thumb);
+ }
+
+ return g_list_reverse (result);
+}
+
+Itdb_Artwork *itdb_artwork_duplicate (Itdb_Artwork *artwork)
+{
+ Itdb_Artwork *dup;
+ g_return_val_if_fail (artwork, NULL);
+
+ dup = itdb_artwork_new ();
+ dup->thumbnails = dup_thumbnails (artwork->thumbnails);
+ dup->artwork_size = artwork->artwork_size;
+ dup->id = artwork->id;
+ return dup;
+}
+
+
+/* Remove @thumb in @artwork */
+void
+itdb_artwork_remove_thumbnail (Itdb_Artwork *artwork, Itdb_Thumb *thumb)
+{
+ g_return_if_fail (artwork);
+ g_return_if_fail (thumb);
+
+ artwork->thumbnails = g_list_remove (artwork->thumbnails, thumb);
+}
+
+
+/* Remove all thumbnails in @artwork */
+void
+itdb_artwork_remove_thumbnails (Itdb_Artwork *artwork)
+{
+ g_return_if_fail (artwork);
+
+ while (artwork->thumbnails)
+ {
+ Itdb_Thumb *thumb = artwork->thumbnails->data;
+ g_return_if_fail (thumb);
+ itdb_artwork_remove_thumbnail (artwork, thumb);
+ }
+ artwork->artwork_size = 0;
+ artwork->id = 0;
+}
+
+
+
+
+/* Append thumbnail of type @type to existing thumbnails in @artwork */
+gboolean
+itdb_artwork_add_thumbnail (Itdb_Artwork *artwork,
+ ItdbThumbType type,
+ const char *filename)
+{
+#ifdef HAVE_GDKPIXBUF
+/* This operation doesn't make sense when we can't save thumbnail files */
+ struct stat statbuf;
+ Itdb_Thumb *thumb;
+
+ g_return_val_if_fail (artwork, FALSE);
+ g_return_val_if_fail (filename, FALSE);
+
+ if (g_stat (filename, &statbuf) != 0) {
+ return FALSE;
+ }
+
+ artwork->artwork_size = statbuf.st_size;
+
+ thumb = itdb_thumb_new ();
+ thumb->filename = g_strdup (filename);
+ thumb->type = type;
+ artwork->thumbnails = g_list_append (artwork->thumbnails, thumb);
+
+ return TRUE;
+#else
+ return FALSE;
+#endif
+}
+
+
+/* Return a pointer to the Itdb_Thumb of type @type or NULL when it
+ * does not exist */
+Itdb_Thumb *itdb_artwork_get_thumb_by_type (Itdb_Artwork *artwork,
+ ItdbThumbType type)
+{
+ GList *gl;
+
+ g_return_val_if_fail (artwork, NULL);
+
+ for (gl=artwork->thumbnails; gl; gl=gl->next)
+ {
+ Itdb_Thumb *thumb = gl->data;
+ g_return_val_if_fail (thumb, NULL);
+ if (thumb->type == type) return thumb;
+ }
+ return NULL;
+}
+
+
+/* Get filename of thumbnail. If it's a thumbnail on the iPod, return
+ the full path to the ithmb file. Otherwise return the full path to
+ the original file.
+ g_free() when not needed any more.
+*/
+gchar *itdb_thumb_get_filename (IpodDevice *device, Itdb_Thumb *thumb)
+{
+ gchar *paths[] = {"iPod_Control", "Artwork", NULL, NULL};
+ gchar *filename, *mountpoint;
+
+ g_return_val_if_fail (device, NULL);
+ g_return_val_if_fail (thumb, NULL);
+
+ /* thumbnail not transferred to the iPod */
+ if (thumb->size == 0)
+ return g_strdup (thumb->filename);
+
+ if (strlen (thumb->filename) < 2)
+ {
+ g_print (_("Illegal filename: '%s'.\n"), thumb->filename);
+ return NULL;
+ }
+
+ g_object_get (G_OBJECT (device),
+ "mount-point", &mountpoint,
+ NULL);
+
+ if (!mountpoint)
+ {
+ g_print (_("Mountpoint not set.\n"));
+ return NULL;
+ }
+
+ paths[2] = thumb->filename+1;
+ filename = itdb_resolve_path (mountpoint, (const char **)paths);
+
+ return filename;
+}
+
+
+static guchar *
+unpack_RGB_565 (guint16 *pixels, guint bytes_len)
+{
+ guchar *result;
+ guint i;
+
+ result = g_malloc ((bytes_len/2) * 3);
+ if (result == NULL) {
+ return NULL;
+ }
+ for (i = 0; i < bytes_len/2; i++) {
+ guint16 cur_pixel;
+
+ cur_pixel = GINT16_FROM_LE (pixels[i]);
+ /* Unpack pixels */
+ result[3*i] = (cur_pixel & RED_MASK) >> RED_SHIFT;
+ result[3*i+1] = (cur_pixel & GREEN_MASK) >> GREEN_SHIFT;
+ result[3*i+2] = (cur_pixel & BLUE_MASK) >> BLUE_SHIFT;
+
+ /* Normalize color values so that they use a [0..255] range */
+ result[3*i] <<= (8 - RED_BITS);
+ result[3*i+1] <<= (8 - GREEN_BITS);
+ result[3*i+2] <<= (8 - BLUE_BITS);
+ }
+
+ return result;
+}
+
+
+static guchar *
+get_pixel_data (IpodDevice *device, Itdb_Thumb *thumb)
+{
+ gchar *filename = NULL;
+ guchar *result = NULL;
+ FILE *f = NULL;
+ gint res;
+
+ g_return_val_if_fail (thumb, NULL);
+ g_return_val_if_fail (thumb->filename, NULL);
+
+ result = g_malloc (thumb->size);
+
+ filename = itdb_thumb_get_filename (device, thumb);
+
+ if (!filename)
+ {
+ g_print (_("Could not find on iPod: '%s'\n"),
+ thumb->filename);
+ goto error;
+ }
+
+ f = fopen (filename, "r");
+ if (f == NULL) {
+ g_print ("Failed to open %s: %s\n",
+ filename, strerror (errno));
+ goto error;
+ }
+
+ res = fseek (f, thumb->offset, SEEK_SET);
+ if (res != 0) {
+ g_print ("Seek to %d failed on %s: %s\n",
+ thumb->offset, thumb->filename, strerror (errno));
+ goto error;
+ }
+
+ res = fread (result, thumb->size, 1, f);
+ if (res != 1) {
+ g_print ("Failed to read %u bytes from %s: %s\n",
+ thumb->size, thumb->filename, strerror (errno));
+ goto error;
+ }
+
+ goto cleanup;
+
+ error:
+ g_free (result);
+ result = NULL;
+ cleanup:
+ if (f != NULL) {
+ fclose (f);
+ }
+ g_free (filename);
+
+ return result;
+}
+
+static guchar *
+itdb_thumb_get_rgb_data (IpodDevice *device, Itdb_Thumb *thumb)
+{
+ void *pixels565;
+ guchar *pixels;
+
+ g_return_val_if_fail (device, NULL);
+ g_return_val_if_fail (thumb, NULL);
+
+ /* no rgb pixel data available (FIXME: calculate from real
+ * image file) */
+ if (thumb->size == 0) return NULL;
+
+ pixels565 = get_pixel_data (device, thumb);
+ if (pixels565 == NULL) {
+ return NULL;
+ }
+
+ pixels = unpack_RGB_565 (pixels565, thumb->size);
+ g_free (pixels565);
+
+ return pixels;
+
+}
+
+
+
+/* Convert the pixeldata in @thumb to a GdkPixbuf.
+ Since we want to have gdk-pixbuf dependency optional, a generic
+ gpointer is returned which you have to cast to (GdkPixbuf *)
+ yourself. If gdk-pixbuf is not installed the NULL pointer is
+ returned.
+ The returned GdkPixbuf must be freed with gdk_pixbuf_unref() after
+ use. */
+gpointer
+itdb_thumb_get_gdk_pixbuf (IpodDevice *device, Itdb_Thumb *thumb)
+{
+#if HAVE_GDKPIXBUF
+ GdkPixbuf *pixbuf;
+ guchar *pixels;
+ const IpodArtworkFormat *img_info;
+
+ g_return_val_if_fail (device, NULL);
+ g_return_val_if_fail (thumb, NULL);
+
+ img_info = ipod_get_artwork_info_from_type (device, thumb->type);
+
+ if (img_info == NULL)
+ {
+ g_print (_("Unable to obtain image info on thumb (type: %d, filename: '%s'\n)"), thumb->type, thumb->filename);
+ return NULL;
+ }
+
+ if (thumb->size == 0)
+ { /* pixbuf has not yet been transfered to the iPod */
+ gint width, height;
+
+ pixbuf = gdk_pixbuf_new_from_file_at_size (thumb->filename,
+ img_info->width,
+ img_info->height,
+ NULL);
+ if (!pixbuf)
+ return NULL;
+
+
+ /* !! cannot write directly to &thumb->width/height because
+ g_object_get() returns a gint, but thumb->width/height are
+ gint16 !! */
+ g_object_get (G_OBJECT (pixbuf),
+ "width", &width,
+ "height", &height,
+ NULL);
+
+ thumb->width = width;
+ thumb->height = height;
+
+ return pixbuf;
+ }
+
+ /* pixbuf is already on the iPod -> read from there */
+ pixels = itdb_thumb_get_rgb_data (device, thumb);
+ if (pixels == NULL)
+ {
+ return NULL;
+ }
+
+ pixbuf = gdk_pixbuf_new_from_data (pixels, GDK_COLORSPACE_RGB, FALSE,
+ 8, thumb->width, thumb->height,
+ img_info->width*3,
+ (GdkPixbufDestroyNotify)g_free,
+ NULL);
+
+
+ /* !! do not g_free(pixels) here: it will be freed when doing a
+ * gdk_pixbuf_unref() on the GdkPixbuf !! */
+
+ return pixbuf;
+#else
+ return NULL;
+#endif
+}
+
+
+Itdb_Thumb *itdb_thumb_new (void)
+{
+ Itdb_Thumb *thumb = g_new0 (Itdb_Thumb, 1);
+ return thumb;
+}
+
+
+void itdb_thumb_free (Itdb_Thumb *thumb)
+{
+ g_return_if_fail (thumb);
+
+ g_free (thumb->filename);
+ g_free (thumb);
+}
+
+Itdb_Thumb *itdb_thumb_duplicate (Itdb_Thumb *thumb)
+{
+ Itdb_Thumb *new_thumb;
+
+ g_return_val_if_fail (thumb, NULL);
+
+ new_thumb = itdb_thumb_new ();
+ memcpy (new_thumb, thumb, sizeof (Itdb_Thumb));
+ new_thumb->filename = g_strdup (thumb->filename);
+
+ return new_thumb;
+}
diff --git a/src/itdb_itunesdb.c b/src/itdb_itunesdb.c
index 195321e..a74cf9c 100644
--- a/src/itdb_itunesdb.c
+++ b/src/itdb_itunesdb.c
@@ -1,4 +1,4 @@
-/* Time-stamp: <2005-11-20 16:06:58 jcs>
+/* Time-stamp: <2005-11-27 18:31:02 jcs>
|
| Copyright (C) 2002-2005 Jorg Schuler <jcsjcs at users sourceforge net>
| Part of the gtkpod project.
@@ -2667,6 +2667,25 @@ static void mk_mhlt (FExport *fexp, guint32 num)
}
+static void update_artwork_info (Itdb_Track *track)
+{
+ GList *gl;
+
+ track->artwork_count = 0;
+ /* count the number of valid thumbnails */
+ for (gl=track->artwork->thumbnails; gl; gl=gl->next)
+ {
+ Itdb_Thumb *thumb = gl->data;
+ g_return_if_fail (thumb);
+ if (thumb->size != 0) ++track->artwork_count;
+ }
+ if (track->artwork_count != 0)
+ track->artwork_size = track->artwork->artwork_size;
+ else
+ track->artwork_size = 0;
+}
+
+
/* Write out the mhit header. Size will be written later */
static void mk_mhit (WContents *cts, Itdb_Track *track)
{
@@ -2711,6 +2730,7 @@ static void mk_mhit (WContents *cts, Itdb_Track *track)
else put8int (cts, 0);
put8int (cts, track->app_rating);
put16lint (cts, track->BPM);
+ update_artwork_info (track);
put16lint (cts, track->artwork_count);
put16lint (cts, track->unk126);
put32lint (cts, track->artwork_size);
@@ -3578,6 +3598,10 @@ gboolean itdb_write_file (Itdb_iTunesDB *itdb, const gchar *filename,
if (!filename) filename = itdb->filename;
+#if HAVE_GDKPIXBUF
+ ipod_write_artwork_db (itdb);
+#endif
+
fexp = g_new0 (FExport, 1);
fexp->itdb = itdb;
fexp->itunesdb = wcontents_new (filename);
@@ -3650,9 +3674,6 @@ gboolean itdb_write (Itdb_iTunesDB *itdb, GError **error)
* Errors happening during that operation are considered non fatal since
* they shouldn't corrupt the main database.
*/
-#if HAVE_GDKPIXBUF
- ipod_write_artwork_db (itdb);
-#endif
itunes_path = itdb_resolve_path (itdb->mountpoint, db);
diff --git a/src/itdb_track.c b/src/itdb_track.c
index 66d7b7e..6b0bcf0 100644
--- a/src/itdb_track.c
+++ b/src/itdb_track.c
@@ -1,4 +1,4 @@
-/* Time-stamp: <2005-11-12 22:57:11 jcs>
+/* Time-stamp: <2005-11-28 22:31:30 jcs>
|
| Copyright (C) 2002-2005 Jorg Schuler <jcsjcs at users sourceforge net>
| Part of the gtkpod project.
@@ -50,6 +50,8 @@ Itdb_Track *itdb_track_new (void)
{
Itdb_Track *track = g_new0 (Itdb_Track, 1);
+ track->artwork = itdb_artwork_new ();
+
track->visible = 1;
return track;
}
@@ -79,7 +81,7 @@ static void itdb_track_set_defaults (Itdb_Track *tr)
g_return_if_fail (tr->itdb);
/* The exact meaning of unk126 is unknown, but always seems to be
- 0xffff for MP3/AAC songs, 0x0 for uncompressed songs (like WAVE
+ 0xffff for MP3/AAC tracks, 0x0 for uncompressed tracks (like WAVE
format), 0x1 for Audible. */
if (tr->unk126 == 0)
{
@@ -107,9 +109,9 @@ static void itdb_track_set_defaults (Itdb_Track *tr)
tr->unk126 = 0x00; /* default value */
}
}
- /* The exact meaning of unk144 is unknown, but MP3 songs appear to
+ /* The exact meaning of unk144 is unknown, but MP3 tracks appear to
be always 0x0000000c or 0x0100000c (if played one or more times
- in iTunes), AAC songs are always 0x01000033, Audible files are
+ in iTunes), AAC tracks are always 0x01000033, Audible files are
0x01000029, WAV files are 0x0. */
if (tr->unk144 == 0)
{
@@ -160,7 +162,7 @@ static void itdb_track_set_defaults (Itdb_Track *tr)
}
}
}
- /* The sample rate of the song expressed as an IEEE 32 bit
+ /* The sample rate of the track expressed as an IEEE 32 bit
floating point number. It's uncertain why this is here. itdb
will set this when adding a track */
tr->samplerate2 = tr->samplerate;
@@ -206,22 +208,6 @@ void itdb_track_add (Itdb_iTunesDB *itdb, Itdb_Track *track, gint32 pos)
else itdb->tracks = g_list_insert (itdb->tracks, track, pos);
}
-void
-itdb_track_free_generated_thumbnails (Itdb_Track *track)
-{
- GList *it;
-
- for (it = track->thumbnails; it != NULL; it = it->next) {
- Itdb_Image *image;
-
- image = (Itdb_Image *)it->data;
- g_free (image->filename);
- g_free (image);
- }
- g_list_free (track->thumbnails);
- track->thumbnails = NULL;
-}
-
/* Free the memory taken by @track */
void itdb_track_free (Itdb_Track *track)
{
@@ -242,8 +228,8 @@ void itdb_track_free (Itdb_Track *track)
g_free (track->subtitle);
g_free (track->ipod_path);
g_free (track->chapterdata_raw);
- itdb_track_free_generated_thumbnails (track);
- g_free (track->orig_image_filename);
+ itdb_artwork_remove_thumbnails (track->artwork);
+ g_free (track->artwork);
if (track->userdata && track->userdata_destroy)
(*track->userdata_destroy) (track->userdata);
g_free (track);
@@ -276,30 +262,6 @@ void itdb_track_unlink (Itdb_Track *track)
track->itdb = NULL;
}
-static GList *dup_thumbnails (GList *thumbnails)
-{
- GList *it;
- GList *result;
-
- result = NULL;
- for (it = thumbnails; it != NULL; it = it->next)
- {
- Itdb_Image *new_image;
- Itdb_Image *image;
-
- image = (Itdb_Image *)it->data;
- g_return_val_if_fail (image, NULL);
-
- new_image = g_new (Itdb_Image, 1);
- memcpy (new_image, image, sizeof (Itdb_Image));
- new_image->filename = g_strdup (image->filename);
-
- result = g_list_prepend (result, new_image);
- }
-
- return g_list_reverse (result);
-}
-
/* Duplicate an existing track */
Itdb_Track *itdb_track_duplicate (Itdb_Track *tr)
{
@@ -338,8 +300,7 @@ Itdb_Track *itdb_track_duplicate (Itdb_Track *tr)
}
/* Copy thumbnail data */
- tr_dup->orig_image_filename = g_strdup (tr->orig_image_filename);
- tr_dup->thumbnails = dup_thumbnails (tr->thumbnails);
+ tr_dup->artwork = itdb_artwork_duplicate (tr->artwork);
/* Copy userdata */
if (tr->userdata && tr->userdata_duplicate)
@@ -349,6 +310,35 @@ Itdb_Track *itdb_track_duplicate (Itdb_Track *tr)
}
+gboolean itdb_track_set_thumbnails (Itdb_Track *track,
+ const gchar *filename)
+{
+ gboolean result;
+
+ g_return_val_if_fail (track, FALSE);
+ g_return_val_if_fail (filename, FALSE);
+
+ itdb_artwork_remove_thumbnails (track->artwork);
+ result = itdb_artwork_add_thumbnail (track->artwork,
+ ITDB_THUMB_COVER_SMALL,
+ filename);
+ if (result == TRUE)
+ result = itdb_artwork_add_thumbnail (track->artwork,
+ ITDB_THUMB_COVER_LARGE,
+ filename);
+ if (result == FALSE)
+ itdb_artwork_remove_thumbnails (track->artwork);
+
+ return result;
+}
+
+
+void itdb_track_remove_thumbnails (Itdb_Track *track)
+{
+ g_return_if_fail (track);
+ itdb_artwork_remove_thumbnails (track->artwork);
+}
+
/* Returns the track with the ID @id or NULL if the ID cannot be
* found. */
@@ -419,38 +409,4 @@ Itdb_Track *itdb_track_id_tree_by_id (GTree *idtree, guint32 id)
return (Itdb_Track *)g_tree_lookup (idtree, &id);
}
-void
-itdb_track_remove_thumbnail (Itdb_Track *song)
-{
- itdb_track_free_generated_thumbnails (song);
- g_free (song->orig_image_filename);
- song->orig_image_filename = NULL;
- song->image_id = 0;
-}
-
-#ifdef HAVE_GDKPIXBUF
-/* This operation doesn't make sense when we can't save thumbnail files */
-int
-itdb_track_set_thumbnail (Itdb_Track *song, const char *filename)
-{
- struct stat statbuf;
-
- g_return_val_if_fail (song != NULL, -1);
-
- if (g_stat (filename, &statbuf) != 0) {
- return -1;
- }
- itdb_track_remove_thumbnail (song);
- song->artwork_size = statbuf.st_size;
- song->orig_image_filename = g_strdup (filename);
-
- return 0;
-}
-#else
-int
-itdb_track_set_thumbnail (Itdb_Track *song, const char *filename)
-{
- return -1;
-}
-#endif
diff --git a/src/ithumb-writer.c b/src/ithumb-writer.c
index 075a9dc..7fb3bed 100644
--- a/src/ithumb-writer.c
+++ b/src/ithumb-writer.c
@@ -35,6 +35,12 @@
#include <string.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+
struct _iThumbWriter {
off_t cur_offset;
FILE *f;
@@ -48,11 +54,11 @@ typedef struct _iThumbWriter iThumbWriter;
* here to specify which size we are interested in in case the pixbuf is non
* square
*/
-static gushort *
+static guint16 *
pack_RGB_565 (GdkPixbuf *pixbuf, int dst_width, int dst_height)
{
guchar *pixels;
- gushort *result;
+ guint16 *result;
gint row_stride;
gint channels;
gint width;
@@ -66,9 +72,7 @@ pack_RGB_565 (GdkPixbuf *pixbuf, int dst_width, int dst_height)
"pixels", &pixels, NULL);
g_return_val_if_fail ((width <= dst_width) && (height <= dst_height), NULL);
result = g_malloc0 (dst_width * dst_height * 2);
- if (result == NULL) {
- return NULL;
- }
+
for (h = 0; h < height; h++) {
for (w = 0; w < width; w++) {
gint r;
@@ -92,117 +96,147 @@ pack_RGB_565 (GdkPixbuf *pixbuf, int dst_width, int dst_height)
-static Itdb_Image *
-itdb_image_dup (Itdb_Image *image)
-{
- Itdb_Image *result;
- result = g_new0 (Itdb_Image, 1);
- if (result == NULL) {
- return NULL;
- }
- result->type = image->type;
- result->height = image->height;
- result->width = image->width;
- result->offset = image->offset;
- result->size = image->size;
+static char *
+ipod_image_get_ithmb_filename (const char *mount_point, gint correlation_id)
+{
+ char *paths[] = {"iPod_Control", "Artwork", NULL, NULL};
+ char *filename, *buf;
- return result;
-}
+ buf = g_strdup_printf ("F%04u_1.ithmb", correlation_id);
-static Itdb_Image *
-ithumb_writer_write_thumbnail (iThumbWriter *writer,
- const char *filename)
-{
- GdkPixbuf *thumb;
- gushort *pixels;
- Itdb_Image *image;
+ paths[2] = buf;
- image = g_hash_table_lookup (writer->cache, filename);
- if (image != NULL) {
- return itdb_image_dup (image);
- }
+ filename = itdb_resolve_path (mount_point, (const char **)paths);
- image = g_new0 (Itdb_Image, 1);
- if (image == NULL) {
- return NULL;
+ /* itdb_resolve_path() only returns existing paths */
+ if (!filename)
+ {
+ gchar *path;
+ paths[2] = NULL;
+ path = itdb_resolve_path (mount_point, (const char **)paths);
+ if (path)
+ {
+ filename = g_build_filename (path, buf, NULL);
+ }
+ g_free (path);
}
- thumb = gdk_pixbuf_new_from_file_at_size (filename,
- writer->img_info->width,
- writer->img_info->height,
- NULL);
- if (thumb == NULL) {
- g_free (image);
- return NULL;
- }
- g_object_get (G_OBJECT (thumb),
- "height", &image->height,
- "width", &image->width,
- NULL);
- image->offset = writer->cur_offset;
- image->type = writer->img_info->type;
- image->size = writer->img_info->width * writer->img_info->height * 2;
- /* FIXME: under certain conditions (probably related to writer->offset
- * getting too big), this should be :F%04u_2.ithmb and so on
- */
- image->filename = g_strdup_printf (":F%04u_1.ithmb",
- writer->img_info->correlation_id);
- pixels = pack_RGB_565 (thumb, writer->img_info->width,
- writer->img_info->height);
- g_object_unref (G_OBJECT (thumb));
- if (pixels == NULL) {
- g_free (image);
- return NULL;
- }
- if (fwrite (pixels, image->size, 1, writer->f) != 1) {
- g_free (image);
- g_free (pixels);
- g_print ("Error writing to file: %s\n", strerror (errno));
- return NULL;
- }
- g_free (pixels);
- writer->cur_offset += image->size;
- g_hash_table_insert (writer->cache, g_strdup (filename), image);
+ g_free (buf);
- return image;
+ return filename;
}
-static char *
-ipod_image_get_ithmb_filename (const char *mount_point, gint correlation_id)
+
+static gboolean
+ithumb_writer_write_thumbnail (iThumbWriter *writer,
+ Itdb_Thumb *thumb)
{
- char *paths[] = {"iPod_Control", "Artwork", NULL, NULL};
- char *filename;
+ GdkPixbuf *pixbuf;
+ guint16 *pixels;
+ gchar *filename;
+ gint width, height;
+
+ Itdb_Thumb *old_thumb;
+
+ g_return_val_if_fail (writer, FALSE);
+ g_return_val_if_fail (thumb, FALSE);
+
+ /* If the same filename was written before, just use the old
+ thumbnail to save space on the iPod */
+ old_thumb = g_hash_table_lookup (writer->cache, thumb->filename);
+ if (old_thumb != NULL)
+ {
+ g_free (thumb->filename);
+ memcpy (thumb, old_thumb, sizeof (Itdb_Thumb));
+ thumb->filename = g_strdup (old_thumb->filename);
+ return TRUE;
+ }
+
+ filename = g_strdup (thumb->filename);
+
+ pixbuf = gdk_pixbuf_new_from_file_at_size (filename,
+ writer->img_info->width,
+ writer->img_info->height,
+ NULL);
+ if (pixbuf == NULL) {
+ return FALSE;
+ }
+
+ /* !! cannot write directly to &thumb->width/height because
+ g_object_get() returns a gint, but thumb->width/height are
+ gint16 !! */
+ g_object_get (G_OBJECT (pixbuf),
+ "width", &width,
+ "height", &height,
+ NULL);
+
+ thumb->width = width;
+ 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);
+ g_object_unref (G_OBJECT (pixbuf));
+
+ if (pixels == NULL)
+ {
+ return FALSE;
+ }
+ if (fwrite (pixels, thumb->size, 1, writer->f) != 1) {
+ g_free (pixels);
+ g_print ("Error writing to file: %s\n", strerror (errno));
+ return FALSE;
+ }
+ g_free (pixels);
+ writer->cur_offset += thumb->size;
+ g_hash_table_insert (writer->cache, filename, thumb);
- paths[2] = g_strdup_printf ("F%04u_1.ithmb", correlation_id);
- filename = itdb_resolve_path (mount_point, (const char **)paths);
- g_free (paths[2]);
- return filename;
+ /* !! filename is g_free()d when destroying the hash table. Do not
+ do it here */
+
+ return TRUE;
}
+static void
+write_thumbnail (gpointer _writer, gpointer _artwork)
+{
+ iThumbWriter *writer = _writer;
+ Itdb_Artwork *artwork = _artwork;
+ Itdb_Thumb *thumb;
+
+ thumb = itdb_artwork_get_thumb_by_type (artwork,
+ writer->img_info->type);
+
+ /* size == 0 indicates a thumbnail not yet written to the
+ thumbnail file */
+ if (thumb && (thumb->size == 0))
+ {
+ ithumb_writer_write_thumbnail (writer, thumb);
+ }
+}
static iThumbWriter *
ithumb_writer_new (const char *mount_point, const IpodArtworkFormat *info)
{
char *filename;
iThumbWriter *writer;
+
writer = g_new0 (iThumbWriter, 1);
- if (writer == NULL) {
- return NULL;
- }
+
writer->img_info = g_memdup (info, sizeof (IpodArtworkFormat));
- if (writer->img_info == NULL) {
- g_free (writer);
- return NULL;
- }
+
writer->cache = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, NULL);
- if (writer->cache == NULL) {
- g_free (writer->img_info);
- g_free (writer);
- return NULL;
- }
+
filename = ipod_image_get_ithmb_filename (mount_point,
info->correlation_id);
if (filename == NULL) {
@@ -211,7 +245,7 @@ ithumb_writer_new (const char *mount_point, const IpodArtworkFormat *info)
g_free (writer);
return NULL;
}
- writer->f = fopen (filename, "w");
+ writer->f = fopen (filename, "ab");
if (writer->f == NULL) {
g_print ("Error opening %s: %s\n", filename, strerror (errno));
g_free (filename);
@@ -220,6 +254,7 @@ ithumb_writer_new (const char *mount_point, const IpodArtworkFormat *info)
g_free (writer);
return NULL;
}
+ writer->cur_offset = ftell (writer->f);
g_free (filename);
return writer;
@@ -236,33 +271,222 @@ ithumb_writer_free (iThumbWriter *writer)
}
-static void
-write_thumbnail (gpointer data, gpointer user_data)
+static gboolean ithumb_rearrange_thumbnail_file (gpointer _key,
+ gpointer _thumbs,
+ gpointer _user_data)
{
- iThumbWriter *writer;
- Itdb_Track *song;
- Itdb_Image *thumb;
+ auto gint offset_sort (gconstpointer a, gconstpointer b);
+ gint offset_sort (gconstpointer a, gconstpointer b)
+ {
+ return (((Itdb_Thumb *)a)->offset -
+ ((Itdb_Thumb *)b)->offset);
+ }
+ gchar *filename = _key;
+ GList *thumbs = _thumbs;
+ gboolean *result = _user_data;
+ gint fd = -1;
+ guint32 size = 0;
+ guint32 tnf_num, tn_num, i;
+ GList *gl;
+ struct stat statbuf;
+ void *buf = NULL;
+
+/* printf ("%s: %d\n", filename, g_list_length (thumbs)); */
+
+ /* check if an error occured */
+ if (*result == FALSE)
+ goto out;
+
+ /* check if all thumbnails have the same size */
+ for (gl=thumbs; gl; gl=gl->next)
+ {
+ Itdb_Thumb *img = gl->data;
+
+ if (size == 0)
+ size = img->size;
+ if (size != img->size)
+ {
+ *result = FALSE;
+ goto out;
+ }
+ }
+ /* OK, all thumbs are the same size @size, let's see how many
+ * thumbnails are in the actual file */
+/* printf (" %d\n", size); */
+ if (g_stat (filename, &statbuf) != 0)
+ {
+ *result = FALSE;
+ goto out;
+ }
+ tnf_num = statbuf.st_size / size;
+
+ /* check if the file size is a multiple of @size */
+ if (tnf_num*size != statbuf.st_size)
+ {
+ *result = FALSE;
+ goto out;
+ }
+
+ tn_num = g_list_length (thumbs);
+
+ /* We're finished if the number here and the number of thumbnails
+ * in our list is the same */
+ if (tn_num == tnf_num)
+ goto out;
+
+ fd = open (filename, O_RDWR, 0);
+ if (fd == -1)
+ {
+ *result = FALSE;
+ goto out;
+ }
+
+ /* Performance note: for performance reaons the list should be
+ ordered in reverse order of offsets because of frequent use
+ g_list_last(), and instead of using g_list_nth_data() the list
+ should be crawled by element from the end -- I will do that
+ eventually unless someone beats me to it. */
+
+ /* Sort the list of thumbs according to img->offset */
+ thumbs = g_list_sort (thumbs, offset_sort);
+
+ buf = g_malloc (size);
+
+ for (i=0; i<tn_num; ++i)
+ {
+ guint offset = i * size;
+ Itdb_Thumb *img = g_list_nth_data (thumbs, i);
+ if (offset != img->offset)
+ { /* We found an open space -> copy the last element here */
+ gl = g_list_last (thumbs);
+ img = gl->data;
+ thumbs = g_list_delete_link (thumbs, gl);
+ thumbs = g_list_insert (thumbs, img, i);
+
+ /* actually copy the data */
+ if (lseek (fd, img->offset, SEEK_SET) != img->offset)
+ {
+ *result = FALSE;
+ goto out;
+ }
+ if (read (fd, buf, size) != size)
+ {
+ *result = FALSE;
+ goto out;
+ }
+ if (lseek (fd, offset, SEEK_SET) != offset)
+ {
+ *result = FALSE;
+ goto out;
+ }
+ if (write (fd, buf, size) != size)
+ {
+ *result = FALSE;
+ goto out;
+ }
+
+ img->offset = offset;
+ }
+ }
+ /* truncate the file */
+ if (ftruncate (fd, tn_num*size) == -1)
+ {
+ *result = FALSE;
+ goto out;
+ }
+
+ out:
+ if (fd != -1) close (fd);
+ if (buf) g_free (buf);
+ g_list_free (thumbs);
+ return TRUE;
+}
+
+
+/* The actual image data of thumbnails is not read into memory. As a
+ consequence, writing the thumbnail file is not as straight-forward
+ as e.g. writing the iTunesDB where all data is held in memory.
- song = (Itdb_Track *)user_data;
- writer = (iThumbWriter *)data;
+ To avoid the need to read large amounts from the iPod and back, or
+ have to large files exist on the iPod (reading from the original
+ thumbnail fail and writing to the new thumbnail file), the
+ modifications are done in place.
- thumb = ithumb_writer_write_thumbnail (writer,
- song->orig_image_filename);
- if (thumb != NULL) {
- song->thumbnails = g_list_append (song->thumbnails, thumb);
- song->artwork_count++;
+ It is assumed that all thumbnails have the same data size. If not,
+ FALSE is returned.
+
+ If a thumbnail has been removed, a slot in the file is opened. This
+ slot is filled by copying data from the end of the file and
+ adjusting the corresponding Itdb_Image offset pointer. When all
+ slots are filled, the file is truncated to the new length.
+*/
+static gboolean
+ithmb_rearrange_existing_thumbnails (Itdb_iTunesDB *itdb,
+ const IpodArtworkFormat *info)
+{
+ GList *gl;
+ GHashTable *filenamehash;
+ gboolean result = TRUE;
+
+ g_return_val_if_fail (itdb, FALSE);
+ g_return_val_if_fail (info, FALSE);
+ g_return_val_if_fail (itdb->mountpoint, FALSE);
+
+ filenamehash = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, NULL);
+
+ /* Create a hash with all filenames used for thumbnails.
+ 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))
+ {
+ GList *thumbs;
+ gchar *filename = itdb_thumb_get_filename (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);
+ }
}
+ }
+
+ g_hash_table_foreach_remove (filenamehash,
+ ithumb_rearrange_thumbnail_file, &result);
+ g_hash_table_destroy (filenamehash);
+
+ return result;
}
+#endif
G_GNUC_INTERNAL int
-itdb_write_ithumb_files (Itdb_iTunesDB *db, const char *mount_point)
+itdb_write_ithumb_files (Itdb_iTunesDB *db)
{
+#ifdef HAVE_GDKPIXBUF
GList *writers;
GList *it;
+ gchar *mount_point;
const IpodArtworkFormat *format;
/* g_print ("%s\n", G_GNUC_FUNCTION);*/
+ g_return_val_if_fail (db, -1);
+
+ mount_point = db->mountpoint;
+ /* FIXME: support writing to directory rather than writing to
+ iPod */
+ if (mount_point == NULL)
+ return -1;
if (db->device == NULL) {
return -1;
@@ -281,6 +505,8 @@ itdb_write_ithumb_files (Itdb_iTunesDB *db, const char *mount_point)
switch (format->type) {
case IPOD_COVER_SMALL:
case IPOD_COVER_LARGE:
+ ithmb_rearrange_existing_thumbnails (db,
+ format);
writer = ithumb_writer_new (mount_point, format);
if (writer != NULL) {
writers = g_list_prepend (writers, writer);
@@ -297,26 +523,20 @@ itdb_write_ithumb_files (Itdb_iTunesDB *db, const char *mount_point)
}
for (it = db->tracks; it != NULL; it = it->next) {
- Itdb_Track *song;
+ Itdb_Track *track;
- song = (Itdb_Track *)it->data;
- song->artwork_count = 0;
- itdb_track_free_generated_thumbnails (song);
- if (song->orig_image_filename == NULL) {
- continue;
- }
- g_list_foreach (writers, write_thumbnail, song);
+ track = it->data;
+ g_return_val_if_fail (track, -1);
+ track->artwork_count = 0;
+
+ g_list_foreach (writers, write_thumbnail, track->artwork);
}
g_list_foreach (writers, (GFunc)ithumb_writer_free, NULL);
g_list_free (writers);
return 0;
-}
#else
-G_GNUC_INTERNAL int
-itdb_write_ithumb_files (Itdb_iTunesDB *db, const char *mount_point)
-{
return -1;
-}
#endif
+}
diff --git a/tests/test-covers.c b/tests/test-covers.c
index 5816ce2..0a79cff 100644
--- a/tests/test-covers.c
+++ b/tests/test-covers.c
@@ -33,14 +33,14 @@
static void
-save_itdb_image (Itdb_iTunesDB *itdb, Itdb_Image *image, const char *filename)
+save_itdb_thumb (Itdb_iTunesDB *itdb, Itdb_Thumb *thumb, const char *filename)
{
- GdkPixbuf *thumb;
+ GdkPixbuf *pixbuf;
- thumb = itdb_image_get_gdk_pixbuf (itdb, image);
- if (thumb != NULL) {
- gdk_pixbuf_save (thumb, filename, "png", NULL, NULL);
- gdk_pixbuf_unref (thumb);
+ pixbuf = itdb_thumb_get_gdk_pixbuf (itdb->device, thumb);
+ if (pixbuf != NULL) {
+ gdk_pixbuf_save (pixbuf, filename, "png", NULL, NULL);
+ gdk_pixbuf_unref (pixbuf);
/* g_print ("Saved %s\n", filename); */
}
}
@@ -49,20 +49,20 @@ save_song_thumbnails (Itdb_Track *song)
{
GList *it;
- for (it = song->thumbnails; it != NULL; it = it->next) {
- Itdb_Image *image;
+ for (it = song->artwork->thumbnails; it != NULL; it = it->next) {
+ Itdb_Thumb *thumb;
gchar *filename;
- image = (Itdb_Image *)it->data;
- g_return_if_fail (image);
+ thumb = (Itdb_Thumb *)it->data;
+ g_return_if_fail (thumb);
filename = NULL;
filename = g_strdup_printf ("%s-%s-%s-%d-%016"G_GINT64_MODIFIER"x.png",
song->artist, song->album,
- song->title, image->type,
+ song->title, thumb->type,
song->dbid);
if (filename != NULL) {
- save_itdb_image (song->itdb, image, filename);
+ save_itdb_thumb (song->itdb, thumb, filename);
g_free (filename);
}
}
diff --git a/tests/test-write-covers.c b/tests/test-write-covers.c
index 88c0216..dab7fc0 100644
--- a/tests/test-write-covers.c
+++ b/tests/test-write-covers.c
@@ -97,11 +97,11 @@ main (int argc, char **argv)
const char *coverpath;
song = (Itdb_Track*)it->data;
- itdb_track_remove_thumbnail (song);
+ itdb_artwork_remove_thumbnails (song->artwork);
coverpath = g_list_nth_data (covers,
g_random_int_range (0, nb_covers));
- itdb_track_set_thumbnail (song, coverpath);
+ itdb_track_set_thumbnails (song, coverpath);
/* g_print ("%s - %s - %s gets %s\n",
song->artist, song->album, song->title, coverpath);*/